From cd6c838953b9b593bdbc0533e5f8be4b3b0e2e2c Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 15 Mar 2021 16:22:25 +1100 Subject: [PATCH 01/17] clean --- .../sskenvironment/DataExtractionNotificationManager.kt | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sskenvironment/DataExtractionNotificationManager.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/DataExtractionNotificationManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/DataExtractionNotificationManager.kt deleted file mode 100644 index 0c8fa779d4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/DataExtractionNotificationManager.kt +++ /dev/null @@ -1,4 +0,0 @@ -package org.thoughtcrime.securesms.sskenvironment - -class DataExtractionNotificationManager { -} \ No newline at end of file From 471e028cf31dd5ac4e1cd00a5d5e982500c8b4d4 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 16 Mar 2021 14:56:47 +1100 Subject: [PATCH 02/17] implementation of the receiving side of Data Extraction notifications & explicit group updates notifications --- .../securesms/database/MmsSmsColumns.java | 36 ++++++++++++ .../securesms/database/Storage.kt | 56 ++++++++++++++----- .../database/model/DisplayRecord.java | 16 ++++++ .../database/model/MessageRecord.java | 30 ++++++++-- .../securesms/jobs/PushDecryptJob.java | 4 +- .../service/ExpiringMessageManager.java | 1 + app/src/main/res/values/strings.xml | 12 ++++ .../libsession/messaging/StorageProtocol.kt | 4 ++ .../control/DataExtractionNotification.kt | 6 +- .../messages/signal/IncomingMediaMessage.java | 34 ++++++----- .../MessageReceiverHandler.kt | 25 +++++++-- .../DataExtractionNotificationInfoMessage.kt | 16 ++++++ .../api/messages/SignalServiceGroup.java | 6 +- 13 files changed, 206 insertions(+), 40 deletions(-) create mode 100644 libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java index 36b86023e6..d26fc12b21 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -70,6 +70,10 @@ public interface MmsSmsColumns { protected static final long GROUP_UPDATE_BIT = 0x10000; protected static final long GROUP_QUIT_BIT = 0x20000; protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000; + protected static final long GROUP_CREATION_BIT = 0x80000; + protected static final long GROUP_NAME_UPDATE_BIT = 0x16000; + protected static final long GROUP_MEMBER_ADDED_BIT = 0x32000; + protected static final long GROUP_MEMBER_REMOVED_BIT = 0x64000; // Encrypted Storage Information XXX public static final long ENCRYPTION_MASK = 0xFF000000; @@ -84,6 +88,8 @@ public interface MmsSmsColumns { // Loki protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000; protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT = 0x00100000; + protected static final long DATA_EXTRACTION_SCREENSHOT_BIT = 0x00010000; + protected static final long DATA_EXTRACTION_MEDIA_SAVED_BIT = 0x00001000; public static boolean isDraftMessageType(long type) { return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE; @@ -197,6 +203,16 @@ public interface MmsSmsColumns { return (type & EXPIRATION_TIMER_UPDATE_BIT) != 0; } + // DATA EXTRACTION NOTIFICATION + + public static boolean isDataExtractionScreenshotUpdate(long type) { + return (type & DATA_EXTRACTION_SCREENSHOT_BIT) != 0; + } + + public static boolean isDataExtractionMediaSavedUpdate(long type) { + return (type & DATA_EXTRACTION_MEDIA_SAVED_BIT) != 0; + } + public static boolean isIncomingCall(long type) { return type == INCOMING_CALL_TYPE; } @@ -209,14 +225,34 @@ public interface MmsSmsColumns { return type == MISSED_CALL_TYPE; } + // GROUPS EXPLICIT UPDATES + public static boolean isGroupUpdate(long type) { return (type & GROUP_UPDATE_BIT) != 0; } + public static boolean isGroupCreation(long type) { + return (type & GROUP_CREATION_BIT) != 0; + } + + public static boolean isGroupNameUpdate(long type) { + return (type & GROUP_NAME_UPDATE_BIT) != 0; + } + + public static boolean isGroupMemberAdded(long type) { + return (type & GROUP_MEMBER_ADDED_BIT) != 0; + } + + public static boolean isGroupMemberRemoved(long type) { + return (type & GROUP_MEMBER_REMOVED_BIT) != 0; + } + public static boolean isGroupQuit(long type) { return (type & GROUP_QUIT_BIT) != 0; } + + public static boolean isFailedDecryptType(long type) { return (type & ENCRYPTION_REMOTE_FAILED_BIT) != 0; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 6a0d42777d..57c6a34100 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -8,18 +8,23 @@ import org.session.libsession.messaging.jobs.AttachmentUploadJob import org.session.libsession.messaging.jobs.Job import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.MessageSendJob +import org.session.libsession.messaging.messages.signal.* import org.session.libsession.messaging.messages.visible.Attachment import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.messaging.opengroups.OpenGroup import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel import org.session.libsession.messaging.threads.Address +import org.session.libsession.messaging.threads.Address.Companion.fromSerialized import org.session.libsession.messaging.threads.GroupRecord import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.utilities.GroupUtil +import org.session.libsession.utilities.IdentityKeyUtil import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.preferences.ProfileKeyUtil import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.libsignal.util.KeyHelper import org.session.libsignal.libsignal.util.guava.Optional @@ -29,21 +34,13 @@ import org.session.libsignal.service.api.messages.SignalServiceGroup import org.session.libsignal.service.internal.push.SignalServiceProtos import org.session.libsignal.service.loki.api.opengroups.PublicChat import org.session.libsignal.utilities.logging.Log -import org.session.libsession.utilities.IdentityKeyUtil import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities import org.thoughtcrime.securesms.loki.utilities.get import org.thoughtcrime.securesms.loki.utilities.getString -import org.session.libsession.messaging.messages.signal.IncomingMediaMessage -import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage -import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage import org.thoughtcrime.securesms.mms.PartAuthority -import org.session.libsession.messaging.messages.signal.IncomingGroupMessage -import org.session.libsession.messaging.messages.signal.IncomingTextMessage -import org.session.libsession.messaging.messages.signal.OutgoingTextMessage -import org.session.libsession.utilities.preferences.ProfileKeyUtil class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol { override fun getUserPublicKey(): String? { @@ -125,17 +122,21 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, PointerAttachment.forPointer(Optional.of(it)).orNull() } val mediaMessage = OutgoingMediaMessage.from(message, Recipient.from(context, targetAddress, false), attachments, quote.orNull(), linkPreviews.orNull().firstOrNull()) - mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!) + mmsDatabase.insertSecureDecryptedMessageOutbox(mediaMessage, message.threadID + ?: -1, message.sentTimestamp!!) } else { // It seems like we have replaced SignalServiceAttachment with SessionServiceAttachment val attachments: Optional> = Optional.of(message.attachmentIDs.mapNotNull { DatabaseFactory.getAttachmentProvider(context).getSignalAttachmentPointer(it) }) - val mediaMessage = IncomingMediaMessage.from(message, senderAddress, senderRecipient.expireMessages * 1000L, group, attachments, quote, linkPreviews) + // FIXME deal with DataExtraction parameter + val mediaMessage = IncomingMediaMessage.from(message, senderAddress, senderRecipient.expireMessages * 1000L, group, attachments, quote, linkPreviews, Optional.absent()) if (group.isPresent) { - mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1, message.sentTimestamp!!) + mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID + ?: -1, message.sentTimestamp!!) } else { - mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1) + mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID + ?: -1) } } if (insertResult.isPresent) { @@ -157,7 +158,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } } val textMessage = OutgoingTextMessage.from(message, Recipient.from(context, targetAddress, false)) - smsDatabase.insertMessageOutbox(message.threadID ?: -1, textMessage, message.sentTimestamp!!) + smsDatabase.insertMessageOutbox(message.threadID + ?: -1, textMessage, message.sentTimestamp!!) } else { val textMessage = IncomingTextMessage.from(message, senderAddress, group, senderRecipient.expireMessages * 1000L) if (group.isPresent) { @@ -417,7 +419,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, val infoMessage = OutgoingGroupMediaMessage(recipient, groupContextBuilder.build(), null, sentTimestamp, 0, null, listOf(), listOf()) val mmsDB = DatabaseFactory.getMmsDatabase(context) val mmsSmsDB = DatabaseFactory.getMmsSmsDatabase(context) - if (mmsSmsDB.getMessageFor(sentTimestamp,userPublicKey) != null) return + if (mmsSmsDB.getMessageFor(sentTimestamp, userPublicKey) != null) return val infoMessageID = mmsDB.insertMessageOutbox(infoMessage, threadID, false, null) mmsDB.markAsSent(infoMessageID, true) } @@ -538,4 +540,30 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, override fun getAttachmentThumbnailUri(attachmentId: AttachmentId): Uri { return PartAuthority.getAttachmentThumbnailUri(attachmentId) } + + // Data Extraction Notification + override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) { + val database = DatabaseFactory.getMmsDatabase(context) + val address = fromSerialized(senderPublicKey) + val recipient = Recipient.from(context, address, false) + + if (recipient.isBlocked) return + + var groupInfo = Optional.absent() + if (groupID != null) { + groupInfo = Optional.of(SignalServiceGroup(groupID.toByteArray(), SignalServiceGroup.GroupType.SIGNAL)) + } + val mediaMessage = IncomingMediaMessage(address, sentTimestamp, -1, + 0, false, + false, + Optional.absent(), + groupInfo, + Optional.absent(), + Optional.absent(), + Optional.absent(), + Optional.absent(), + Optional.of(message)) + + database.insertSecureDecryptedMessageInbox(mediaMessage, -1) + } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index ab40f3381c..cf712351e1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -113,6 +113,14 @@ public abstract class DisplayRecord { return SmsDatabase.Types.isGroupUpdate(type); } + public boolean isGroupCreation() { return MmsSmsColumns.Types.isGroupCreation(type); } + + public boolean isGroupNameUpdate() { return MmsSmsColumns.Types.isGroupNameUpdate(type); } + + public boolean isGroupMemberAdded() { return MmsSmsColumns.Types.isGroupMemberAdded(type); } + + public boolean isGroupMemberRemoved() { return MmsSmsColumns.Types.isGroupMemberRemoved(type); } + public boolean isGroupQuit() { return SmsDatabase.Types.isGroupQuit(type); } @@ -125,6 +133,14 @@ public abstract class DisplayRecord { return SmsDatabase.Types.isExpirationTimerUpdate(type); } + public boolean isDataExtractionScreenshot() { + return MmsSmsColumns.Types.isDataExtractionScreenshotUpdate(type); + } + + public boolean isDataExtractionMediaSaved() { + return MmsSmsColumns.Types.isDataExtractionMediaSavedUpdate(type); + } + public boolean isCallLog() { return SmsDatabase.Types.isCallLog(type); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index b41e4ae78e..a043e74830 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -90,10 +90,26 @@ public abstract class MessageRecord extends DisplayRecord { @Override public SpannableString getDisplayBody(@NonNull Context context) { - if (isGroupUpdate() && isOutgoing()) { + if (isGroupCreation() && isOutgoing()) { + return new SpannableString(context.getString(R.string.MessageRecord_you_created_a_new_group)); + } else if (isGroupCreation()) { + return new SpannableString(context.getString(R.string.MessageRecord_s_created_a_new_group, getIndividualRecipient().toShortString())); + } else if (isGroupUpdate() && isOutgoing()) { return new SpannableString(context.getString(R.string.MessageRecord_you_updated_group)); } else if (isGroupUpdate()) { return new SpannableString(GroupDescription.Companion.getDescription(context, getBody()).toString(getIndividualRecipient())); + } else if (isGroupNameUpdate() && isOutgoing()) { + return new SpannableString(context.getString(R.string.MessageRecord_you_renamed_the_group)); + } else if (isGroupNameUpdate()) { + return new SpannableString(context.getString(R.string.MessageRecord_s_renamed_the_group, getIndividualRecipient().toShortString())); + } else if (isGroupMemberAdded() && isOutgoing()) { + return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group)); + } else if (isGroupMemberAdded()) { + return new SpannableString(context.getString(R.string.MessageRecord_s_added_new_members_to_the_group, getIndividualRecipient().toShortString())); + } else if (isGroupMemberRemoved() && isOutgoing()) { + return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group)); + } else if (isGroupMemberRemoved()) { + return new SpannableString(context.getString(R.string.MessageRecord_s_removed_members_from_the_group, getIndividualRecipient().toShortString())); } else if (isGroupQuit() && isOutgoing()) { return new SpannableString(context.getString(R.string.MessageRecord_left_group)); } else if (isGroupQuit()) { @@ -107,14 +123,20 @@ public abstract class MessageRecord extends DisplayRecord { } else if (isJoined()) { return new SpannableString(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().toShortString())); } else if (isExpirationTimerUpdate()) { - int seconds = (int)(getExpiresIn() / 1000); + int seconds = (int) (getExpiresIn() / 1000); if (seconds <= 0) { return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages)) - : new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString())); + : new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString())); } String time = ExpirationUtil.getExpirationDisplayValue(context, seconds); return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)) - : new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time)); + : new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time)); + } else if (isDataExtractionScreenshot()) { + return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_took_a_screenshot)) + : new SpannableString(context.getString(R.string.MessageRecord_s_took_a_screenshot, getIndividualRecipient().toShortString())); + } else if (isDataExtractionMediaSaved()) { + return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_you)) + : new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_s, getIndividualRecipient().toShortString())); } else if (isIdentityUpdate()) { return new SpannableString(context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, getIndividualRecipient().toShortString())); } else if (isIdentityVerified()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 6ab83939bf..46f99eae9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -272,6 +272,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType { Optional.absent(), Optional.absent(), Optional.absent(), + Optional.absent(), Optional.absent()); database.insertSecureDecryptedMessageInbox(mediaMessage, -1); @@ -371,9 +372,10 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } } else { + // FIXME handle DataExtraction parameter below where Optional.absent() is IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterAddress, message.getTimestamp(), -1, message.getExpiresInSeconds() * 1000L, false, content.isNeedsReceipt(), message.getBody(), message.getGroupInfo(), message.getAttachments(), - quote, sharedContacts, linkPreviews); + quote, sharedContacts, linkPreviews, Optional.absent()); MmsDatabase database = DatabaseFactory.getMmsDatabase(context); database.beginTransaction(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java index 77eee247cd..646f6756e6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java @@ -86,6 +86,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM Optional.absent(), Optional.absent(), Optional.absent(), + Optional.absent(), Optional.absent()); database.insertSecureDecryptedMessageInbox(mediaMessage, -1); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 34ab7d89b4..2d3b0ff674 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -493,6 +493,14 @@ Received a message encrypted using an old version of Session that is no longer supported. Please ask the sender to update to the most recent version and resend the message. You have left the group. You updated the group. + You created a new group. + %1$s created a new group. + You renamed the group. + %1$s renamed the group. + You added new members to the group. + %1$s added new members to the group. + You removed members from the group. + %1$s removed members from the group. You called Contact called Missed call @@ -505,6 +513,10 @@ %1$s disabled disappearing messages. You set the disappearing message timer to %1$s %1$s set the disappearing message timer to %2$s + You took a screenshot. + %1$s took a screenshot. + Media saved by you. + Media saved by %1$s. Your safety number with %s has changed. You marked your safety number with %s verified You marked your safety number with %s verified from another device diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index 2c54c38387..dceee60ac5 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -11,6 +11,7 @@ import org.session.libsession.messaging.messages.visible.Attachment import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.messaging.opengroups.OpenGroup import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel import org.session.libsession.messaging.threads.Address @@ -152,4 +153,7 @@ interface StorageProtocol { // Message Handling /// Returns the ID of the `TSIncomingMessage` that was constructed. fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List, groupPublicKey: String?, openGroupID: String?): Long? + + // Data Extraction Notification + fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt index a612584af8..e963a8e1ee 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt @@ -12,7 +12,7 @@ class DataExtractionNotification(): ControlMessage() { // Kind enum sealed class Kind { class Screenshot() : Kind() - class MediaSaved(val timestanp: Long) : Kind() + class MediaSaved(val timestamp: Long) : Kind() val description: String = run { when(this) { @@ -50,7 +50,7 @@ class DataExtractionNotification(): ControlMessage() { val kind = kind ?: return false return when(kind) { is Kind.Screenshot -> true - is Kind.MediaSaved -> kind.timestanp > 0 + is Kind.MediaSaved -> kind.timestamp > 0 } } @@ -66,7 +66,7 @@ class DataExtractionNotification(): ControlMessage() { is Kind.Screenshot -> dataExtractionNotification.type = SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT is Kind.MediaSaved -> { dataExtractionNotification.type = SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED - dataExtractionNotification.timestamp = kind.timestanp + dataExtractionNotification.timestamp = kind.timestamp } } val contentProto = SignalServiceProtos.Content.newBuilder() diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java index aa330ce227..8fbc0ef884 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java @@ -3,6 +3,7 @@ package org.session.libsession.messaging.messages.signal; import org.session.libsession.messaging.messages.visible.VisibleMessage; import org.session.libsession.messaging.sending_receiving.attachments.Attachment; import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment; +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage; import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact; import org.session.libsession.messaging.threads.Address; import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview; @@ -26,9 +27,11 @@ public class IncomingMediaMessage { private final int subscriptionId; private final long expiresIn; private final boolean expirationUpdate; - private final QuoteModel quote; private final boolean unidentified; + private final DataExtractionNotificationInfoMessage dataExtractionNotification; + private final QuoteModel quote; + private final List attachments = new LinkedList<>(); private final List sharedContacts = new LinkedList<>(); private final List linkPreviews = new LinkedList<>(); @@ -44,17 +47,19 @@ public class IncomingMediaMessage { Optional> attachments, Optional quote, Optional> sharedContacts, - Optional> linkPreviews) + Optional> linkPreviews, + Optional dataExtractionNotification) { - this.push = true; - this.from = from; - this.sentTimeMillis = sentTimeMillis; - this.body = body.orNull(); - this.subscriptionId = subscriptionId; - this.expiresIn = expiresIn; - this.expirationUpdate = expirationUpdate; - this.quote = quote.orNull(); - this.unidentified = unidentified; + this.push = true; + this.from = from; + this.sentTimeMillis = sentTimeMillis; + this.body = body.orNull(); + this.subscriptionId = subscriptionId; + this.expiresIn = expiresIn; + this.expirationUpdate = expirationUpdate; + this.dataExtractionNotification = dataExtractionNotification.orNull(); + this.quote = quote.orNull(); + this.unidentified = unidentified; if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.INSTANCE.getEncodedId(group.get())); else this.groupId = null; @@ -70,10 +75,11 @@ public class IncomingMediaMessage { Optional group, Optional> attachments, Optional quote, - Optional> linkPreviews) + Optional> linkPreviews, + Optional dataExtractionNotification) { return new IncomingMediaMessage(from, message.getReceivedTimestamp(), -1, expiresIn, false, - false, Optional.fromNullable(message.getText()), group, attachments, quote, Optional.absent(), linkPreviews); + false, Optional.fromNullable(message.getText()), group, attachments, quote, Optional.absent(), linkPreviews, dataExtractionNotification); } public int getSubscriptionId() { @@ -128,6 +134,8 @@ public class IncomingMediaMessage { return linkPreviews; } + public DataExtractionNotificationInfoMessage getDataExtractionNotification() { return dataExtractionNotification; } + public boolean isUnidentified() { return unidentified; } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index 114b0ba326..1f0a130d09 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -9,6 +9,7 @@ import org.session.libsession.messaging.messages.control.* import org.session.libsession.messaging.messages.visible.Attachment import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.messaging.sending_receiving.attachments.PointerAttachment +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel @@ -43,6 +44,7 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, is TypingIndicator -> handleTypingIndicator(message) is ClosedGroupControlMessage -> handleClosedGroupControlMessage(message) is ExpirationTimerUpdate -> handleExpirationTimerUpdate(message, proto) + is DataExtractionNotification -> handleDataExtractionNotification(message) is ConfigurationMessage -> handleConfigurationMessage(message) is VisibleMessage -> handleVisibleMessage(message, proto, openGroupID) } @@ -102,6 +104,21 @@ fun MessageReceiver.disableExpirationTimer(message: ExpirationTimerUpdate, proto SSKEnvironment.shared.messageExpirationManager.disableExpirationTimer(id, senderPublicKey, proto) } +// Data Extraction Notification handling + +private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) { + val storage = MessagingConfiguration.shared.storage + val senderPublicKey = message.sender!! + val notification: DataExtractionNotificationInfoMessage = when(message.kind) { + is DataExtractionNotification.Kind.Screenshot -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.SCREENSHOT) + is DataExtractionNotification.Kind.MediaSaved -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.MEDIASAVED) + else -> return + } + storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.groupPublicKey, message.sentTimestamp!!) +} + +// Configuration message handling + private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMessage) { val context = MessagingConfiguration.shared.context val storage = MessagingConfiguration.shared.storage @@ -239,7 +256,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) // Notify the user - storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) + storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NEW, name, members, admins, sentTimestamp) } storage.setProfileSharing(Address.fromSerialized(groupID), true) // Add the group to the user's set of public keys to poll for @@ -356,7 +373,7 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon val name = kind.name storage.updateTitle(groupID, name) - storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!) + storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NAME_UPDATE, name, members, admins, message.sentTimestamp!!) } private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) { @@ -384,7 +401,7 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, message.sentTimestamp!!) } else { - storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!) + storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.MEMBER_ADDED, name, members, admins, message.sentTimestamp!!) } if (userPublicKey in admins) { // send current encryption key to the latest added members @@ -445,7 +462,7 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup } val (contextType, signalType) = if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT - else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE + else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.MEMBER_REMOVED storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, message.sentTimestamp!!) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt new file mode 100644 index 0000000000..64d7af7ff1 --- /dev/null +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt @@ -0,0 +1,16 @@ +package org.session.libsession.messaging.sending_receiving.dataextraction + +class DataExtractionNotificationInfoMessage { + + enum class Kind { + SCREENSHOT, + MEDIASAVED + } + + var kind: Kind? = null + + constructor(kind: Kind?) { + this.kind = kind + } + +} \ No newline at end of file diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java index b503531097..fa84a389f0 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java @@ -37,7 +37,11 @@ public class SignalServiceGroup { UPDATE, DELIVER, QUIT, - REQUEST_INFO + REQUEST_INFO, + NEW, + NAME_UPDATE, + MEMBER_ADDED, + MEMBER_REMOVED } private final byte[] groupId; From 9d82b4b7a90905d60634fb3e98df44acb8e081e1 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Wed, 17 Mar 2021 14:26:29 +1100 Subject: [PATCH 03/17] sending media saved notification --- .../org/thoughtcrime/securesms/MediaPreviewActivity.java | 9 +++++++++ .../securesms/conversation/ConversationFragment.java | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index 6399dbc022..3308b0f992 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -53,6 +53,8 @@ import android.widget.FrameLayout; import android.widget.TextView; import android.widget.Toast; +import org.session.libsession.messaging.messages.control.DataExtractionNotification; +import org.session.libsession.messaging.sending_receiving.MessageSender; import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment; import org.session.libsession.messaging.threads.Address; import org.session.libsession.messaging.threads.recipients.Recipient; @@ -353,11 +355,18 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im saveTask.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null)); + // Sending a Data extraction notification + sendMediaSavedNotificationIfNeeded(); }) .execute(); }); } + private void sendMediaSavedNotificationIfNeeded() { + DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); + MessageSender.send(message, conversationRecipient.getAddress()); + } + @SuppressLint("StaticFieldLeak") private void deleteMedia() { MediaItem mediaItem = getCurrentMediaItem(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 0d30b8ce97..4bf0cf905f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -57,6 +57,7 @@ import androidx.recyclerview.widget.RecyclerView.OnScrollListener; import com.annimon.stream.Stream; +import org.session.libsession.messaging.messages.control.DataExtractionNotification; import org.session.libsession.messaging.messages.visible.Quote; import org.session.libsession.messaging.messages.visible.VisibleMessage; import org.session.libsession.messaging.opengroups.OpenGroupAPI; @@ -745,6 +746,8 @@ public class ConversationFragment extends Fragment if (!Util.isEmpty(attachments)) { SaveAttachmentTask saveTask = new SaveAttachmentTask(getActivity()); saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, attachments.toArray(new SaveAttachmentTask.Attachment[0])); + // Sending a Data extraction notification + sendMediaSavedNotificationIfNeeded(); return; } @@ -757,6 +760,11 @@ public class ConversationFragment extends Fragment }); } + private void sendMediaSavedNotificationIfNeeded() { + DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); + MessageSender.send(message, recipient.getAddress()); + } + @Override public @NonNull Loader onCreateLoader(int id, Bundle args) { Log.i(TAG, "onCreateLoader"); From 2ca8b1acb1b34a181a23a524b0a7d0f88b6b5f87 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Wed, 17 Mar 2021 15:08:09 +1100 Subject: [PATCH 04/17] missed case for sending media saved notification --- .../securesms/MediaOverviewActivity.java | 12 ++++++++++++ .../thoughtcrime/securesms/MediaPreviewActivity.java | 3 +++ .../securesms/conversation/ConversationFragment.java | 3 +++ 3 files changed, 18 insertions(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java index 0056718e3c..39e817037b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -52,6 +52,8 @@ import androidx.viewpager.widget.ViewPager; import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager; import com.google.android.material.tabs.TabLayout; +import org.session.libsession.messaging.messages.control.DataExtractionNotification; +import org.session.libsession.messaging.sending_receiving.MessageSender; import org.session.libsession.messaging.threads.Address; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; import org.thoughtcrime.securesms.database.MediaDatabase; @@ -351,6 +353,8 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { saveTask.executeOnExecutor(THREAD_POOL_EXECUTOR, attachments.toArray(new SaveAttachmentTask.Attachment[attachments.size()])); actionMode.finish(); + // Sending a Data extraction notification + sendMediaSavedNotificationIfNeeded(); } }.execute(); }) @@ -358,6 +362,14 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { }, mediaRecords.size()); } + /** + * Send a MediaSaved notification to the recipient + */ + private void sendMediaSavedNotificationIfNeeded() { + DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); + MessageSender.send(message, recipient.getAddress()); + } + @SuppressLint("StaticFieldLeak") private void handleDeleteMedia(@NonNull Collection mediaRecords) { int recordCount = mediaRecords.size(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index 3308b0f992..5775ce936c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -362,6 +362,9 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im }); } + /** + * Send a MediaSaved notification to the recipient + */ private void sendMediaSavedNotificationIfNeeded() { DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); MessageSender.send(message, conversationRecipient.getAddress()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 4bf0cf905f..b833ad6c31 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -760,6 +760,9 @@ public class ConversationFragment extends Fragment }); } + /** + * Send a MediaSaved notification to the recipient + */ private void sendMediaSavedNotificationIfNeeded() { DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); MessageSender.send(message, recipient.getAddress()); From 5dcb3d77d4468be50b571641a1d939f5c31a13ff Mon Sep 17 00:00:00 2001 From: Brice-W Date: Fri, 19 Mar 2021 16:39:41 +1100 Subject: [PATCH 05/17] revert changes regarding explicit group updates as it's now in a separate PR --- .../securesms/database/MmsSmsColumns.java | 36 ------------------- .../database/model/DisplayRecord.java | 16 --------- .../database/model/MessageRecord.java | 26 +------------- app/src/main/res/values/strings.xml | 8 ----- .../MessageReceiverHandler.kt | 8 ++--- .../api/messages/SignalServiceGroup.java | 6 +--- 6 files changed, 6 insertions(+), 94 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java index d26fc12b21..36b86023e6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -70,10 +70,6 @@ public interface MmsSmsColumns { protected static final long GROUP_UPDATE_BIT = 0x10000; protected static final long GROUP_QUIT_BIT = 0x20000; protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000; - protected static final long GROUP_CREATION_BIT = 0x80000; - protected static final long GROUP_NAME_UPDATE_BIT = 0x16000; - protected static final long GROUP_MEMBER_ADDED_BIT = 0x32000; - protected static final long GROUP_MEMBER_REMOVED_BIT = 0x64000; // Encrypted Storage Information XXX public static final long ENCRYPTION_MASK = 0xFF000000; @@ -88,8 +84,6 @@ public interface MmsSmsColumns { // Loki protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_SENT_BIT = 0x01000000; protected static final long ENCRYPTION_LOKI_SESSION_RESTORE_DONE_BIT = 0x00100000; - protected static final long DATA_EXTRACTION_SCREENSHOT_BIT = 0x00010000; - protected static final long DATA_EXTRACTION_MEDIA_SAVED_BIT = 0x00001000; public static boolean isDraftMessageType(long type) { return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE; @@ -203,16 +197,6 @@ public interface MmsSmsColumns { return (type & EXPIRATION_TIMER_UPDATE_BIT) != 0; } - // DATA EXTRACTION NOTIFICATION - - public static boolean isDataExtractionScreenshotUpdate(long type) { - return (type & DATA_EXTRACTION_SCREENSHOT_BIT) != 0; - } - - public static boolean isDataExtractionMediaSavedUpdate(long type) { - return (type & DATA_EXTRACTION_MEDIA_SAVED_BIT) != 0; - } - public static boolean isIncomingCall(long type) { return type == INCOMING_CALL_TYPE; } @@ -225,34 +209,14 @@ public interface MmsSmsColumns { return type == MISSED_CALL_TYPE; } - // GROUPS EXPLICIT UPDATES - public static boolean isGroupUpdate(long type) { return (type & GROUP_UPDATE_BIT) != 0; } - public static boolean isGroupCreation(long type) { - return (type & GROUP_CREATION_BIT) != 0; - } - - public static boolean isGroupNameUpdate(long type) { - return (type & GROUP_NAME_UPDATE_BIT) != 0; - } - - public static boolean isGroupMemberAdded(long type) { - return (type & GROUP_MEMBER_ADDED_BIT) != 0; - } - - public static boolean isGroupMemberRemoved(long type) { - return (type & GROUP_MEMBER_REMOVED_BIT) != 0; - } - public static boolean isGroupQuit(long type) { return (type & GROUP_QUIT_BIT) != 0; } - - public static boolean isFailedDecryptType(long type) { return (type & ENCRYPTION_REMOTE_FAILED_BIT) != 0; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index cf712351e1..ab40f3381c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -113,14 +113,6 @@ public abstract class DisplayRecord { return SmsDatabase.Types.isGroupUpdate(type); } - public boolean isGroupCreation() { return MmsSmsColumns.Types.isGroupCreation(type); } - - public boolean isGroupNameUpdate() { return MmsSmsColumns.Types.isGroupNameUpdate(type); } - - public boolean isGroupMemberAdded() { return MmsSmsColumns.Types.isGroupMemberAdded(type); } - - public boolean isGroupMemberRemoved() { return MmsSmsColumns.Types.isGroupMemberRemoved(type); } - public boolean isGroupQuit() { return SmsDatabase.Types.isGroupQuit(type); } @@ -133,14 +125,6 @@ public abstract class DisplayRecord { return SmsDatabase.Types.isExpirationTimerUpdate(type); } - public boolean isDataExtractionScreenshot() { - return MmsSmsColumns.Types.isDataExtractionScreenshotUpdate(type); - } - - public boolean isDataExtractionMediaSaved() { - return MmsSmsColumns.Types.isDataExtractionMediaSavedUpdate(type); - } - public boolean isCallLog() { return SmsDatabase.Types.isCallLog(type); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index a043e74830..8ac7fac42f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -90,26 +90,8 @@ public abstract class MessageRecord extends DisplayRecord { @Override public SpannableString getDisplayBody(@NonNull Context context) { - if (isGroupCreation() && isOutgoing()) { - return new SpannableString(context.getString(R.string.MessageRecord_you_created_a_new_group)); - } else if (isGroupCreation()) { - return new SpannableString(context.getString(R.string.MessageRecord_s_created_a_new_group, getIndividualRecipient().toShortString())); - } else if (isGroupUpdate() && isOutgoing()) { - return new SpannableString(context.getString(R.string.MessageRecord_you_updated_group)); - } else if (isGroupUpdate()) { + if (isGroupUpdate() && isOutgoing()) { return new SpannableString(GroupDescription.Companion.getDescription(context, getBody()).toString(getIndividualRecipient())); - } else if (isGroupNameUpdate() && isOutgoing()) { - return new SpannableString(context.getString(R.string.MessageRecord_you_renamed_the_group)); - } else if (isGroupNameUpdate()) { - return new SpannableString(context.getString(R.string.MessageRecord_s_renamed_the_group, getIndividualRecipient().toShortString())); - } else if (isGroupMemberAdded() && isOutgoing()) { - return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group)); - } else if (isGroupMemberAdded()) { - return new SpannableString(context.getString(R.string.MessageRecord_s_added_new_members_to_the_group, getIndividualRecipient().toShortString())); - } else if (isGroupMemberRemoved() && isOutgoing()) { - return new SpannableString(context.getString(R.string.MessageRecord_you_added_new_members_to_the_group)); - } else if (isGroupMemberRemoved()) { - return new SpannableString(context.getString(R.string.MessageRecord_s_removed_members_from_the_group, getIndividualRecipient().toShortString())); } else if (isGroupQuit() && isOutgoing()) { return new SpannableString(context.getString(R.string.MessageRecord_left_group)); } else if (isGroupQuit()) { @@ -131,12 +113,6 @@ public abstract class MessageRecord extends DisplayRecord { String time = ExpirationUtil.getExpirationDisplayValue(context, seconds); return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)) : new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time)); - } else if (isDataExtractionScreenshot()) { - return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_took_a_screenshot)) - : new SpannableString(context.getString(R.string.MessageRecord_s_took_a_screenshot, getIndividualRecipient().toShortString())); - } else if (isDataExtractionMediaSaved()) { - return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_you)) - : new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_s, getIndividualRecipient().toShortString())); } else if (isIdentityUpdate()) { return new SpannableString(context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, getIndividualRecipient().toShortString())); } else if (isIdentityVerified()) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2d3b0ff674..166f8c42d1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -493,14 +493,6 @@ Received a message encrypted using an old version of Session that is no longer supported. Please ask the sender to update to the most recent version and resend the message. You have left the group. You updated the group. - You created a new group. - %1$s created a new group. - You renamed the group. - %1$s renamed the group. - You added new members to the group. - %1$s added new members to the group. - You removed members from the group. - %1$s removed members from the group. You called Contact called Missed call diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index 1f0a130d09..64a4e39c62 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -256,7 +256,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) // Notify the user - storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NEW, name, members, admins, sentTimestamp) + storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) } storage.setProfileSharing(Address.fromSerialized(groupID), true) // Add the group to the user's set of public keys to poll for @@ -373,7 +373,7 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon val name = kind.name storage.updateTitle(groupID, name) - storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.NAME_UPDATE, name, members, admins, message.sentTimestamp!!) + storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!) } private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) { @@ -401,7 +401,7 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) storage.insertOutgoingInfoMessage(context, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, name, members, admins, threadID, message.sentTimestamp!!) } else { - storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.MEMBER_ADDED, name, members, admins, message.sentTimestamp!!) + storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, message.sentTimestamp!!) } if (userPublicKey in admins) { // send current encryption key to the latest added members @@ -462,7 +462,7 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup } val (contextType, signalType) = if (senderLeft) SignalServiceProtos.GroupContext.Type.QUIT to SignalServiceGroup.Type.QUIT - else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.MEMBER_REMOVED + else SignalServiceProtos.GroupContext.Type.UPDATE to SignalServiceGroup.Type.UPDATE storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, contextType, signalType, name, members, admins, message.sentTimestamp!!) } diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java index fa84a389f0..b503531097 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/messages/SignalServiceGroup.java @@ -37,11 +37,7 @@ public class SignalServiceGroup { UPDATE, DELIVER, QUIT, - REQUEST_INFO, - NEW, - NAME_UPDATE, - MEMBER_ADDED, - MEMBER_REMOVED + REQUEST_INFO } private final byte[] groupId; From a47113f2c5e0ff3c378452397b56c4b860c5bde8 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Fri, 19 Mar 2021 16:57:00 +1100 Subject: [PATCH 06/17] revert changes --- .../securesms/database/model/MessageRecord.java | 8 +++++--- .../libsession/messaging/jobs/MessageReceiveJob.kt | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 8ac7fac42f..b41e4ae78e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -91,6 +91,8 @@ public abstract class MessageRecord extends DisplayRecord { @Override public SpannableString getDisplayBody(@NonNull Context context) { if (isGroupUpdate() && isOutgoing()) { + return new SpannableString(context.getString(R.string.MessageRecord_you_updated_group)); + } else if (isGroupUpdate()) { return new SpannableString(GroupDescription.Companion.getDescription(context, getBody()).toString(getIndividualRecipient())); } else if (isGroupQuit() && isOutgoing()) { return new SpannableString(context.getString(R.string.MessageRecord_left_group)); @@ -105,14 +107,14 @@ public abstract class MessageRecord extends DisplayRecord { } else if (isJoined()) { return new SpannableString(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().toShortString())); } else if (isExpirationTimerUpdate()) { - int seconds = (int) (getExpiresIn() / 1000); + int seconds = (int)(getExpiresIn() / 1000); if (seconds <= 0) { return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages)) - : new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString())); + : new SpannableString(context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, getIndividualRecipient().toShortString())); } String time = ExpirationUtil.getExpirationDisplayValue(context, seconds); return isOutgoing() ? new SpannableString(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time)) - : new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time)); + : new SpannableString(context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, getIndividualRecipient().toShortString(), time)); } else if (isIdentityUpdate()) { return new SpannableString(context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, getIndividualRecipient().toShortString())); } else if (isIdentityVerified()) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageReceiveJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageReceiveJob.kt index 014b66a0c8..4ce46b4577 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageReceiveJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageReceiveJob.kt @@ -15,7 +15,7 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val // Settings override val maxFailureCount: Int = 10 companion object { - val TAG = MessageReceiveJob::class.qualifiedName + val TAG = MessageReceiveJob::class.simpleName val KEY: String = "MessageReceiveJob" //keys used for database storage purpose From 68a3c73ab1e672057a27c600fa768568d850797b Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 23 Mar 2021 10:59:03 +1100 Subject: [PATCH 07/17] clean --- .../main/java/org/thoughtcrime/securesms/database/Storage.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index edffc8cac0..cb7c8b7aee 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -44,8 +44,6 @@ import org.thoughtcrime.securesms.mms.PartAuthority import org.session.libsession.messaging.messages.signal.IncomingGroupMessage import org.session.libsession.messaging.messages.signal.IncomingTextMessage import org.session.libsession.messaging.messages.signal.OutgoingTextMessage -import org.session.libsession.utilities.preferences.ProfileKeyUtil -import org.session.libsignal.service.loki.utilities.prettifiedDescription class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol { override fun getUserPublicKey(): String? { From 1b01d0afd47ef4f64dee97cc9868393c1277f14b Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 23 Mar 2021 11:03:09 +1100 Subject: [PATCH 08/17] clean --- .../main/java/org/thoughtcrime/securesms/database/Storage.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index cb7c8b7aee..d6515ae80c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -24,7 +24,6 @@ import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.IdentityKeyUtil import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsession.utilities.preferences.ProfileKeyUtil import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.libsignal.util.KeyHelper import org.session.libsignal.libsignal.util.guava.Optional @@ -44,6 +43,8 @@ import org.thoughtcrime.securesms.mms.PartAuthority import org.session.libsession.messaging.messages.signal.IncomingGroupMessage import org.session.libsession.messaging.messages.signal.IncomingTextMessage import org.session.libsession.messaging.messages.signal.OutgoingTextMessage +import org.session.libsession.utilities.preferences.ProfileKeyUtil +import org.session.libsignal.service.loki.utilities.prettifiedDescription class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol { override fun getUserPublicKey(): String? { From cc24e29cb2d5cb3cad4f1817f18cc734bdf383ab Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 8 Apr 2021 15:11:46 +1000 Subject: [PATCH 09/17] clean --- .../java/org/session/libsession/messaging/StorageProtocol.kt | 2 +- .../messaging/messages/control/DataExtractionNotification.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index 5b88e362a7..3327952304 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -162,4 +162,4 @@ interface StorageProtocol { // Data Extraction Notification fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) -} \ No newline at end of file +} diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt index 040ea66d0f..538b0b0001 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/DataExtractionNotification.kt @@ -73,5 +73,4 @@ class DataExtractionNotification(): ControlMessage() { return null } } - -} \ No newline at end of file +} From fce1d60d7d31d352bce6415b982a12c17ffa8aa8 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 8 Apr 2021 15:40:00 +1000 Subject: [PATCH 10/17] clean --- .../main/java/org/thoughtcrime/securesms/database/Storage.kt | 3 +-- .../messaging/messages/signal/IncomingMediaMessage.java | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index ab88d16ce0..57aad5b10d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -148,8 +148,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, val signalServiceAttachments = attachments.mapNotNull { it.toSignalPointer() } - //TODO deal with data extraction instead of Optional.absent() - val mediaMessage = IncomingMediaMessage.from(message, senderAddress, targetRecipient.expireMessages * 1000L, group, signalServiceAttachments, quote, linkPreviews, Optional.absent()) + val mediaMessage = IncomingMediaMessage.from(message, senderAddress, targetRecipient.expireMessages * 1000L, group, signalServiceAttachments, quote, linkPreviews) mmsDatabase.beginTransaction() mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1, message.receivedTimestamp ?: 0) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java index dff60354c3..ad110964a0 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java @@ -75,11 +75,10 @@ public class IncomingMediaMessage { Optional group, List attachments, Optional quote, - Optional> linkPreviews, - Optional dataExtractionNotification) + Optional> linkPreviews) { return new IncomingMediaMessage(from, message.getSentTimestamp(), -1, expiresIn, false, - false, Optional.fromNullable(message.getText()), group, Optional.fromNullable(attachments), quote, Optional.absent(), linkPreviews, dataExtractionNotification); + false, Optional.fromNullable(message.getText()), group, Optional.fromNullable(attachments), quote, Optional.absent(), linkPreviews, Optional.absent()); } public int getSubscriptionId() { From c03b49eeb732697f0b8f637b8aaaa441de03419d Mon Sep 17 00:00:00 2001 From: Brice-W Date: Thu, 8 Apr 2021 15:48:00 +1000 Subject: [PATCH 11/17] clean --- .../java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java index 0bf78d38ce..ad2e55dafc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptJob.java @@ -373,7 +373,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType { } } else { - // FIXME handle DataExtraction parameter below where Optional.absent() is IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterAddress, message.getTimestamp(), -1, message.getExpiresInSeconds() * 1000L, false, content.isNeedsReceipt(), message.getBody(), message.getGroupInfo(), message.getAttachments(), quote, sharedContacts, linkPreviews, Optional.absent()); From e57c697eca8193349fc34560c27d5e5ce01935a5 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Fri, 9 Apr 2021 16:06:12 +1000 Subject: [PATCH 12/17] finishing data extraction handling --- .../securesms/MediaOverviewActivity.java | 2 ++ .../securesms/MediaPreviewActivity.java | 2 ++ .../conversation/ConversationFragment.java | 2 ++ .../conversation/ConversationUpdateItem.java | 19 +++++++++++++++++++ .../securesms/database/MmsDatabase.java | 8 ++++++++ .../securesms/database/MmsSmsColumns.java | 12 ++++++++++++ .../securesms/database/Storage.kt | 8 ++------ .../database/model/DisplayRecord.java | 14 ++++++++++++++ .../database/model/MessageRecord.java | 5 ++++- .../database/model/ThreadRecord.java | 6 +++++- app/src/main/res/values/strings.xml | 4 ++-- .../libsession/messaging/StorageProtocol.kt | 2 +- .../messages/signal/IncomingMediaMessage.java | 14 ++++++++++++++ .../MessageReceiverHandler.kt | 10 +++++++--- 14 files changed, 94 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java index 39e817037b..762d88b81c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -366,6 +366,8 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { * Send a MediaSaved notification to the recipient */ private void sendMediaSavedNotificationIfNeeded() { + // we don't send media saved notification for groups + if (recipient.isGroupRecipient()) return; DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); MessageSender.send(message, recipient.getAddress()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index 39a67d762d..8bc53250a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -368,6 +368,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im * Send a MediaSaved notification to the recipient */ private void sendMediaSavedNotificationIfNeeded() { + // we don't send media saved notification for groups + if (conversationRecipient.isGroupRecipient()) return; DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); MessageSender.send(message, conversationRecipient.getAddress()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index b833ad6c31..d69574c4d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -764,6 +764,8 @@ public class ConversationFragment extends Fragment * Send a MediaSaved notification to the recipient */ private void sendMediaSavedNotificationIfNeeded() { + // we don't send media saved notification for groups + if (recipient.isGroupRecipient()) return; DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(System.currentTimeMillis())); MessageSender.send(message, recipient.getAddress()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 6b76c0572a..0bdb8ba3cf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -15,6 +15,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage; import org.thoughtcrime.securesms.BindableConversationItem; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt; @@ -106,6 +107,8 @@ public class ConversationUpdateItem extends LinearLayout else if (messageRecord.isCallLog()) setCallRecord(messageRecord); else if (messageRecord.isJoined()) setJoinedRecord(messageRecord); else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord); + else if (messageRecord.isScreenshotExtraction()) setDataExtractionRecord(messageRecord, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT); + else if (messageRecord.isMediaSavedExtraction()) setDataExtractionRecord(messageRecord, DataExtractionNotificationInfoMessage.Kind.MEDIASAVED); else if (messageRecord.isEndSession()) setEndSessionRecord(messageRecord); else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord); else if (messageRecord.isIdentityVerified() || @@ -149,6 +152,22 @@ public class ConversationUpdateItem extends LinearLayout date.setVisibility(GONE); } + private void setDataExtractionRecord(final MessageRecord messageRecord, DataExtractionNotificationInfoMessage.Kind kind) { + @ColorInt int color = GeneralUtilitiesKt.getColorWithID(getResources(), R.color.text, getContext().getTheme()); + if (kind == DataExtractionNotificationInfoMessage.Kind.SCREENSHOT) { + icon.setImageResource(R.drawable.quick_camera_dark); + } else if (kind == DataExtractionNotificationInfoMessage.Kind.MEDIASAVED) { + icon.setImageResource(R.drawable.ic_file_download_white_36dp); + } + icon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); + + body.setText(messageRecord.getDisplayBody(getContext())); + + title.setVisibility(VISIBLE); + body.setVisibility(VISIBLE); + date.setVisibility(GONE); + } + private void setIdentityRecord(final MessageRecord messageRecord) { icon.setImageResource(R.drawable.ic_security_white_24dp); icon.setColorFilter(new PorterDuffColorFilter(Color.parseColor("#757575"), PorterDuff.Mode.MULTIPLY)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index 62de9499a1..12e5ba2d95 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -709,6 +709,14 @@ public class MmsDatabase extends MessagingDatabase { type |= Types.EXPIRATION_TIMER_UPDATE_BIT; } + if (retrieved.isScreenshotDataExtraction()) { + type |= Types.SCREENSHOT_EXTRACTION_BIT; + } + + if (retrieved.isMediaSavedDataExtraction()) { + type |= Types.MEDIA_SAVED_EXTRACTION_BIT; + } + return insertMessageInbox(retrieved, "", threadId, type, serverTimestamp); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java index 36b86023e6..aefd1af808 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -71,6 +71,10 @@ public interface MmsSmsColumns { protected static final long GROUP_QUIT_BIT = 0x20000; protected static final long EXPIRATION_TIMER_UPDATE_BIT = 0x40000; + // Data Extraction Information + protected static final long MEDIA_SAVED_EXTRACTION_BIT = 0x01000; + protected static final long SCREENSHOT_EXTRACTION_BIT = 0x02000; + // Encrypted Storage Information XXX public static final long ENCRYPTION_MASK = 0xFF000000; // public static final long ENCRYPTION_SYMMETRIC_BIT = 0x80000000; Deprecated @@ -197,6 +201,14 @@ public interface MmsSmsColumns { return (type & EXPIRATION_TIMER_UPDATE_BIT) != 0; } + public static boolean isMediaSavedExtraction(long type) { + return (type & MEDIA_SAVED_EXTRACTION_BIT) != 0; + } + + public static boolean isScreenshotExtraction(long type) { + return (type & SCREENSHOT_EXTRACTION_BIT) != 0; + } + public static boolean isIncomingCall(long type) { return type == INCOMING_CALL_TYPE; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 57aad5b10d..7722840a49 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -581,22 +581,18 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } // Data Extraction Notification - override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) { + override fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long) { val database = DatabaseFactory.getMmsDatabase(context) val address = fromSerialized(senderPublicKey) val recipient = Recipient.from(context, address, false) if (recipient.isBlocked) return - var groupInfo = Optional.absent() - if (groupID != null) { - groupInfo = Optional.of(SignalServiceGroup(groupID.toByteArray(), SignalServiceGroup.GroupType.SIGNAL)) - } val mediaMessage = IncomingMediaMessage(address, sentTimestamp, -1, 0, false, false, Optional.absent(), - groupInfo, + Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index ab40f3381c..28eae16f16 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -125,6 +125,20 @@ public abstract class DisplayRecord { return SmsDatabase.Types.isExpirationTimerUpdate(type); } + // Data extraction + + public boolean isMediaSavedExtraction() { + return MmsSmsColumns.Types.isMediaSavedExtraction(type); + } + + public boolean isScreenshotExtraction() { + return MmsSmsColumns.Types.isScreenshotExtraction(type); + } + + public boolean isDataExtraction() { + return isMediaSavedExtraction() || isScreenshotExtraction(); + } + public boolean isCallLog() { return SmsDatabase.Types.isCallLog(type); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index b41e4ae78e..64229e95b5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -98,6 +98,9 @@ public abstract class MessageRecord extends DisplayRecord { return new SpannableString(context.getString(R.string.MessageRecord_left_group)); } else if (isGroupQuit()) { return new SpannableString(context.getString(R.string.ConversationItem_group_action_left, getIndividualRecipient().toShortString())); + } else if (isDataExtraction()) { + if (isMediaSavedExtraction()) return new SpannableString(context.getString(R.string.MessageRecord_media_saved_by_s, getIndividualRecipient().toShortString())); + if (isScreenshotExtraction()) return new SpannableString(context.getString(R.string.MessageRecord_s_took_a_screenshot, getIndividualRecipient().toShortString())); } else if (isIncomingCall()) { return new SpannableString(context.getString(R.string.MessageRecord_s_called_you, getIndividualRecipient().toShortString())); } else if (isOutgoingCall()) { @@ -175,7 +178,7 @@ public abstract class MessageRecord extends DisplayRecord { } public boolean isUpdate() { - return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() || + return isGroupAction() || isJoined() || isExpirationTimerUpdate() || isCallLog() || isDataExtraction() || isEndSession() || isIdentityUpdate() || isIdentityVerified() || isIdentityDefault() || isLokiSessionRestoreSent() || isLokiSessionRestoreDone(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java index e2a286c854..42c8a20ede 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java @@ -103,12 +103,16 @@ public class ThreadRecord extends DisplayRecord { } else if (SmsDatabase.Types.isJoinedType(type)) { return emphasisAdded(context.getString(R.string.ThreadRecord_s_is_on_signal, getRecipient().toShortString())); } else if (SmsDatabase.Types.isExpirationTimerUpdate(type)) { - int seconds = (int)(getExpiresIn() / 1000); + int seconds = (int) (getExpiresIn() / 1000); if (seconds <= 0) { return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_messages_disabled)); } String time = ExpirationUtil.getExpirationDisplayValue(context, seconds); return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time)); + } else if (MmsSmsColumns.Types.isMediaSavedExtraction(type)) { + return emphasisAdded(context.getString(R.string.ThreadRecord_media_saved_by_s, getRecipient().toShortString())); + } else if (MmsSmsColumns.Types.isScreenshotExtraction(type)) { + return emphasisAdded(context.getString(R.string.ThreadRecord_s_took_a_screenshot, getRecipient().toShortString())); } else if (SmsDatabase.Types.isIdentityUpdate(type)) { if (getRecipient().isGroupRecipient()) return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed)); else return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, getRecipient().toShortString())); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 166f8c42d1..3b0693645a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -505,9 +505,7 @@ %1$s disabled disappearing messages. You set the disappearing message timer to %1$s %1$s set the disappearing message timer to %2$s - You took a screenshot. %1$s took a screenshot. - Media saved by you. Media saved by %1$s. Your safety number with %s has changed. You marked your safety number with %s verified @@ -707,6 +705,8 @@ %s is on Session! Disappearing messages disabled Disappearing message time set to %s + %s took a screenshot. + Media saved by %s. Safety number changed Your safety number with %s has changed. You marked verified diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index 3327952304..b390637ca2 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -161,5 +161,5 @@ interface StorageProtocol { fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List, groupPublicKey: String?, openGroupID: String?, attachments: List): Long? // Data Extraction Notification - fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, groupID: String?, sentTimestamp: Long) + fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java index ad110964a0..53e48a5897 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java @@ -121,6 +121,20 @@ public class IncomingMediaMessage { return groupId != null; } + public boolean isScreenshotDataExtraction() { + if (dataExtractionNotification == null) return false; + else { + return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.SCREENSHOT; + } + } + + public boolean isMediaSavedDataExtraction() { + if (dataExtractionNotification == null) return false; + else { + return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.MEDIASAVED; + } + } + public QuoteModel getQuote() { return quote; } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index 2c0e2269c9..190a55195f 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -96,6 +96,9 @@ private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimer // Data Extraction Notification handling private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) { + // we don't handle data extraction messages for groups (they shouldn't be sent, but in case we filter them here too) + if (message.groupPublicKey != null) return + val storage = MessagingConfiguration.shared.storage val senderPublicKey = message.sender!! val notification: DataExtractionNotificationInfoMessage = when(message.kind) { @@ -103,7 +106,7 @@ private fun MessageReceiver.handleDataExtractionNotification(message: DataExtrac is DataExtractionNotification.Kind.MediaSaved -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.MEDIASAVED) else -> return } - storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.groupPublicKey, message.sentTimestamp!!) + storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.sentTimestamp!!) } // Configuration message handling @@ -170,7 +173,8 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS } } // Get or create thread - val threadID = storage.getOrCreateThreadIdFor(message.syncTarget ?: message.sender!!, message.groupPublicKey, openGroupID) + val threadID = storage.getOrCreateThreadIdFor(message.syncTarget + ?: message.sender!!, message.groupPublicKey, openGroupID) // Parse quote if needed var quoteModel: QuoteModel? = null if (message.quote != null && proto.dataMessage.hasQuote()) { @@ -259,7 +263,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli storage.updateMembers(groupID, members.map { Address.fromSerialized(it) }) } else { storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), - null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) + null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) // Notify the user storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins, sentTimestamp) } From 40015c2898a7ecac819db877d96e9973fd8a62e0 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Fri, 9 Apr 2021 16:36:18 +1000 Subject: [PATCH 13/17] clean --- .../messaging/messages/signal/IncomingMediaMessage.java | 2 -- .../dataextraction/DataExtractionNotificationInfoMessage.kt | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java index 53e48a5897..1d359a6c64 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java @@ -147,8 +147,6 @@ public class IncomingMediaMessage { return linkPreviews; } - public DataExtractionNotificationInfoMessage getDataExtractionNotification() { return dataExtractionNotification; } - public boolean isUnidentified() { return unidentified; } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt index 64d7af7ff1..108b51c7aa 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt @@ -13,4 +13,4 @@ class DataExtractionNotificationInfoMessage { this.kind = kind } -} \ No newline at end of file +} From 2bce2738b30b3d15670f325ad6eb501836dead80 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Mon, 12 Apr 2021 12:02:41 +1000 Subject: [PATCH 14/17] media saved notification is sent only when incoming media are saved --- .../org/thoughtcrime/securesms/MediaOverviewActivity.java | 7 +++++-- .../org/thoughtcrime/securesms/MediaPreviewActivity.java | 6 ++++-- .../securesms/conversation/ConversationFragment.java | 6 ++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java index 762d88b81c..fe6f249b0b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -353,8 +353,11 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { saveTask.executeOnExecutor(THREAD_POOL_EXECUTOR, attachments.toArray(new SaveAttachmentTask.Attachment[attachments.size()])); actionMode.finish(); - // Sending a Data extraction notification - sendMediaSavedNotificationIfNeeded(); + // Sending a Data extraction notification (for incoming attachments only) + boolean containsIncoming = mediaRecords.parallelStream().anyMatch(m -> !m.isOutgoing()); + if (containsIncoming) { + sendMediaSavedNotificationIfNeeded(); + } } }.execute(); }) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index 8bc53250a4..03e1c6b4f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -357,8 +357,10 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im saveTask.executeOnExecutor( AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null)); - // Sending a Data extraction notification - sendMediaSavedNotificationIfNeeded(); + // Sending a Data extraction notification (for incoming attachments only) + if(!mediaItem.outgoing) { + sendMediaSavedNotificationIfNeeded(); + } }) .execute(); }); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index d69574c4d1..32668cb247 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -746,8 +746,10 @@ public class ConversationFragment extends Fragment if (!Util.isEmpty(attachments)) { SaveAttachmentTask saveTask = new SaveAttachmentTask(getActivity()); saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, attachments.toArray(new SaveAttachmentTask.Attachment[0])); - // Sending a Data extraction notification - sendMediaSavedNotificationIfNeeded(); + // Sending a Data extraction notification (for incoming attachments only) + if(!message.isOutgoing()) { + sendMediaSavedNotificationIfNeeded(); + } return; } From 3bfef2d0cdf1a92eccfd9ebc6eae66f90f45a119 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 20 Apr 2021 16:55:46 +1000 Subject: [PATCH 15/17] e UpdateMessageBuilder to generate data extraction message --- .../securesms/database/model/MessageRecord.java | 4 ++++ app/src/main/res/values-fr/strings.xml | 2 ++ .../messaging/utilities/UpdateMessageBuilder.kt | 14 ++++++++++---- libsession/src/main/res/values/strings.xml | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index af293d3833..954cedb150 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -27,6 +27,7 @@ import network.loki.messenger.R; import org.session.libsession.messaging.utilities.UpdateMessageBuilder; import org.session.libsession.messaging.utilities.UpdateMessageData; +import org.session.libsignal.service.internal.push.SignalServiceProtos; import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.SmsDatabase; import org.session.libsession.database.documents.IdentityKeyMismatch; @@ -97,6 +98,9 @@ public abstract class MessageRecord extends DisplayRecord { } else if (isExpirationTimerUpdate()) { int seconds = (int) (getExpiresIn() / 1000); return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing())); + } else if (isDataExtraction()) { + if (isScreenshotExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT, getIndividualRecipient().getAddress().serialize()))); + else if (isMediaSavedExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize()))); } // TODO below lines are left here for compatibility with older group update messages, it can be deleted later on else if (isGroupUpdate() && isOutgoing()) { diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f156dad77b..5fbc37a757 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -440,6 +440,8 @@ %1$s a désactivé les messages éphémères. Vous avez défini l’expiration des messages éphémères à %1$s. %1$s a défini l’expiration des messages éphémères à %2$s. + %1$s a pris une capture d’écran. + %1$s a sauvegardé un media. Votre numéro de sécurité avec %s a changé. Vous avez marqué votre numéro de sécurité avec %s comme vérifié Vous avez marqué votre numéro de sécurité avec %s comme vérifié à partir d’un autre appareil diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt index d6f446e364..7404d2e3ca 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt @@ -5,6 +5,7 @@ import org.session.libsession.R import org.session.libsession.messaging.MessagingConfiguration import org.session.libsession.utilities.ExpirationUtil import org.session.libsignal.service.api.messages.SignalServiceGroup +import org.session.libsignal.service.internal.push.SignalServiceProtos object UpdateMessageBuilder { @@ -82,7 +83,7 @@ object UpdateMessageBuilder { if (!isOutgoing && sender == null) return "" val senderName: String? = if (!isOutgoing) { MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender - } else { sender } + } else { context.getString(R.string.MessageRecord_you) } return if (duration <= 0) { if (isOutgoing) context.getString(R.string.MessageRecord_you_disabled_disappearing_messages) else context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, senderName) @@ -93,8 +94,13 @@ object UpdateMessageBuilder { } } - //TODO do this when the current update is merged - fun buildDataExtractionMessage(): String { - return "" + fun buildDataExtractionMessage(context: Context, kind: SignalServiceProtos.DataExtractionNotification.Type, sender: String? = null): String { + val senderName = MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender + return when (kind) { + SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT -> + context.getString(R.string.MessageRecord_s_took_a_screenshot, senderName) + SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED -> + context.getString(R.string.MessageRecord_media_saved_by_s, senderName) + } } } diff --git a/libsession/src/main/res/values/strings.xml b/libsession/src/main/res/values/strings.xml index 116b106017..ee0510385c 100644 --- a/libsession/src/main/res/values/strings.xml +++ b/libsession/src/main/res/values/strings.xml @@ -509,6 +509,8 @@ %1$s disabled disappearing messages. You set the disappearing message timer to %1$s %1$s set the disappearing message timer to %2$s + %1$s took a screenshot. + Media saved by %1$s. Your safety number with %s has changed. You marked your safety number with %s verified You marked your safety number with %s verified from another device From 7aa1f30c986574f6af7b6ada06ad5e20b7be34fe Mon Sep 17 00:00:00 2001 From: Brice-W Date: Tue, 20 Apr 2021 17:07:21 +1000 Subject: [PATCH 16/17] fix --- .../securesms/conversation/ConversationUpdateItem.java | 4 ++-- .../securesms/database/model/MessageRecord.java | 6 +++--- .../messaging/messages/signal/IncomingMediaMessage.java | 2 +- .../messaging/sending_receiving/MessageReceiverHandler.kt | 2 +- .../DataExtractionNotificationInfoMessage.kt | 2 +- .../messaging/utilities/UpdateMessageBuilder.kt | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 7218006755..91d1c4244b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -106,7 +106,7 @@ public class ConversationUpdateItem extends LinearLayout else if (messageRecord.isJoined()) setJoinedRecord(messageRecord); else if (messageRecord.isExpirationTimerUpdate()) setTimerRecord(messageRecord); else if (messageRecord.isScreenshotExtraction()) setDataExtractionRecord(messageRecord, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT); - else if (messageRecord.isMediaSavedExtraction()) setDataExtractionRecord(messageRecord, DataExtractionNotificationInfoMessage.Kind.MEDIASAVED); + else if (messageRecord.isMediaSavedExtraction()) setDataExtractionRecord(messageRecord, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED); else if (messageRecord.isEndSession()) setEndSessionRecord(messageRecord); else if (messageRecord.isIdentityUpdate()) setIdentityRecord(messageRecord); else if (messageRecord.isIdentityVerified() || @@ -154,7 +154,7 @@ public class ConversationUpdateItem extends LinearLayout @ColorInt int color = GeneralUtilitiesKt.getColorWithID(getResources(), R.color.text, getContext().getTheme()); if (kind == DataExtractionNotificationInfoMessage.Kind.SCREENSHOT) { icon.setImageResource(R.drawable.quick_camera_dark); - } else if (kind == DataExtractionNotificationInfoMessage.Kind.MEDIASAVED) { + } else if (kind == DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED) { icon.setImageResource(R.drawable.ic_file_download_white_36dp); } icon.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index 954cedb150..9ecb9bac2e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -25,9 +25,9 @@ import android.text.style.StyleSpan; import network.loki.messenger.R; +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage; import org.session.libsession.messaging.utilities.UpdateMessageBuilder; import org.session.libsession.messaging.utilities.UpdateMessageData; -import org.session.libsignal.service.internal.push.SignalServiceProtos; import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.SmsDatabase; import org.session.libsession.database.documents.IdentityKeyMismatch; @@ -99,8 +99,8 @@ public abstract class MessageRecord extends DisplayRecord { int seconds = (int) (getExpiresIn() / 1000); return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), isOutgoing())); } else if (isDataExtraction()) { - if (isScreenshotExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT, getIndividualRecipient().getAddress().serialize()))); - else if (isMediaSavedExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize()))); + if (isScreenshotExtraction()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, 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 else if (isGroupUpdate() && isOutgoing()) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java index 1d359a6c64..f235e84e92 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/signal/IncomingMediaMessage.java @@ -131,7 +131,7 @@ public class IncomingMediaMessage { public boolean isMediaSavedDataExtraction() { if (dataExtractionNotification == null) return false; else { - return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.MEDIASAVED; + return dataExtractionNotification.getKind() == DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED; } } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index e5d0c8e278..fc1b28e1cc 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -103,7 +103,7 @@ private fun MessageReceiver.handleDataExtractionNotification(message: DataExtrac val senderPublicKey = message.sender!! val notification: DataExtractionNotificationInfoMessage = when(message.kind) { is DataExtractionNotification.Kind.Screenshot -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.SCREENSHOT) - is DataExtractionNotification.Kind.MediaSaved -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.MEDIASAVED) + is DataExtractionNotification.Kind.MediaSaved -> DataExtractionNotificationInfoMessage(DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED) else -> return } storage.insertDataExtractionNotificationMessage(senderPublicKey, notification, message.sentTimestamp!!) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt index 108b51c7aa..aca360eca6 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/dataextraction/DataExtractionNotificationInfoMessage.kt @@ -4,7 +4,7 @@ class DataExtractionNotificationInfoMessage { enum class Kind { SCREENSHOT, - MEDIASAVED + MEDIA_SAVED } var kind: Kind? = null diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt index 7404d2e3ca..b2ad3ca2b3 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt @@ -3,9 +3,9 @@ package org.session.libsession.messaging.utilities import android.content.Context import org.session.libsession.R import org.session.libsession.messaging.MessagingConfiguration +import org.session.libsession.messaging.sending_receiving.dataextraction.DataExtractionNotificationInfoMessage import org.session.libsession.utilities.ExpirationUtil import org.session.libsignal.service.api.messages.SignalServiceGroup -import org.session.libsignal.service.internal.push.SignalServiceProtos object UpdateMessageBuilder { @@ -94,12 +94,12 @@ object UpdateMessageBuilder { } } - fun buildDataExtractionMessage(context: Context, kind: SignalServiceProtos.DataExtractionNotification.Type, sender: String? = null): String { + fun buildDataExtractionMessage(context: Context, kind: DataExtractionNotificationInfoMessage.Kind, sender: String? = null): String { val senderName = MessagingConfiguration.shared.storage.getDisplayNameForRecipient(sender!!) ?: sender return when (kind) { - SignalServiceProtos.DataExtractionNotification.Type.SCREENSHOT -> + DataExtractionNotificationInfoMessage.Kind.SCREENSHOT -> context.getString(R.string.MessageRecord_s_took_a_screenshot, senderName) - SignalServiceProtos.DataExtractionNotification.Type.MEDIA_SAVED -> + DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED -> context.getString(R.string.MessageRecord_media_saved_by_s, senderName) } } From d1e276bf0804a27fff918a9ac9edaabf6f6e81e5 Mon Sep 17 00:00:00 2001 From: Brice-W Date: Wed, 21 Apr 2021 13:43:29 +1000 Subject: [PATCH 17/17] disable data extraction notification sending --- .../java/org/thoughtcrime/securesms/MediaOverviewActivity.java | 3 ++- .../java/org/thoughtcrime/securesms/MediaPreviewActivity.java | 3 ++- .../securesms/conversation/ConversationFragment.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java index fe6f249b0b..66482c9c57 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -356,7 +356,8 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity { // Sending a Data extraction notification (for incoming attachments only) boolean containsIncoming = mediaRecords.parallelStream().anyMatch(m -> !m.isOutgoing()); if (containsIncoming) { - sendMediaSavedNotificationIfNeeded(); + //TODO uncomment line below when Data extraction will be activated + //sendMediaSavedNotificationIfNeeded(); } } }.execute(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index 876a33d09a..6edfca5e9d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -354,7 +354,8 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im new Attachment(mediaItem.uri, mediaItem.type, saveDate, null)); // Sending a Data extraction notification (for incoming attachments only) if(!mediaItem.outgoing) { - sendMediaSavedNotificationIfNeeded(); + //TODO uncomment line below when Data extraction will be activated + //sendMediaSavedNotificationIfNeeded(); } }) .execute(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 32668cb247..2aedad1119 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -748,7 +748,8 @@ public class ConversationFragment extends Fragment saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, attachments.toArray(new SaveAttachmentTask.Attachment[0])); // Sending a Data extraction notification (for incoming attachments only) if(!message.isOutgoing()) { - sendMediaSavedNotificationIfNeeded(); + //TODO uncomment line below when Data extraction will be activated + //sendMediaSavedNotificationIfNeeded(); } return; }