diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsActivity.kt index 9ced182699..5422712202 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/expiration/ExpirationSettingsActivity.kt @@ -107,7 +107,7 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() { lifecycleScope.launchWhenStarted { launch { viewModel.selectedExpirationType.collect { type -> - val position = deleteTypeOptions.indexOfFirst { it.value.toIntOrNull() == type?.number } + val position = deleteTypeOptions.indexOfFirst { it.value.toIntOrNull() == type } deleteTypeOptionAdapter.setSelectedPosition(max(0, position)) } } @@ -208,7 +208,7 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() { setSupportActionBar(binding.toolbar) val actionBar = supportActionBar ?: return actionBar.title = getString(R.string.activity_expiration_settings_title) - actionBar.subtitle = if (viewModel.selectedExpirationType.value == ExpirationType.DELETE_AFTER_SEND) { + actionBar.subtitle = if (viewModel.selectedExpirationType.value == ExpirationType.DELETE_AFTER_SEND.number) { getString(R.string.activity_expiration_settings_subtitle_sent) } else { getString(R.string.activity_expiration_settings_subtitle) 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 fd35096894..acf7174237 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 @@ -34,8 +34,8 @@ class ExpirationSettingsViewModel( private val _recipient = MutableStateFlow(null) val recipient: StateFlow = _recipient - private val _selectedExpirationType = MutableStateFlow(null) - val selectedExpirationType: StateFlow = _selectedExpirationType + private val _selectedExpirationType = MutableStateFlow(null) + val selectedExpirationType: StateFlow = _selectedExpirationType private val _selectedExpirationTimer = MutableStateFlow(afterSendOptions.firstOrNull()) val selectedExpirationTimer: StateFlow = _selectedExpirationTimer @@ -49,10 +49,10 @@ class ExpirationSettingsViewModel( val recipient = threadDb.getRecipientForThreadId(threadId) _recipient.value = recipient showExpirationTypeSelector = !ExpirationConfiguration.isNewConfigEnabled || (recipient?.isContactRecipient == true && !recipient.isLocalNumber) - if (recipient?.isLocalNumber == true || recipient?.isClosedGroupRecipient == true) { - _selectedExpirationType.value = ExpirationType.DELETE_AFTER_SEND + if (ExpirationConfiguration.isNewConfigEnabled && (recipient?.isLocalNumber == true || recipient?.isClosedGroupRecipient == true)) { + _selectedExpirationType.value = ExpirationType.DELETE_AFTER_SEND.number } else { - _selectedExpirationType.value = expirationConfig?.expirationType + _selectedExpirationType.value = expirationConfig?.expirationTypeValue } _selectedExpirationTimer.value = when(expirationConfig?.expirationType) { ExpirationType.DELETE_AFTER_SEND -> afterSendOptions.find { it.value.toIntOrNull() == expirationConfig?.durationSeconds } @@ -62,8 +62,8 @@ class ExpirationSettingsViewModel( } selectedExpirationType.mapLatest { when (it) { - ExpirationType.DELETE_AFTER_SEND -> afterSendOptions - ExpirationType.DELETE_AFTER_READ -> afterReadOptions + 0, ExpirationType.DELETE_AFTER_SEND.number -> afterSendOptions + ExpirationType.DELETE_AFTER_READ.number -> afterReadOptions else -> emptyList() } }.onEach { options -> @@ -76,7 +76,7 @@ class ExpirationSettingsViewModel( } fun onExpirationTypeSelected(option: RadioOption) { - _selectedExpirationType.value = option.value.toIntOrNull()?.let { ExpirationType.valueOf(it) } + _selectedExpirationType.value = option.value.toIntOrNull() } fun onExpirationTimerSelected(option: RadioOption) { 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 a7c3bf252e..aac19f8390 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ExpirationConfigurationDatabase.kt @@ -7,7 +7,6 @@ import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.utilities.GroupUtil.CLOSED_GROUP_PREFIX import org.session.libsession.utilities.GroupUtil.OPEN_GROUP_INBOX_PREFIX import org.session.libsession.utilities.GroupUtil.OPEN_GROUP_PREFIX -import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper class ExpirationConfigurationDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) { @@ -51,7 +50,7 @@ class ExpirationConfigurationDatabase(context: Context, helper: SQLCipherOpenHel return ExpirationConfiguration( threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID)), durationSeconds = cursor.getInt(cursor.getColumnIndexOrThrow(DURATION_SECONDS)), - expirationType = ExpirationType.valueOf(cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRATION_TYPE))), + expirationTypeValue = cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRATION_TYPE)), updatedTimestampMs = cursor.getLong(cursor.getColumnIndexOrThrow(UPDATED_TIMESTAMP_MS)) ) } @@ -78,7 +77,7 @@ class ExpirationConfigurationDatabase(context: Context, helper: SQLCipherOpenHel val values = ContentValues().apply { put(THREAD_ID, configuration.threadId) put(DURATION_SECONDS, configuration.durationSeconds) - put(EXPIRATION_TYPE, configuration.expirationType?.number) + put(EXPIRATION_TYPE, configuration.expirationTypeValue) put(UPDATED_TIMESTAMP_MS, configuration.updatedTimestampMs) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index d3510c082a..f528b6c789 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -138,6 +138,11 @@ public class RecipientDatabase extends Database { "OR "+ADDRESS+" IN (SELECT "+GroupDatabase.TABLE_NAME+"."+GroupDatabase.ADMINS+" FROM "+GroupDatabase.TABLE_NAME+")))"; } + public static String getCreateDisappearingStateCommand() { + return "ALTER TABLE "+ TABLE_NAME + " " + + "ADD COLUMN " + DISAPPEARING_STATE + " INTEGER DEFAULT 0;"; + } + public static final int NOTIFY_TYPE_ALL = 0; public static final int NOTIFY_TYPE_MENTIONS = 1; public static final int NOTIFY_TYPE_NONE = 2; 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 77fff1b7e2..b8243d57a6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -544,7 +544,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, val recipient = Recipient.from(context, fromSerialized(groupID), false) val threadId = DatabaseComponent.get(context).threadDatabase().getThreadIdIfExistsFor(recipient) DatabaseComponent.get(context).expirationConfigurationDatabase().setExpirationConfiguration( - ExpirationConfiguration(threadId, duration, ExpirationType.DELETE_AFTER_SEND, System.currentTimeMillis()) + ExpirationConfiguration(threadId, duration, ExpirationType.DELETE_AFTER_SEND.number, System.currentTimeMillis()) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index f380c62a64..fff5459288 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -165,6 +165,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { db.execSQL(GroupDatabase.getCreateUpdatedTimestampCommand()); db.execSQL(RecipientDatabase.getCreateApprovedCommand()); db.execSQL(RecipientDatabase.getCreateApprovedMeCommand()); + db.execSQL(RecipientDatabase.getCreateDisappearingStateCommand()); db.execSQL(MmsDatabase.CREATE_MESSAGE_REQUEST_RESPONSE_COMMAND); db.execSQL(MmsDatabase.CREATE_REACTIONS_UNREAD_COMMAND); db.execSQL(SmsDatabase.CREATE_REACTIONS_UNREAD_COMMAND); @@ -418,6 +419,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { } if (oldVersion < lokiV39) { + db.execSQL(RecipientDatabase.getCreateDisappearingStateCommand()); db.execSQL(ExpirationConfigurationDatabase.CREATE_EXPIRATION_CONFIGURATION_TABLE_COMMAND); db.execSQL(ExpirationConfigurationDatabase.MIGRATE_GROUP_CONVERSATION_EXPIRY_TYPE_COMMAND); db.execSQL(ExpirationConfigurationDatabase.MIGRATE_ONE_TO_ONE_CONVERSATION_EXPIRY_TYPE_COMMAND); 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 64819aedd0..760622b12f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/ExpiringMessageManager.java @@ -14,7 +14,6 @@ import org.session.libsession.utilities.SSKEnvironment; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.recipients.Recipient; import org.session.libsignal.messages.SignalServiceGroup; -import org.session.libsignal.protos.SignalServiceProtos; import org.session.libsignal.utilities.Log; import org.session.libsignal.utilities.guava.Optional; import org.thoughtcrime.securesms.database.MmsDatabase; @@ -69,7 +68,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM } @Override - public void setExpirationTimer(@NotNull ExpirationTimerUpdate message, @Nullable SignalServiceProtos.Content.ExpirationType type) { + public void setExpirationTimer(@NotNull ExpirationTimerUpdate message, @Nullable Integer expirationType) { try { long threadId = message.getThreadID(); if (message.getGroupPublicKey() != null) { @@ -77,7 +76,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM threadId = DatabaseComponent.get(context).threadDatabase().getOrCreateThreadIdFor(recipient); } DatabaseComponent.get(context).expirationConfigurationDatabase().setExpirationConfiguration( - new ExpirationConfiguration(threadId, message.getDuration(), type, System.currentTimeMillis()) + new ExpirationConfiguration(threadId, message.getDuration(), expirationType, System.currentTimeMillis()) ); } catch (Exception e) { Log.e("Loki", "Failed to update expiration configuration."); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9e96207feb..e615f628b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -873,7 +873,7 @@ Close Dialog Disappearing Messages This setting applies to everyone in this conversation. - Use the original version of disappearing messages. + Original version of disappearing messages. Legacy Messages disappear after they have been sent. Disappear After Read diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt index dd2634303c..527628905c 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt @@ -5,10 +5,12 @@ import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType class ExpirationConfiguration( val threadId: Long = -1, val durationSeconds: Int = 0, - val expirationType: ExpirationType? = null, + val expirationTypeValue: Int? = null, val updatedTimestampMs: Long = 0 ) { val isEnabled = durationSeconds > 0 + val expirationType = expirationTypeValue?.let { ExpirationType.valueOf(it) } + companion object { val isNewConfigEnabled = System.currentTimeMillis() > 1_674_000_000_000 // 18/01/2023 } 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 a28c1046d1..c883e28c34 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 @@ -98,7 +98,7 @@ fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalService val remoteConfig = ExpirationConfiguration( threadID, durationSeconds, - type, + type?.number, proto.lastDisappearingMessageChangeTimestamp ) storage.setExpirationConfiguration(remoteConfig) @@ -164,7 +164,7 @@ private fun MessageReceiver.handleExpirationTimerUpdate(message: ExpirationTimer recipient.isContactRecipient || recipient.isGroupRecipient -> ExpirationType.DELETE_AFTER_SEND else -> null } - SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type) + SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number) } 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 bac6d4a7b4..1deda649a0 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/SSKEnvironment.kt @@ -4,7 +4,6 @@ import android.content.Context import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier import org.session.libsession.utilities.recipients.Recipient -import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType class SSKEnvironment( val typingIndicators: TypingIndicatorsProtocol, @@ -37,7 +36,7 @@ class SSKEnvironment( } interface MessageExpirationManagerProtocol { - fun setExpirationTimer(message: ExpirationTimerUpdate, type: ExpirationType?) + fun setExpirationTimer(message: ExpirationTimerUpdate, expirationType: Int?) fun startAnyExpiration(timestamp: Long, author: String) }