From 487f99ab931d0f6dda10ee80c8aec0b49cb2de10 Mon Sep 17 00:00:00 2001 From: charles Date: Mon, 19 Dec 2022 19:37:22 +1100 Subject: [PATCH] Fix expiry timer update handling --- .../conversation/ConversationActionBarView.kt | 8 ++++++- .../expiration/ExpirationSettingsViewModel.kt | 11 +++++---- .../ExpirationConfigurationDatabase.kt | 1 + .../securesms/dependencies/DatabaseModule.kt | 6 +++++ .../service/ExpiringMessageManager.java | 15 +----------- .../ReceivedMessageHandler.kt | 23 ++++++++++++++++--- .../libsession/utilities/SSKEnvironment.kt | 2 +- 7 files changed, 42 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActionBarView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActionBarView.kt index 9d1149849b..2e2b5a5d93 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActionBarView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActionBarView.kt @@ -20,6 +20,7 @@ import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.open_groups.OpenGroup import org.session.libsession.utilities.ExpirationUtil import org.session.libsession.utilities.recipients.Recipient +import org.session.libsignal.protos.SignalServiceProtos import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities import org.thoughtcrime.securesms.database.GroupDatabase import org.thoughtcrime.securesms.database.LokiAPIDatabase @@ -104,9 +105,14 @@ class ConversationActionBarView : LinearLayout { fun updateSubtitle(recipient: Recipient, openGroup: OpenGroup? = null, config: ExpirationConfiguration? = null) { val settings = mutableListOf() if (config?.isEnabled == true) { + val prefix = if (config.expirationType == SignalServiceProtos.Content.ExpirationType.DELETE_AFTER_READ) { + context.getString(R.string.expiration_type_disappear_after_read) + } else { + context.getString(R.string.expiration_type_disappear_after_send) + } settings.add( ConversationSetting( - "${context.getString(R.string.expiration_type_disappear_after_read)} - ${ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, config?.durationSeconds ?: 0)}" , + "$prefix - ${ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, config.durationSeconds)}" , ConversationSettingType.EXPIRATION, R.drawable.ic_timer ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsViewModel.kt index ba9ce0f053..c754412343 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsViewModel.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.launch import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.sending_receiving.MessageSender +import org.session.libsession.utilities.SSKEnvironment.MessageExpirationManagerProtocol import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType import org.thoughtcrime.securesms.database.Storage @@ -25,6 +26,7 @@ class ExpirationSettingsViewModel( private val threadId: Long, private val afterReadOptions: List, private val afterSendOptions: List, + private val messageExpirationManager: MessageExpirationManagerProtocol, private val threadDb: ThreadDatabase, private val storage: Storage ) : ViewModel() { @@ -54,11 +56,6 @@ class ExpirationSettingsViewModel( _uiState.update { it.copy(showExpirationTypeSelector = !ExpirationConfiguration.isNewConfigEnabled || (recipient?.isContactRecipient == true && !recipient.isLocalNumber)) } - if (ExpirationConfiguration.isNewConfigEnabled && (recipient?.isLocalNumber == true || recipient?.isClosedGroupRecipient == true)) { - _selectedExpirationType.value = ExpirationType.DELETE_AFTER_SEND.number - } else { - _selectedExpirationType.value = expirationConfig?.expirationTypeValue ?: -1 - } _selectedExpirationType.value = if (ExpirationConfiguration.isNewConfigEnabled) { if (recipient?.isLocalNumber == true || recipient?.isClosedGroupRecipient == true) { ExpirationType.DELETE_AFTER_SEND.number @@ -108,6 +105,8 @@ class ExpirationSettingsViewModel( val address = recipient.value?.address ?: return@launch message.recipient = address.serialize() message.sentTimestamp = System.currentTimeMillis() + messageExpirationManager.setExpirationTimer(message) + MessageSender.send(message, address) _uiState.update { it.copy(settingsSaved = true) @@ -128,6 +127,7 @@ class ExpirationSettingsViewModel( @Assisted private val threadId: Long, @Assisted("afterRead") private val afterReadOptions: List, @Assisted("afterSend") private val afterSendOptions: List, + private val messageExpirationManager: MessageExpirationManagerProtocol, private val threadDb: ThreadDatabase, private val storage: Storage ) : ViewModelProvider.Factory { @@ -137,6 +137,7 @@ class ExpirationSettingsViewModel( threadId, afterReadOptions, afterSendOptions, + messageExpirationManager, threadDb, storage ) as T diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt index 67e2b42c79..3f8c73aba4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt @@ -83,6 +83,7 @@ class ExpirationConfigurationDatabase(context: Context, helper: SQLCipherOpenHel writableDatabase.insert(TABLE_NAME, null, values) writableDatabase.setTransactionSuccessful() + notifyConversationListeners(configuration.threadId) } finally { writableDatabase.endTransaction() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt index c1a71bf497..d34cc3f25b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt @@ -8,12 +8,14 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import net.sqlcipher.database.SQLiteDatabase import org.session.libsession.database.MessageDataProvider +import org.session.libsession.utilities.SSKEnvironment import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider import org.thoughtcrime.securesms.crypto.AttachmentSecret import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider import org.thoughtcrime.securesms.database.* import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper +import org.thoughtcrime.securesms.service.ExpiringMessageManager import javax.inject.Singleton @Module @@ -25,6 +27,10 @@ object DatabaseModule { SQLiteDatabase.loadLibs(context) } + @Provides + @Singleton + fun provideMessageExpirationManagerProtocol(@ApplicationContext context: Context): SSKEnvironment.MessageExpirationManagerProtocol = ExpiringMessageManager(context) + @Provides @Singleton fun provideAttachmentSecret(@ApplicationContext context: Context) = AttachmentSecretProvider.getInstance(context).orCreateAttachmentSecret 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 f09dee8b55..a88c0bcca2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java @@ -69,20 +69,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM } @Override - public void setExpirationTimer(@NotNull ExpirationTimerUpdate message, @Nullable Integer expirationType) { - try { - ThreadDatabase threadDb = DatabaseComponent.get(context).threadDatabase(); - long threadId = threadDb.getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(message.getSender()), false)); - if (message.getGroupPublicKey() != null) { - Recipient recipient = Recipient.from(context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(message.getGroupPublicKey())), false); - threadId = threadDb.getOrCreateThreadIdFor(recipient); - } - DatabaseComponent.get(context).expirationConfigurationDatabase().setExpirationConfiguration( - new ExpirationConfiguration(threadId, message.getDuration(), expirationType, System.currentTimeMillis()) - ); - } catch (Exception e) { - Log.e("Loki", "Failed to update expiration configuration."); - } + public void setExpirationTimer(@NotNull ExpirationTimerUpdate message) { String userPublicKey = TextSecurePreferences.getLocalNumber(context); String senderPublicKey = message.getSender(); diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index ffbd599509..d0111e85a7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -33,8 +33,10 @@ import org.session.libsession.messaging.utilities.SodiumUtilities import org.session.libsession.messaging.utilities.WebRtcUtils import org.session.libsession.snode.SnodeAPI import org.session.libsession.utilities.Address +import org.session.libsession.utilities.Address.Companion.fromSerialized import org.session.libsession.utilities.GroupRecord import org.session.libsession.utilities.GroupUtil +import org.session.libsession.utilities.GroupUtil.doubleEncodeGroupID import org.session.libsession.utilities.ProfileKeyUtil import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.TextSecurePreferences @@ -92,7 +94,7 @@ fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalService val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID) if (threadID <= 0) return val localConfig = storage.getExpirationConfiguration(threadID) - if (localConfig == null || localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) return + if (localConfig != null && localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) return val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0 val type = if (proto.hasExpirationType()) proto.expirationType else null val remoteConfig = ExpirationConfiguration( @@ -102,6 +104,9 @@ fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalService proto.lastDisappearingMessageChangeTimestamp ) storage.setExpirationConfiguration(remoteConfig) + if (message is ExpirationTimerUpdate) { + SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message) + } } // region Control Messages @@ -158,13 +163,25 @@ fun MessageReceiver.cancelTypingIndicatorsIfNeeded(senderPublicKey: String) { private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimerUpdate) { if (ExpirationConfiguration.isNewConfigEnabled) return - val recipient = Recipient.from(MessagingModuleConfiguration.shared.context, Address.fromSerialized(message.sender!!), false) + val module = MessagingModuleConfiguration.shared + val recipient = Recipient.from(module.context, Address.fromSerialized(message.sender!!), false) val type = when { recipient.isContactRecipient -> ExpirationType.DELETE_AFTER_READ recipient.isGroupRecipient -> ExpirationType.DELETE_AFTER_SEND else -> null } - SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number) + try { + var threadId: Long = module.storage.getOrCreateThreadIdFor(fromSerialized(message.sender!!)) + if (message.groupPublicKey != null) { + threadId = module.storage.getOrCreateThreadIdFor(fromSerialized(doubleEncodeGroupID(message.groupPublicKey!!))) + } + module.storage.setExpirationConfiguration( + ExpirationConfiguration(threadId, message.duration!!, type?.number ?: -1, System.currentTimeMillis()) + ) + } catch (e: Exception) { + Log.e("Loki", "Failed to update expiration configuration.") + } + SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message) } private fun MessageReceiver.handleDataExtractionNotification(message: DataExtractionNotification) { diff --git a/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt b/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt index 1deda649a0..b97ac33a73 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt @@ -36,7 +36,7 @@ class SSKEnvironment( } interface MessageExpirationManagerProtocol { - fun setExpirationTimer(message: ExpirationTimerUpdate, expirationType: Int?) + fun setExpirationTimer(message: ExpirationTimerUpdate) fun startAnyExpiration(timestamp: Long, author: String) }