mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
views created + database storage
This commit is contained in:
parent
d98cef3c77
commit
b2a924ebf8
@ -87,15 +87,17 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
|||||||
Collections.synchronizedMap(new LRUCache<String, SoftReference<MessageRecord>>(MAX_CACHE_SIZE));
|
Collections.synchronizedMap(new LRUCache<String, SoftReference<MessageRecord>>(MAX_CACHE_SIZE));
|
||||||
private final SparseArray<String> positionToCacheRef = new SparseArray<>();
|
private final SparseArray<String> positionToCacheRef = new SparseArray<>();
|
||||||
|
|
||||||
private static final int MESSAGE_TYPE_OUTGOING = 0;
|
private static final int MESSAGE_TYPE_OUTGOING = 0;
|
||||||
private static final int MESSAGE_TYPE_INCOMING = 1;
|
private static final int MESSAGE_TYPE_INCOMING = 1;
|
||||||
private static final int MESSAGE_TYPE_UPDATE = 2;
|
private static final int MESSAGE_TYPE_UPDATE = 2;
|
||||||
private static final int MESSAGE_TYPE_AUDIO_OUTGOING = 3;
|
private static final int MESSAGE_TYPE_AUDIO_OUTGOING = 3;
|
||||||
private static final int MESSAGE_TYPE_AUDIO_INCOMING = 4;
|
private static final int MESSAGE_TYPE_AUDIO_INCOMING = 4;
|
||||||
private static final int MESSAGE_TYPE_THUMBNAIL_OUTGOING = 5;
|
private static final int MESSAGE_TYPE_THUMBNAIL_OUTGOING = 5;
|
||||||
private static final int MESSAGE_TYPE_THUMBNAIL_INCOMING = 6;
|
private static final int MESSAGE_TYPE_THUMBNAIL_INCOMING = 6;
|
||||||
private static final int MESSAGE_TYPE_DOCUMENT_OUTGOING = 7;
|
private static final int MESSAGE_TYPE_DOCUMENT_OUTGOING = 7;
|
||||||
private static final int MESSAGE_TYPE_DOCUMENT_INCOMING = 8;
|
private static final int MESSAGE_TYPE_DOCUMENT_INCOMING = 8;
|
||||||
|
private static final int MESSAGE_TYPE_INVITATION_OUTGOING = 9;
|
||||||
|
private static final int MESSAGE_TYPE_INVITATION_INCOMING = 10;
|
||||||
|
|
||||||
private final Set<MessageRecord> batchSelected = Collections.synchronizedSet(new HashSet<MessageRecord>());
|
private final Set<MessageRecord> batchSelected = Collections.synchronizedSet(new HashSet<MessageRecord>());
|
||||||
|
|
||||||
@ -281,10 +283,12 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
|||||||
case MESSAGE_TYPE_AUDIO_OUTGOING:
|
case MESSAGE_TYPE_AUDIO_OUTGOING:
|
||||||
case MESSAGE_TYPE_THUMBNAIL_OUTGOING:
|
case MESSAGE_TYPE_THUMBNAIL_OUTGOING:
|
||||||
case MESSAGE_TYPE_DOCUMENT_OUTGOING:
|
case MESSAGE_TYPE_DOCUMENT_OUTGOING:
|
||||||
|
case MESSAGE_TYPE_INVITATION_OUTGOING:
|
||||||
case MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent;
|
case MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent;
|
||||||
case MESSAGE_TYPE_AUDIO_INCOMING:
|
case MESSAGE_TYPE_AUDIO_INCOMING:
|
||||||
case MESSAGE_TYPE_THUMBNAIL_INCOMING:
|
case MESSAGE_TYPE_THUMBNAIL_INCOMING:
|
||||||
case MESSAGE_TYPE_DOCUMENT_INCOMING:
|
case MESSAGE_TYPE_DOCUMENT_INCOMING:
|
||||||
|
case MESSAGE_TYPE_INVITATION_INCOMING:
|
||||||
case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received;
|
case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received;
|
||||||
case MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update;
|
case MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update;
|
||||||
default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter");
|
default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter");
|
||||||
@ -295,6 +299,9 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
|||||||
public int getItemViewType(@NonNull MessageRecord messageRecord) {
|
public int getItemViewType(@NonNull MessageRecord messageRecord) {
|
||||||
if (messageRecord.isUpdate()) {
|
if (messageRecord.isUpdate()) {
|
||||||
return MESSAGE_TYPE_UPDATE;
|
return MESSAGE_TYPE_UPDATE;
|
||||||
|
} else if (messageRecord.isOpenGroupInvitation()) {
|
||||||
|
if (messageRecord.isOutgoing()) return MESSAGE_TYPE_INVITATION_OUTGOING;
|
||||||
|
else return MESSAGE_TYPE_INVITATION_INCOMING;
|
||||||
} else if (hasAudio(messageRecord)) {
|
} else if (hasAudio(messageRecord)) {
|
||||||
if (messageRecord.isOutgoing()) return MESSAGE_TYPE_AUDIO_OUTGOING;
|
if (messageRecord.isOutgoing()) return MESSAGE_TYPE_AUDIO_OUTGOING;
|
||||||
else return MESSAGE_TYPE_AUDIO_INCOMING;
|
else return MESSAGE_TYPE_AUDIO_INCOMING;
|
||||||
|
@ -63,7 +63,9 @@ import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAt
|
|||||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener;
|
||||||
|
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
|
import org.session.libsession.utilities.OpenGroupUrlParser;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.ThemeUtil;
|
import org.session.libsession.utilities.ThemeUtil;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
@ -92,6 +94,7 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
|||||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities;
|
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities;
|
||||||
import org.thoughtcrime.securesms.loki.views.MessageAudioView;
|
import org.thoughtcrime.securesms.loki.views.MessageAudioView;
|
||||||
|
import org.thoughtcrime.securesms.loki.views.OpenGroupInvitationView;
|
||||||
import org.thoughtcrime.securesms.loki.views.ProfilePictureView;
|
import org.thoughtcrime.securesms.loki.views.ProfilePictureView;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
@ -156,6 +159,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
private Stub<DocumentView> documentViewStub;
|
private Stub<DocumentView> documentViewStub;
|
||||||
private Stub<LinkPreviewView> linkPreviewStub;
|
private Stub<LinkPreviewView> linkPreviewStub;
|
||||||
private Stub<StickerView> stickerStub;
|
private Stub<StickerView> stickerStub;
|
||||||
|
private Stub<OpenGroupInvitationView> openGroupInvitationViewStub;
|
||||||
private @Nullable EventListener eventListener;
|
private @Nullable EventListener eventListener;
|
||||||
|
|
||||||
private int defaultBubbleColor;
|
private int defaultBubbleColor;
|
||||||
@ -203,6 +207,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
this.documentViewStub = new Stub<>(findViewById(R.id.document_view_stub));
|
this.documentViewStub = new Stub<>(findViewById(R.id.document_view_stub));
|
||||||
this.linkPreviewStub = new Stub<>(findViewById(R.id.link_preview_stub));
|
this.linkPreviewStub = new Stub<>(findViewById(R.id.link_preview_stub));
|
||||||
this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub));
|
this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub));
|
||||||
|
this.openGroupInvitationViewStub = new Stub<>(findViewById(R.id.open_group_invitation_stub));
|
||||||
this.groupSenderHolder = findViewById(R.id.group_sender_holder);
|
this.groupSenderHolder = findViewById(R.id.group_sender_holder);
|
||||||
this.quoteView = findViewById(R.id.quote_view);
|
this.quoteView = findViewById(R.id.quote_view);
|
||||||
this.container = findViewById(R.id.container);
|
this.container = findViewById(R.id.container);
|
||||||
@ -467,7 +472,9 @@ public class ConversationItem extends LinearLayout
|
|||||||
bodyText.setOverflowText(null);
|
bodyText.setOverflowText(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyText.setText(text);
|
if (!messageRecord.isOpenGroupInvitation())
|
||||||
|
bodyText.setText(text);
|
||||||
|
|
||||||
bodyText.setVisibility(View.VISIBLE);
|
bodyText.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -528,6 +535,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
||||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||||
|
if (openGroupInvitationViewStub.resolved()) openGroupInvitationViewStub.get().setVisibility(View.GONE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
|
||||||
@ -564,6 +572,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||||
|
if (openGroupInvitationViewStub.resolved()) openGroupInvitationViewStub.get().setVisibility(View.GONE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
audioViewStub.get().setAudio(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls);
|
audioViewStub.get().setAudio(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls);
|
||||||
@ -580,6 +589,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
||||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||||
|
if (openGroupInvitationViewStub.resolved()) openGroupInvitationViewStub.get().setVisibility(View.GONE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
documentViewStub.get().setDocument(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getDocumentSlide(), showControls);
|
documentViewStub.get().setDocument(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getDocumentSlide(), showControls);
|
||||||
@ -597,6 +607,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||||
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||||
|
if (openGroupInvitationViewStub.resolved()) openGroupInvitationViewStub.get().setVisibility(View.GONE);
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
List<Slide> thumbnailSlides = ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlides();
|
List<Slide> thumbnailSlides = ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlides();
|
||||||
@ -619,6 +630,29 @@ public class ConversationItem extends LinearLayout
|
|||||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
|
||||||
footer.setVisibility(VISIBLE);
|
footer.setVisibility(VISIBLE);
|
||||||
|
} else if (messageRecord.isOpenGroupInvitation()) {
|
||||||
|
openGroupInvitationViewStub.get().setVisibility(View.VISIBLE);
|
||||||
|
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
||||||
|
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
||||||
|
if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE);
|
||||||
|
if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE);
|
||||||
|
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||||
|
|
||||||
|
UpdateMessageData updateMessageData = UpdateMessageData.Companion.fromJSON(messageRecord.getBody());
|
||||||
|
String name = null, url = null;
|
||||||
|
if (updateMessageData.getKind() instanceof UpdateMessageData.Kind.OpenGroupInvitation) {
|
||||||
|
UpdateMessageData.Kind.OpenGroupInvitation data = (UpdateMessageData.Kind.OpenGroupInvitation)updateMessageData.getKind();
|
||||||
|
name = data.getGroupName();
|
||||||
|
url = OpenGroupUrlParser.INSTANCE.trimParameter(data.getGroupUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
openGroupInvitationViewStub.get().setOpenGroup(name, url, messageRecord.isOutgoing());
|
||||||
|
openGroupInvitationViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||||
|
|
||||||
|
bodyText.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
} else {
|
} else {
|
||||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
|
||||||
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
|
||||||
|
@ -47,13 +47,15 @@ public interface MmsSmsColumns {
|
|||||||
BASE_PENDING_INSECURE_SMS_FALLBACK,
|
BASE_PENDING_INSECURE_SMS_FALLBACK,
|
||||||
OUTGOING_CALL_TYPE};
|
OUTGOING_CALL_TYPE};
|
||||||
|
|
||||||
|
|
||||||
|
//TODO clean unused keys
|
||||||
// Message attributes
|
// Message attributes
|
||||||
protected static final long MESSAGE_FORCE_SMS_BIT = 0x40;
|
protected static final long MESSAGE_FORCE_SMS_BIT = 0x40;
|
||||||
|
|
||||||
// Key Exchange Information
|
// Key Exchange Information
|
||||||
protected static final long KEY_EXCHANGE_MASK = 0xFF00;
|
protected static final long KEY_EXCHANGE_MASK = 0xFF00;
|
||||||
protected static final long KEY_EXCHANGE_BIT = 0x8000;
|
protected static final long KEY_EXCHANGE_BIT = 0x8000;
|
||||||
protected static final long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x4000;
|
protected static final long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x40000;
|
||||||
protected static final long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000;
|
protected static final long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000;
|
||||||
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
protected static final long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000;
|
||||||
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
protected static final long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800;
|
||||||
@ -75,6 +77,8 @@ public interface MmsSmsColumns {
|
|||||||
// Data Extraction Information
|
// Data Extraction Information
|
||||||
protected static final long MEDIA_SAVED_EXTRACTION_BIT = 0x01000;
|
protected static final long MEDIA_SAVED_EXTRACTION_BIT = 0x01000;
|
||||||
protected static final long SCREENSHOT_EXTRACTION_BIT = 0x02000;
|
protected static final long SCREENSHOT_EXTRACTION_BIT = 0x02000;
|
||||||
|
// Open Group Invitation
|
||||||
|
protected static final long OPEN_GROUP_INVITATION_BIT = 0x04000;
|
||||||
|
|
||||||
// Encrypted Storage Information XXX
|
// Encrypted Storage Information XXX
|
||||||
public static final long ENCRYPTION_MASK = 0xFF000000;
|
public static final long ENCRYPTION_MASK = 0xFF000000;
|
||||||
@ -210,6 +214,10 @@ public interface MmsSmsColumns {
|
|||||||
return (type & SCREENSHOT_EXTRACTION_BIT) != 0;
|
return (type & SCREENSHOT_EXTRACTION_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOpenGroupInvitation(long type) {
|
||||||
|
return (type & OPEN_GROUP_INVITATION_BIT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isIncomingCall(long type) {
|
public static boolean isIncomingCall(long type) {
|
||||||
return type == INCOMING_CALL_TYPE;
|
return type == INCOMING_CALL_TYPE;
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,9 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
if (((IncomingGroupMessage)message).isUpdateMessage()) type |= Types.GROUP_UPDATE_MESSAGE_BIT;
|
if (((IncomingGroupMessage)message).isUpdateMessage()) type |= Types.GROUP_UPDATE_MESSAGE_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.isPush()) type |= Types.PUSH_MESSAGE_BIT;
|
if (message.isPush()) type |= Types.PUSH_MESSAGE_BIT;
|
||||||
|
|
||||||
|
if (message.isOpenGroupInvitation()) type |= Types.OPEN_GROUP_INVITATION_BIT;
|
||||||
|
|
||||||
Recipient recipient = Recipient.from(context, message.getSender(), true);
|
Recipient recipient = Recipient.from(context, message.getSender(), true);
|
||||||
|
|
||||||
@ -443,8 +445,9 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
{
|
{
|
||||||
long type = Types.BASE_SENDING_TYPE;
|
long type = Types.BASE_SENDING_TYPE;
|
||||||
|
|
||||||
if (message.isSecureMessage()) type |= (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT);
|
if (message.isSecureMessage()) type |= (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT);
|
||||||
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
||||||
|
if (message.isOpenGroupInvitation()) type |= Types.OPEN_GROUP_INVITATION_BIT;
|
||||||
|
|
||||||
Address address = message.getRecipient().getAddress();
|
Address address = message.getRecipient().getAddress();
|
||||||
Map<Address, Long> earlyDeliveryReceipts = earlyDeliveryReceiptCache.remove(date);
|
Map<Address, Long> earlyDeliveryReceipts = earlyDeliveryReceiptCache.remove(date);
|
||||||
|
@ -24,7 +24,7 @@ import org.session.libsession.messaging.threads.Address
|
|||||||
import org.session.libsession.messaging.threads.Address.Companion.fromSerialized
|
import org.session.libsession.messaging.threads.Address.Companion.fromSerialized
|
||||||
import org.session.libsession.messaging.threads.GroupRecord
|
import org.session.libsession.messaging.threads.GroupRecord
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageData
|
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.IdentityKeyUtil
|
import org.session.libsession.utilities.IdentityKeyUtil
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
@ -165,11 +165,15 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
mmsDatabase.endTransaction()
|
mmsDatabase.endTransaction()
|
||||||
} else {
|
} else {
|
||||||
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
|
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
|
||||||
|
val isOpenGroupInvitation = message.openGroupInvitation != null
|
||||||
|
|
||||||
val insertResult = if (message.sender == getUserPublicKey()) {
|
val insertResult = if (message.sender == getUserPublicKey()) {
|
||||||
val textMessage = OutgoingTextMessage.from(message, targetRecipient)
|
val textMessage = if (isOpenGroupInvitation) OutgoingTextMessage.fromOpenGroupInvitation(message.openGroupInvitation, targetRecipient, message.sentTimestamp)
|
||||||
|
else OutgoingTextMessage.from(message, targetRecipient)
|
||||||
smsDatabase.insertMessageOutbox(message.threadID ?: -1, textMessage, message.sentTimestamp!!)
|
smsDatabase.insertMessageOutbox(message.threadID ?: -1, textMessage, message.sentTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
val textMessage = IncomingTextMessage.from(message, senderAddress, group, targetRecipient.expireMessages * 1000L)
|
val textMessage = if (isOpenGroupInvitation) IncomingTextMessage.fromOpenGroupInvitation(message.openGroupInvitation, senderAddress, message.sentTimestamp)
|
||||||
|
else IncomingTextMessage.from(message, senderAddress, group, targetRecipient.expireMessages * 1000L)
|
||||||
val encrypted = IncomingEncryptedMessage(textMessage, textMessage.messageBody)
|
val encrypted = IncomingEncryptedMessage(textMessage, textMessage.messageBody)
|
||||||
smsDatabase.insertMessageInbox(encrypted, message.receivedTimestamp ?: 0)
|
smsDatabase.insertMessageInbox(encrypted, message.receivedTimestamp ?: 0)
|
||||||
}
|
}
|
||||||
@ -475,7 +479,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
|
override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long) {
|
||||||
val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList())
|
||||||
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
|
val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true)
|
||||||
val updateData = ClosedGroupUpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
|
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
|
||||||
val infoMessage = IncomingGroupMessage(m, groupID, updateData, true)
|
val infoMessage = IncomingGroupMessage(m, groupID, updateData, true)
|
||||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||||
smsDB.insertMessageInbox(infoMessage)
|
smsDB.insertMessageInbox(infoMessage)
|
||||||
@ -485,7 +489,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
val userPublicKey = getUserPublicKey()
|
val userPublicKey = getUserPublicKey()
|
||||||
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
val recipient = Recipient.from(context, Address.fromSerialized(groupID), false)
|
||||||
|
|
||||||
val updateData = ClosedGroupUpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON() ?: ""
|
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON() ?: ""
|
||||||
val infoMessage = OutgoingGroupMediaMessage(recipient, updateData, groupID, null, sentTimestamp, 0, true, null, listOf(), listOf())
|
val infoMessage = OutgoingGroupMediaMessage(recipient, updateData, groupID, null, sentTimestamp, 0, true, null, listOf(), listOf())
|
||||||
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
val mmsDB = DatabaseFactory.getMmsDatabase(context)
|
||||||
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context)
|
||||||
|
@ -145,6 +145,12 @@ public abstract class DisplayRecord {
|
|||||||
return isMediaSavedExtraction() || isScreenshotExtraction();
|
return isMediaSavedExtraction() || isScreenshotExtraction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open Group Invitation
|
||||||
|
|
||||||
|
public boolean isOpenGroupInvitation() {
|
||||||
|
return MmsSmsColumns.Types.isOpenGroupInvitation(type);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isCallLog() {
|
public boolean isCallLog() {
|
||||||
return SmsDatabase.Types.isCallLog(type);
|
return SmsDatabase.Types.isCallLog(type);
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ import android.text.style.StyleSpan;
|
|||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage;
|
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage;
|
||||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageBuilder;
|
import org.session.libsession.messaging.utilities.UpdateMessageBuilder;
|
||||||
import org.session.libsession.messaging.utilities.ClosedGroupUpdateMessageData;
|
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
import org.session.libsession.database.documents.IdentityKeyMismatch;
|
||||||
@ -93,14 +93,14 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
@Override
|
@Override
|
||||||
public SpannableString getDisplayBody(@NonNull Context context) {
|
public SpannableString getDisplayBody(@NonNull Context context) {
|
||||||
if(isGroupUpdateMessage()) {
|
if(isGroupUpdateMessage()) {
|
||||||
ClosedGroupUpdateMessageData updateMessageData = ClosedGroupUpdateMessageData.Companion.fromJSON(getBody());
|
UpdateMessageData updateMessageData = UpdateMessageData.Companion.fromJSON(getBody());
|
||||||
return new SpannableString(ClosedGroupUpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||||
} else if (isExpirationTimerUpdate()) {
|
} else if (isExpirationTimerUpdate()) {
|
||||||
int seconds = (int) (getExpiresIn() / 1000);
|
int seconds = (int) (getExpiresIn() / 1000);
|
||||||
return new SpannableString(ClosedGroupUpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
|
||||||
} else if (isDataExtraction()) {
|
} else if (isDataExtraction()) {
|
||||||
if (isScreenshotExtraction()) return new SpannableString((ClosedGroupUpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
if (isScreenshotExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
|
||||||
else if (isMediaSavedExtraction()) return new SpannableString((ClosedGroupUpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));
|
else if (isMediaSavedExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));
|
||||||
}
|
}
|
||||||
// TODO below lines are left here for compatibility with older group update messages, it can be deleted later on
|
// TODO below lines are left here for compatibility with older group update messages, it can be deleted later on
|
||||||
else if (isGroupUpdate() && isOutgoing()) {
|
else if (isGroupUpdate() && isOutgoing()) {
|
||||||
|
@ -121,7 +121,7 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("JoinPublicChatActivity", "Fialed to join open group.", e)
|
Log.e("JoinPublicChatActivity", "Failed to join open group.", e)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
hideLoader()
|
hideLoader()
|
||||||
Toast.makeText(this@JoinPublicChatActivity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this@JoinPublicChatActivity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsignal.utilities.logging.Log
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class OpenGroupInvitationView : FrameLayout {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "OpenGroupInvitationView"
|
||||||
|
}
|
||||||
|
|
||||||
|
private val joinButton: ImageView
|
||||||
|
private val openGroupIcon: ImageView
|
||||||
|
private val groupName: TextView
|
||||||
|
private val groupUrl: TextView
|
||||||
|
|
||||||
|
constructor(context: Context): this(context, null)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0)
|
||||||
|
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr) {
|
||||||
|
View.inflate(context, R.layout.open_group_invitation_view, this)
|
||||||
|
joinButton = findViewById(R.id.join_open_group)
|
||||||
|
openGroupIcon = findViewById(R.id.open_group_icon)
|
||||||
|
groupName = findViewById(R.id.group_name)
|
||||||
|
groupUrl = findViewById(R.id.group_url)
|
||||||
|
|
||||||
|
joinButton.setOnClickListener { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOpenGroup(name: String, url: String, isOutgoing: Boolean = false) {
|
||||||
|
groupName.text = name
|
||||||
|
groupUrl.text = url
|
||||||
|
|
||||||
|
if(isOutgoing) {
|
||||||
|
joinButton.visibility = View.GONE
|
||||||
|
openGroupIcon.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
joinButton.visibility = View.VISIBLE
|
||||||
|
openGroupIcon.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun joinPublicGroup(url: String) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -140,6 +140,12 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout="@layout/conversation_item_received_link_preview" />
|
android:layout="@layout/conversation_item_received_link_preview" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/open_group_invitation_stub"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout="@layout/conversation_item_received_open_group_invitation" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/audio_view_stub"
|
android:id="@+id/audio_view_stub"
|
||||||
android:layout="@layout/conversation_item_received_audio"
|
android:layout="@layout/conversation_item_received_audio"
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.thoughtcrime.securesms.loki.views.OpenGroupInvitationView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/open_group_invitation_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
@ -50,13 +50,13 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/large_spacing"
|
android:layout_marginStart="@dimen/large_spacing"
|
||||||
android:layout_marginBottom="@dimen/medium_spacing"
|
|
||||||
android:layout_marginEnd="@dimen/large_spacing"
|
android:layout_marginEnd="@dimen/large_spacing"
|
||||||
|
android:layout_marginBottom="@dimen/medium_spacing"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:message_type="outgoing"
|
app:message_type="outgoing"
|
||||||
app:quote_colorPrimary="@color/text"
|
app:quote_colorPrimary="@color/text"
|
||||||
app:quote_colorSecondary="@color/text"
|
app:quote_colorSecondary="@color/text"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/image_view_stub"
|
android:id="@+id/image_view_stub"
|
||||||
@ -76,6 +76,12 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout="@layout/conversation_item_sent_link_preview" />
|
android:layout="@layout/conversation_item_sent_link_preview" />
|
||||||
|
|
||||||
|
<ViewStub
|
||||||
|
android:id="@+id/open_group_invitation_stub"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout="@layout/conversation_item_sent_open_group_invitation" />
|
||||||
|
|
||||||
<ViewStub
|
<ViewStub
|
||||||
android:id="@+id/audio_view_stub"
|
android:id="@+id/audio_view_stub"
|
||||||
android:layout="@layout/conversation_item_sent_audio"
|
android:layout="@layout/conversation_item_sent_audio"
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.thoughtcrime.securesms.loki.views.OpenGroupInvitationView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/open_group_invitation_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
73
app/src/main/res/layout/open_group_invitation_view.xml
Normal file
73
app/src/main/res/layout/open_group_invitation_view.xml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context="org.thoughtcrime.securesms.loki.views.OpenGroupInvitationView">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/audio_widget_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="8dp"
|
||||||
|
tools:ignore="MissingConstraints" >
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/join_open_group"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
android:contentDescription="@string/open_group_invitation_view__join_accessibility_description"
|
||||||
|
app:srcCompat="@drawable/ic_add_white_original_24dp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/open_group_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:contentDescription="@string/open_group_invitation_view__join_accessibility_description"
|
||||||
|
android:src="@drawable/ic_globe" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="6dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/group_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/Signal.Text.Caption"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
|
android:textSize="@dimen/large_font_size"
|
||||||
|
android:maxLines="1"
|
||||||
|
tools:text="Open group" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/open_group_invitation_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/Signal.Text.Body"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="@string/open_group_invitation_view__open_group_invitation" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/group_url"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/Signal.Text.Caption"
|
||||||
|
android:maxLines="1"
|
||||||
|
tools:text="http://1.1.1.1" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</merge>
|
@ -782,6 +782,9 @@ Vous avez reçu un message d’échange de clés pour une version de protocole i
|
|||||||
<string name="audio_view__play_accessibility_description">Lire</string>
|
<string name="audio_view__play_accessibility_description">Lire</string>
|
||||||
<string name="audio_view__pause_accessibility_description">Mettre en pause</string>
|
<string name="audio_view__pause_accessibility_description">Mettre en pause</string>
|
||||||
<string name="audio_view__download_accessibility_description">Télécharger</string>
|
<string name="audio_view__download_accessibility_description">Télécharger</string>
|
||||||
|
<!-- open_group_invitation_view -->
|
||||||
|
<string name="open_group_invitation_view__join_accessibility_description">Rejoindre</string>
|
||||||
|
<string name="open_group_invitation_view__open_group_invitation">Invitation à un groupe public</string>
|
||||||
<!--QuoteView-->
|
<!--QuoteView-->
|
||||||
<string name="QuoteView_audio">Contenu audio</string>
|
<string name="QuoteView_audio">Contenu audio</string>
|
||||||
<string name="QuoteView_video">Vidéo</string>
|
<string name="QuoteView_video">Vidéo</string>
|
||||||
|
@ -948,6 +948,10 @@
|
|||||||
<string name="audio_view__pause_accessibility_description">Pause</string>
|
<string name="audio_view__pause_accessibility_description">Pause</string>
|
||||||
<string name="audio_view__download_accessibility_description">Download</string>
|
<string name="audio_view__download_accessibility_description">Download</string>
|
||||||
|
|
||||||
|
<!-- open_group_invitation_view -->
|
||||||
|
<string name="open_group_invitation_view__join_accessibility_description">Join</string>
|
||||||
|
<string name="open_group_invitation_view__open_group_invitation">Open group invitation</string>
|
||||||
|
|
||||||
<!-- QuoteView -->
|
<!-- QuoteView -->
|
||||||
<string name="QuoteView_audio">Audio</string>
|
<string name="QuoteView_audio">Audio</string>
|
||||||
<string name="QuoteView_video">Video</string>
|
<string name="QuoteView_video">Video</string>
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
package org.session.libsession.messaging.messages.control
|
|
||||||
|
|
||||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
|
||||||
import org.session.libsignal.utilities.logging.Log
|
|
||||||
|
|
||||||
class OpenGroupInvitation() : ControlMessage() {
|
|
||||||
|
|
||||||
var groupUrl: String? = null;
|
|
||||||
var groupName: String? = null;
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "OpenGroupInvitation"
|
|
||||||
|
|
||||||
fun fromProto(proto: SignalServiceProtos.Content): OpenGroupInvitation? {
|
|
||||||
val openGroupInvitationProto = if (proto.hasOpenGroupInvitation()) proto.openGroupInvitation else return null
|
|
||||||
val serverAddress = openGroupInvitationProto.groupUrl
|
|
||||||
val serverName = openGroupInvitationProto.groupName
|
|
||||||
return OpenGroupInvitation(serverAddress, serverName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(url: String?, serverName: String?): this() {
|
|
||||||
this.groupUrl = url
|
|
||||||
this.groupName = serverName
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isValid(): Boolean {
|
|
||||||
if (!super.isValid()) return false
|
|
||||||
return (groupUrl != null && groupName != null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toProto(): SignalServiceProtos.Content? {
|
|
||||||
val openGroupInvitationProto = SignalServiceProtos.OpenGroupInvitation.newBuilder()
|
|
||||||
openGroupInvitationProto.groupUrl = groupUrl
|
|
||||||
openGroupInvitationProto.groupName = groupName
|
|
||||||
|
|
||||||
val proto = SignalServiceProtos.Content.newBuilder()
|
|
||||||
return try {
|
|
||||||
proto.openGroupInvitation = openGroupInvitationProto.build()
|
|
||||||
proto.build()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.w(TAG, "Couldn't construct open group invitation proto from: $this")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,11 +5,14 @@ import android.os.Parcelable;
|
|||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.threads.Address;
|
import org.session.libsession.messaging.threads.Address;
|
||||||
|
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||||
import org.session.libsession.utilities.GroupUtil;
|
import org.session.libsession.utilities.GroupUtil;
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceGroup;
|
import org.session.libsignal.service.api.messages.SignalServiceGroup;
|
||||||
|
import org.session.libsignal.utilities.logging.Log;
|
||||||
|
|
||||||
public class IncomingTextMessage implements Parcelable {
|
public class IncomingTextMessage implements Parcelable {
|
||||||
|
|
||||||
@ -40,6 +43,8 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
private final long expiresInMillis;
|
private final long expiresInMillis;
|
||||||
private final boolean unidentified;
|
private final boolean unidentified;
|
||||||
|
|
||||||
|
private boolean isOpenGroupInvitation = false;
|
||||||
|
|
||||||
public IncomingTextMessage(Address sender, int senderDeviceId, long sentTimestampMillis,
|
public IncomingTextMessage(Address sender, int senderDeviceId, long sentTimestampMillis,
|
||||||
String encodedBody, Optional<SignalServiceGroup> group,
|
String encodedBody, Optional<SignalServiceGroup> group,
|
||||||
long expiresInMillis, boolean unidentified)
|
long expiresInMillis, boolean unidentified)
|
||||||
@ -94,6 +99,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.subscriptionId = base.getSubscriptionId();
|
this.subscriptionId = base.getSubscriptionId();
|
||||||
this.expiresInMillis = base.getExpiresIn();
|
this.expiresInMillis = base.getExpiresIn();
|
||||||
this.unidentified = base.isUnidentified();
|
this.unidentified = base.isUnidentified();
|
||||||
|
this.isOpenGroupInvitation= base.isOpenGroupInvitation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IncomingTextMessage from(VisibleMessage message,
|
public static IncomingTextMessage from(VisibleMessage message,
|
||||||
@ -104,6 +110,14 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
return new IncomingTextMessage(sender, 1, message.getSentTimestamp(), message.getText(), group, expiresInMillis, false);
|
return new IncomingTextMessage(sender, 1, message.getSentTimestamp(), message.getText(), group, expiresInMillis, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IncomingTextMessage fromOpenGroupInvitation(OpenGroupInvitation openGroupInvitation, Address sender, Long sentTimestamp)
|
||||||
|
{
|
||||||
|
String body = UpdateMessageData.Companion.buildOpenGroupInvitation(openGroupInvitation.getGroupUrl(), openGroupInvitation.getGroupName()).toJSON();
|
||||||
|
IncomingTextMessage incomingTextMessage = new IncomingTextMessage(sender, 1, sentTimestamp, body, Optional.absent(), 0, false);
|
||||||
|
incomingTextMessage.isOpenGroupInvitation = true;
|
||||||
|
return incomingTextMessage;
|
||||||
|
}
|
||||||
|
|
||||||
public int getSubscriptionId() {
|
public int getSubscriptionId() {
|
||||||
return subscriptionId;
|
return subscriptionId;
|
||||||
}
|
}
|
||||||
@ -163,6 +177,9 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
public boolean isUnidentified() {
|
public boolean isUnidentified() {
|
||||||
return unidentified;
|
return unidentified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOpenGroupInvitation() { return isOpenGroupInvitation; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package org.session.libsession.messaging.messages.signal;
|
package org.session.libsession.messaging.messages.signal;
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation;
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
import org.session.libsession.messaging.messages.visible.VisibleMessage;
|
||||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||||
|
import org.session.libsession.messaging.utilities.UpdateMessageData;
|
||||||
|
|
||||||
public class OutgoingTextMessage {
|
public class OutgoingTextMessage {
|
||||||
|
|
||||||
@ -11,6 +13,8 @@ public class OutgoingTextMessage {
|
|||||||
private final long expiresIn;
|
private final long expiresIn;
|
||||||
private final long sentTimestampMillis;
|
private final long sentTimestampMillis;
|
||||||
|
|
||||||
|
private boolean isOpenGroupInvitation = false;
|
||||||
|
|
||||||
public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId, long sentTimestampMillis) {
|
public OutgoingTextMessage(Recipient recipient, String message, long expiresIn, int subscriptionId, long sentTimestampMillis) {
|
||||||
this.recipient = recipient;
|
this.recipient = recipient;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
@ -23,6 +27,13 @@ public class OutgoingTextMessage {
|
|||||||
return new OutgoingTextMessage(recipient, message.getText(), recipient.getExpireMessages() * 1000, -1, message.getSentTimestamp());
|
return new OutgoingTextMessage(recipient, message.getText(), recipient.getExpireMessages() * 1000, -1, message.getSentTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OutgoingTextMessage fromOpenGroupInvitation(OpenGroupInvitation openGroupInvitation, Recipient recipient, Long sentTimestamp) {
|
||||||
|
String body = UpdateMessageData.Companion.buildOpenGroupInvitation(openGroupInvitation.getGroupUrl(), openGroupInvitation.getGroupName()).toJSON();
|
||||||
|
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, body, 0, -1, sentTimestamp);
|
||||||
|
outgoingTextMessage.isOpenGroupInvitation = true;
|
||||||
|
return outgoingTextMessage;
|
||||||
|
}
|
||||||
|
|
||||||
public long getExpiresIn() {
|
public long getExpiresIn() {
|
||||||
return expiresIn;
|
return expiresIn;
|
||||||
}
|
}
|
||||||
@ -46,4 +57,6 @@ public class OutgoingTextMessage {
|
|||||||
public boolean isSecureMessage() {
|
public boolean isSecureMessage() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOpenGroupInvitation() { return isOpenGroupInvitation; }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package org.session.libsession.messaging.messages.visible
|
||||||
|
|
||||||
|
import org.session.libsession.messaging.messages.control.ControlMessage
|
||||||
|
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||||
|
import org.session.libsignal.utilities.logging.Log
|
||||||
|
|
||||||
|
class OpenGroupInvitation() {
|
||||||
|
|
||||||
|
var groupUrl: String? = null;
|
||||||
|
var groupName: String? = null;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "OpenGroupInvitation"
|
||||||
|
|
||||||
|
fun fromProto(proto: SignalServiceProtos.DataMessage.OpenGroupInvitation): OpenGroupInvitation? {
|
||||||
|
val groupUrl = proto.url
|
||||||
|
val groupName = proto.name
|
||||||
|
return OpenGroupInvitation(groupUrl, groupName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(url: String?, serverName: String?): this() {
|
||||||
|
this.groupUrl = url
|
||||||
|
this.groupName = serverName
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isValid(): Boolean {
|
||||||
|
return (groupUrl != null && groupName != null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toProto(): SignalServiceProtos.DataMessage.OpenGroupInvitation? {
|
||||||
|
val openGroupInvitationProto = SignalServiceProtos.DataMessage.OpenGroupInvitation.newBuilder()
|
||||||
|
openGroupInvitationProto.url = groupUrl
|
||||||
|
openGroupInvitationProto.name = groupName
|
||||||
|
|
||||||
|
return try {
|
||||||
|
openGroupInvitationProto.build()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Couldn't construct open group invitation proto from: $this")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ class VisibleMessage : Message() {
|
|||||||
var quote: Quote? = null
|
var quote: Quote? = null
|
||||||
var linkPreview: LinkPreview? = null
|
var linkPreview: LinkPreview? = null
|
||||||
var profile: Profile? = null
|
var profile: Profile? = null
|
||||||
|
var openGroupInvitation: OpenGroupInvitation? = null
|
||||||
|
|
||||||
override val isSelfSendValid: Boolean = true
|
override val isSelfSendValid: Boolean = true
|
||||||
|
|
||||||
@ -42,6 +43,11 @@ class VisibleMessage : Message() {
|
|||||||
val linkPreview = LinkPreview.fromProto(linkPreviewProto)
|
val linkPreview = LinkPreview.fromProto(linkPreviewProto)
|
||||||
linkPreview?.let { result.linkPreview = linkPreview }
|
linkPreview?.let { result.linkPreview = linkPreview }
|
||||||
}
|
}
|
||||||
|
val openGroupInvitationProto = if (dataMessage.hasOpenGroupInvitation()) dataMessage.openGroupInvitation else null
|
||||||
|
openGroupInvitationProto?.let {
|
||||||
|
val openGroupInvitation = OpenGroupInvitation.fromProto(openGroupInvitationProto)
|
||||||
|
openGroupInvitation?.let { result.openGroupInvitation = openGroupInvitation}
|
||||||
|
}
|
||||||
// TODO Contact
|
// TODO Contact
|
||||||
val profile = Profile.fromProto(dataMessage)
|
val profile = Profile.fromProto(dataMessage)
|
||||||
profile?.let { result.profile = profile }
|
profile?.let { result.profile = profile }
|
||||||
@ -66,6 +72,7 @@ class VisibleMessage : Message() {
|
|||||||
if (attachmentIDs.isNotEmpty()) return true
|
if (attachmentIDs.isNotEmpty()) return true
|
||||||
val text = text?.trim() ?: return false
|
val text = text?.trim() ?: return false
|
||||||
if (text.isNotEmpty()) return true
|
if (text.isNotEmpty()) return true
|
||||||
|
if (openGroupInvitation != null) return true
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +101,11 @@ class VisibleMessage : Message() {
|
|||||||
dataMessage.addAllPreview(listOf(linkPreviewProto))
|
dataMessage.addAllPreview(listOf(linkPreviewProto))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Open group invitation
|
||||||
|
openGroupInvitation?.let {
|
||||||
|
val openGroupInvitationProto = it.toProto()
|
||||||
|
if (openGroupInvitationProto != null) dataMessage.openGroupInvitation = openGroupInvitationProto
|
||||||
|
}
|
||||||
//Attachments
|
//Attachments
|
||||||
val attachments = attachmentIDs.mapNotNull { MessagingModuleConfiguration.shared.messageDataProvider.getSignalAttachmentPointer(it) }
|
val attachments = attachmentIDs.mapNotNull { MessagingModuleConfiguration.shared.messageDataProvider.getSignalAttachmentPointer(it) }
|
||||||
if (!attachments.all { !it.url.isNullOrEmpty() }) {
|
if (!attachments.all { !it.url.isNullOrEmpty() }) {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package org.session.libsession.messaging.sending_receiving
|
package org.session.libsession.messaging.sending_receiving
|
||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import okhttp3.HttpUrl
|
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.messages.Message
|
import org.session.libsession.messaging.messages.Message
|
||||||
import org.session.libsession.messaging.messages.control.*
|
import org.session.libsession.messaging.messages.control.*
|
||||||
import org.session.libsession.messaging.messages.visible.Attachment
|
import org.session.libsession.messaging.messages.visible.Attachment
|
||||||
|
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
|
||||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment
|
||||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||||
@ -49,7 +49,6 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
|
|||||||
is ExpirationTimerUpdate -> handleExpirationTimerUpdate(message)
|
is ExpirationTimerUpdate -> handleExpirationTimerUpdate(message)
|
||||||
is DataExtractionNotification -> handleDataExtractionNotification(message)
|
is DataExtractionNotification -> handleDataExtractionNotification(message)
|
||||||
is ConfigurationMessage -> handleConfigurationMessage(message)
|
is ConfigurationMessage -> handleConfigurationMessage(message)
|
||||||
is OpenGroupInvitation -> handleOpenGroupInvitation(message)
|
|
||||||
is VisibleMessage -> handleVisibleMessage(message, proto, openGroupID)
|
is VisibleMessage -> handleVisibleMessage(message, proto, openGroupID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,12 +149,6 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) {
|
|||||||
storage.addContacts(message.contacts)
|
storage.addContacts(message.contacts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open group invitation handling
|
|
||||||
|
|
||||||
fun handleOpenGroupInvitation(message: OpenGroupInvitation) {
|
|
||||||
//TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region VisibleMessage
|
//region VisibleMessage
|
||||||
|
@ -6,9 +6,9 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
|
|||||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||||
import org.session.libsession.utilities.ExpirationUtil
|
import org.session.libsession.utilities.ExpirationUtil
|
||||||
|
|
||||||
object ClosedGroupUpdateMessageBuilder {
|
object UpdateMessageBuilder {
|
||||||
|
|
||||||
fun buildGroupUpdateMessage(context: Context, updateMessageData: ClosedGroupUpdateMessageData, sender: String? = null, isOutgoing: Boolean = false): String {
|
fun buildGroupUpdateMessage(context: Context, updateMessageData: UpdateMessageData, sender: String? = null, isOutgoing: Boolean = false): String {
|
||||||
var message = ""
|
var message = ""
|
||||||
val updateData = updateMessageData.kind ?: return message
|
val updateData = updateMessageData.kind ?: return message
|
||||||
if (!isOutgoing && sender == null) return message
|
if (!isOutgoing && sender == null) return message
|
||||||
@ -17,21 +17,21 @@ object ClosedGroupUpdateMessageBuilder {
|
|||||||
} else { context.getString(R.string.MessageRecord_you) }
|
} else { context.getString(R.string.MessageRecord_you) }
|
||||||
|
|
||||||
when (updateData) {
|
when (updateData) {
|
||||||
is ClosedGroupUpdateMessageData.Kind.GroupCreation -> {
|
is UpdateMessageData.Kind.GroupCreation -> {
|
||||||
message = if (isOutgoing) {
|
message = if (isOutgoing) {
|
||||||
context.getString(R.string.MessageRecord_you_created_a_new_group)
|
context.getString(R.string.MessageRecord_you_created_a_new_group)
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.MessageRecord_s_added_you_to_the_group, senderName)
|
context.getString(R.string.MessageRecord_s_added_you_to_the_group, senderName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClosedGroupUpdateMessageData.Kind.GroupNameChange -> {
|
is UpdateMessageData.Kind.GroupNameChange -> {
|
||||||
message = if (isOutgoing) {
|
message = if (isOutgoing) {
|
||||||
context.getString(R.string.MessageRecord_you_renamed_the_group_to_s, updateData.name)
|
context.getString(R.string.MessageRecord_you_renamed_the_group_to_s, updateData.name)
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.MessageRecord_s_renamed_the_group_to_s, senderName, updateData.name)
|
context.getString(R.string.MessageRecord_s_renamed_the_group_to_s, senderName, updateData.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClosedGroupUpdateMessageData.Kind.GroupMemberAdded -> {
|
is UpdateMessageData.Kind.GroupMemberAdded -> {
|
||||||
val members = updateData.updatedMembers.joinToString(", ") {
|
val members = updateData.updatedMembers.joinToString(", ") {
|
||||||
MessagingModuleConfiguration.shared.storage.getDisplayNameForRecipient(it) ?: it
|
MessagingModuleConfiguration.shared.storage.getDisplayNameForRecipient(it) ?: it
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ object ClosedGroupUpdateMessageBuilder {
|
|||||||
context.getString(R.string.MessageRecord_s_added_s_to_the_group, senderName, members)
|
context.getString(R.string.MessageRecord_s_added_s_to_the_group, senderName, members)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClosedGroupUpdateMessageData.Kind.GroupMemberRemoved -> {
|
is UpdateMessageData.Kind.GroupMemberRemoved -> {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val userPublicKey = storage.getUserPublicKey()!!
|
val userPublicKey = storage.getUserPublicKey()!!
|
||||||
// 1st case: you are part of the removed members
|
// 1st case: you are part of the removed members
|
||||||
@ -63,7 +63,7 @@ object ClosedGroupUpdateMessageBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ClosedGroupUpdateMessageData.Kind.GroupMemberLeft -> {
|
is UpdateMessageData.Kind.GroupMemberLeft -> {
|
||||||
message = if (isOutgoing) {
|
message = if (isOutgoing) {
|
||||||
context.getString(R.string.MessageRecord_left_group)
|
context.getString(R.string.MessageRecord_left_group)
|
||||||
} else {
|
} else {
|
@ -9,7 +9,7 @@ import org.session.libsignal.utilities.logging.Log
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
// class used to save update messages details
|
// class used to save update messages details
|
||||||
class ClosedGroupUpdateMessageData () {
|
class UpdateMessageData () {
|
||||||
|
|
||||||
var kind: Kind? = null
|
var kind: Kind? = null
|
||||||
|
|
||||||
@ -20,7 +20,8 @@ class ClosedGroupUpdateMessageData () {
|
|||||||
JsonSubTypes.Type(Kind.GroupNameChange::class, name = "GroupNameChange"),
|
JsonSubTypes.Type(Kind.GroupNameChange::class, name = "GroupNameChange"),
|
||||||
JsonSubTypes.Type(Kind.GroupMemberAdded::class, name = "GroupMemberAdded"),
|
JsonSubTypes.Type(Kind.GroupMemberAdded::class, name = "GroupMemberAdded"),
|
||||||
JsonSubTypes.Type(Kind.GroupMemberRemoved::class, name = "GroupMemberRemoved"),
|
JsonSubTypes.Type(Kind.GroupMemberRemoved::class, name = "GroupMemberRemoved"),
|
||||||
JsonSubTypes.Type(Kind.GroupMemberLeft::class, name = "GroupMemberLeft")
|
JsonSubTypes.Type(Kind.GroupMemberLeft::class, name = "GroupMemberLeft"),
|
||||||
|
JsonSubTypes.Type(Kind.OpenGroupInvitation::class, name = "OpenGroupInvitation")
|
||||||
)
|
)
|
||||||
sealed class Kind() {
|
sealed class Kind() {
|
||||||
class GroupCreation(): Kind()
|
class GroupCreation(): Kind()
|
||||||
@ -34,6 +35,9 @@ class ClosedGroupUpdateMessageData () {
|
|||||||
constructor(): this(Collections.emptyList())
|
constructor(): this(Collections.emptyList())
|
||||||
}
|
}
|
||||||
class GroupMemberLeft(): Kind()
|
class GroupMemberLeft(): Kind()
|
||||||
|
class OpenGroupInvitation(val groupUrl: String, val groupName: String): Kind() {
|
||||||
|
constructor(): this("", "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(kind: Kind): this() {
|
constructor(kind: Kind): this() {
|
||||||
@ -41,22 +45,26 @@ class ClosedGroupUpdateMessageData () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val TAG = ClosedGroupUpdateMessageData::class.simpleName
|
val TAG = UpdateMessageData::class.simpleName
|
||||||
|
|
||||||
fun buildGroupUpdate(type: SignalServiceGroup.Type, name: String, members: Collection<String>): ClosedGroupUpdateMessageData? {
|
fun buildGroupUpdate(type: SignalServiceGroup.Type, name: String, members: Collection<String>): UpdateMessageData? {
|
||||||
return when(type) {
|
return when(type) {
|
||||||
SignalServiceGroup.Type.CREATION -> ClosedGroupUpdateMessageData(Kind.GroupCreation())
|
SignalServiceGroup.Type.CREATION -> UpdateMessageData(Kind.GroupCreation())
|
||||||
SignalServiceGroup.Type.NAME_CHANGE -> ClosedGroupUpdateMessageData(Kind.GroupNameChange(name))
|
SignalServiceGroup.Type.NAME_CHANGE -> UpdateMessageData(Kind.GroupNameChange(name))
|
||||||
SignalServiceGroup.Type.MEMBER_ADDED -> ClosedGroupUpdateMessageData(Kind.GroupMemberAdded(members))
|
SignalServiceGroup.Type.MEMBER_ADDED -> UpdateMessageData(Kind.GroupMemberAdded(members))
|
||||||
SignalServiceGroup.Type.MEMBER_REMOVED -> ClosedGroupUpdateMessageData(Kind.GroupMemberRemoved(members))
|
SignalServiceGroup.Type.MEMBER_REMOVED -> UpdateMessageData(Kind.GroupMemberRemoved(members))
|
||||||
SignalServiceGroup.Type.QUIT -> ClosedGroupUpdateMessageData(Kind.GroupMemberLeft())
|
SignalServiceGroup.Type.QUIT -> UpdateMessageData(Kind.GroupMemberLeft())
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromJSON(json: String): ClosedGroupUpdateMessageData? {
|
fun buildOpenGroupInvitation(url: String, name: String): UpdateMessageData {
|
||||||
|
return UpdateMessageData(Kind.OpenGroupInvitation(url, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fromJSON(json: String): UpdateMessageData? {
|
||||||
return try {
|
return try {
|
||||||
JsonUtil.fromJson(json, ClosedGroupUpdateMessageData::class.java)
|
JsonUtil.fromJson(json, UpdateMessageData::class.java)
|
||||||
} catch (e: JsonParseException) {
|
} catch (e: JsonParseException) {
|
||||||
Log.e(TAG, "${e.message}")
|
Log.e(TAG, "${e.message}")
|
||||||
null
|
null
|
@ -1,38 +1,39 @@
|
|||||||
package org.session.libsession.utilities
|
package org.session.libsession.utilities
|
||||||
|
|
||||||
import java.net.MalformedURLException
|
import okhttp3.HttpUrl
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
object OpenGroupUrlParser {
|
object OpenGroupUrlParser {
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
sealed class Error(val description: String) : Exception(description) {
|
sealed class Error(val description: String) : Exception(description) {
|
||||||
class MalformedUrl(message: String?) : Error("Malformed URL: $message.")
|
class MalformedUrl() : Error("Malformed URL.")
|
||||||
object NoRoomSpecified : Error("No room specified in the URL.")
|
object NoRoomSpecified : Error("No room specified in the URL.")
|
||||||
object NoPublicKeySpecified : Error("No public key specified in the URL.")
|
object NoPublicKeySpecified : Error("No public key specified in the URL.")
|
||||||
object WrongQuery : Error("'public_key' argument is missing.")
|
|
||||||
object InvalidPublicKeyProvided : Error("Invalid public key provided.")
|
object InvalidPublicKeyProvided : Error("Invalid public key provided.")
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val pathPrefix = "/"
|
private const val queryPrefix = "public_key"
|
||||||
private const val queryPrefix = "public_key="
|
|
||||||
|
|
||||||
fun parseUrl(url: String): OpenGroupRoom {
|
fun parseUrl(stringUrl: String): OpenGroupRoom {
|
||||||
|
// Url have to start with 'http://'
|
||||||
|
val url = if (!stringUrl.startsWith("http")) "http://$stringUrl" else stringUrl
|
||||||
// If the URL is malformed, it will throw an exception
|
// If the URL is malformed, it will throw an exception
|
||||||
val url = try { URL(url) } catch (e: MalformedURLException) { throw Error.MalformedUrl(e.message) }
|
val httpUrl = HttpUrl.parse(url) ?: throw Error.MalformedUrl()
|
||||||
|
|
||||||
val host = url.host
|
val host = httpUrl.host()
|
||||||
// Test if the room is specified in the URL
|
// Test if the room is specified in the URL
|
||||||
val room = if (!url.path.isNullOrEmpty()) url.path.removePrefix(pathPrefix) else throw Error.NoRoomSpecified
|
val room = httpUrl.pathSegments().firstOrNull { !it.isNullOrEmpty() } ?: throw Error.NoRoomSpecified
|
||||||
// Test if the query is specified in the URL
|
// Test if the query is specified in the URL
|
||||||
val query = if (!url.query.isNullOrEmpty()) url.query else throw Error.NoPublicKeySpecified
|
val publicKey = httpUrl.queryParameter(queryPrefix) ?: throw Error.NoPublicKeySpecified
|
||||||
// Test if 'public_key' is specified in the URL
|
|
||||||
val publicKey = if (query.contains(queryPrefix)) url.query.removePrefix(queryPrefix) else throw Error.WrongQuery
|
|
||||||
// Public key must be 64 characters
|
// Public key must be 64 characters
|
||||||
if (publicKey.length != 64) throw Error.InvalidPublicKeyProvided
|
if (publicKey.length != 64) throw Error.InvalidPublicKeyProvided
|
||||||
|
|
||||||
return OpenGroupRoom(host,room,publicKey)
|
return OpenGroupRoom(host,room,publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun trimParameter(stringUrl: String): String {
|
||||||
|
return stringUrl.substringBefore("?$queryPrefix")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGroupRoom(val serverHost: String, val room: String, val serverPublicKey: String) {}
|
class OpenGroupRoom(val serverHost: String, val room: String, val serverPublicKey: String) { }
|
||||||
|
@ -19,6 +19,20 @@ class OpenGroupUrlParserTest {
|
|||||||
assertEquals(expectedPublicKey, result.serverPublicKey)
|
assertEquals(expectedPublicKey, result.serverPublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseUrlNoHttpTest() {
|
||||||
|
val inputUrl = "sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
|
|
||||||
|
val expectedHost = "sessionopengroup.co"
|
||||||
|
val expectedRoom = "main"
|
||||||
|
val expectedPublicKey = "658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
|
|
||||||
|
val result = OpenGroupUrlParser.parseUrl(inputUrl)
|
||||||
|
assertEquals(expectedHost, result.serverHost)
|
||||||
|
assertEquals(expectedRoom, result.room)
|
||||||
|
assertEquals(expectedPublicKey, result.serverPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun parseUrlWithIpTest() {
|
fun parseUrlWithIpTest() {
|
||||||
val inputUrl = "https://143.198.213.255:80/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
val inputUrl = "https://143.198.213.255:80/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
@ -33,9 +47,23 @@ class OpenGroupUrlParserTest {
|
|||||||
assertEquals(expectedPublicKey, result.serverPublicKey)
|
assertEquals(expectedPublicKey, result.serverPublicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseUrlWithIpAndNoHttpTest() {
|
||||||
|
val inputUrl = "143.198.213.255/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
|
|
||||||
|
val expectedHost = "143.198.213.255"
|
||||||
|
val expectedRoom = "main"
|
||||||
|
val expectedPublicKey = "658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
|
|
||||||
|
val result = OpenGroupUrlParser.parseUrl(inputUrl)
|
||||||
|
assertEquals(expectedHost, result.serverHost)
|
||||||
|
assertEquals(expectedRoom, result.room)
|
||||||
|
assertEquals(expectedPublicKey, result.serverPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = OpenGroupUrlParser.Error.MalformedUrl::class)
|
@Test(expected = OpenGroupUrlParser.Error.MalformedUrl::class)
|
||||||
fun parseUrlMalformedUrlTest() {
|
fun parseUrlMalformedUrlTest() {
|
||||||
val inputUrl = "sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
val inputUrl = "file:sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
||||||
OpenGroupUrlParser.parseUrl(inputUrl)
|
OpenGroupUrlParser.parseUrl(inputUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,12 +79,6 @@ class OpenGroupUrlParserTest {
|
|||||||
OpenGroupUrlParser.parseUrl(inputUrl)
|
OpenGroupUrlParser.parseUrl(inputUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = OpenGroupUrlParser.Error.WrongQuery::class)
|
|
||||||
fun parseUrlWrongQueryTest() {
|
|
||||||
val inputUrl = "https://sessionopengroup.co/main?publickey=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c"
|
|
||||||
OpenGroupUrlParser.parseUrl(inputUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = OpenGroupUrlParser.Error.InvalidPublicKeyProvided::class)
|
@Test(expected = OpenGroupUrlParser.Error.InvalidPublicKeyProvided::class)
|
||||||
fun parseUrlInvalidPublicKeyProviedTest() {
|
fun parseUrlInvalidPublicKeyProviedTest() {
|
||||||
val inputUrl = "https://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adff"
|
val inputUrl = "https://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adff"
|
||||||
|
@ -41,7 +41,7 @@ message Content {
|
|||||||
optional TypingMessage typingMessage = 6;
|
optional TypingMessage typingMessage = 6;
|
||||||
optional ConfigurationMessage configurationMessage = 7;
|
optional ConfigurationMessage configurationMessage = 7;
|
||||||
optional DataExtractionNotification dataExtractionNotification = 8;
|
optional DataExtractionNotification dataExtractionNotification = 8;
|
||||||
optional OpenGroupInvitation openGroupInvitation = 9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message KeyPair {
|
message KeyPair {
|
||||||
@ -103,6 +103,13 @@ message DataMessage {
|
|||||||
optional string profilePicture = 2;
|
optional string profilePicture = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message OpenGroupInvitation {
|
||||||
|
// @required
|
||||||
|
required string url = 1;
|
||||||
|
// @required
|
||||||
|
required string name = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message ClosedGroupControlMessage {
|
message ClosedGroupControlMessage {
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
@ -141,15 +148,11 @@ message DataMessage {
|
|||||||
optional Quote quote = 8;
|
optional Quote quote = 8;
|
||||||
repeated Preview preview = 10;
|
repeated Preview preview = 10;
|
||||||
optional LokiProfile profile = 101;
|
optional LokiProfile profile = 101;
|
||||||
|
optional OpenGroupInvitation openGroupInvitation = 102;
|
||||||
optional ClosedGroupControlMessage closedGroupControlMessage = 104;
|
optional ClosedGroupControlMessage closedGroupControlMessage = 104;
|
||||||
optional string syncTarget = 105;
|
optional string syncTarget = 105;
|
||||||
}
|
}
|
||||||
|
|
||||||
message OpenGroupInvitation {
|
|
||||||
optional string groupUrl = 1;
|
|
||||||
optional string groupName = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ConfigurationMessage {
|
message ConfigurationMessage {
|
||||||
|
|
||||||
message ClosedGroup {
|
message ClosedGroup {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user