diff --git a/app/src/main/java/org/thoughtcrime/securesms/ExpirationDialog.java b/app/src/main/java/org/thoughtcrime/securesms/ExpirationDialog.java deleted file mode 100644 index 469629ed3f..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/ExpirationDialog.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.thoughtcrime.securesms; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - -import org.session.libsession.utilities.ExpirationUtil; - -import cn.carbswang.android.numberpickerview.library.NumberPickerView; -import network.loki.messenger.R; - -public class ExpirationDialog extends AlertDialog { - - protected ExpirationDialog(Context context) { - super(context); - } - - protected ExpirationDialog(Context context, int theme) { - super(context, theme); - } - - protected ExpirationDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { - super(context, cancelable, cancelListener); - } - - public static void show(final Context context, - final int currentExpiration, - final @NonNull OnClickListener listener) - { - final View view = createNumberPickerView(context, currentExpiration); - - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(context.getString(R.string.ExpirationDialog_disappearing_messages)); - builder.setView(view); - builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { - int selected = ((NumberPickerView)view.findViewById(R.id.expiration_number_picker)).getValue(); - listener.onClick(context.getResources().getIntArray(R.array.expiration_times)[selected]); - }); - builder.setNegativeButton(android.R.string.cancel, null); - builder.show(); - } - - private static View createNumberPickerView(final Context context, final int currentExpiration) { - final LayoutInflater inflater = LayoutInflater.from(context); - final View view = inflater.inflate(R.layout.expiration_dialog, null); - final NumberPickerView numberPickerView = view.findViewById(R.id.expiration_number_picker); - final TextView textView = view.findViewById(R.id.expiration_details); - final int[] expirationTimes = context.getResources().getIntArray(R.array.expiration_times); - final String[] expirationDisplayValues = new String[expirationTimes.length]; - - int selectedIndex = expirationTimes.length - 1; - - for (int i=0;i= expirationTimes[i]) && - (i == expirationTimes.length -1 || currentExpiration < expirationTimes[i+1])) { - selectedIndex = i; - } - } - - numberPickerView.setDisplayedValues(expirationDisplayValues); - numberPickerView.setMinValue(0); - numberPickerView.setMaxValue(expirationTimes.length-1); - - NumberPickerView.OnValueChangeListener listener = (picker, oldVal, newVal) -> { - if (newVal == 0) { - textView.setText(R.string.ExpirationDialog_your_messages_will_not_expire); - } else { - textView.setText(context.getString(R.string.ExpirationDialog_your_messages_will_disappear_s_after_they_have_been_seen, picker.getDisplayedValues()[newVal])); - } - }; - - numberPickerView.setOnValueChangedListener(listener); - numberPickerView.setValue(selectedIndex); - listener.onValueChange(numberPickerView, selectedIndex, selectedIndex); - - return view; - } - - public interface OnClickListener { - public void onClick(int expirationTime); - } - -} 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 caf9925262..5b0925f921 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 @@ -112,6 +112,9 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() { } }) } + binding.buttonSet.setOnClickListener { + viewModel.onSetClick() + } lifecycleScope.launchWhenStarted { launch { viewModel.selectedExpirationType.collect { type -> @@ -119,6 +122,12 @@ class ExpirationSettingsActivity: PassphraseRequiredActionBarActivity() { deleteTypeOptionAdapter.setSelectedPosition(max(0, position)) } } + launch { + viewModel.selectedExpirationTimer.collect { expirationTimer -> + val position = deleteTypeOptions.indexOfFirst { it.value.toIntOrNull() == expirationTimer } + timerOptionAdapter.setSelectedPosition(max(0, position)) + } + } launch { viewModel.expirationTimerOptions.collect { options -> binding.textViewTimer.isVisible = options.isNotEmpty() && viewModel.showExpirationTypeSelector 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 b851cc14a8..3f39931b9d 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 @@ -11,8 +11,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType +import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.preferences.RadioOption @@ -20,29 +22,37 @@ class ExpirationSettingsViewModel( private val threadId: Long, private val afterReadOptions: List, private val afterSendOptions: List, - private val threadDb: ThreadDatabase + private val threadDb: ThreadDatabase, + private val storage: Storage ) : ViewModel() { var showExpirationTypeSelector: Boolean = false private set + private var expirationConfig: ExpirationConfiguration? = null + private val _recipient = MutableStateFlow(null) val recipient: StateFlow = _recipient private val _selectedExpirationType = MutableStateFlow(null) val selectedExpirationType: StateFlow = _selectedExpirationType + private val _selectedExpirationTimer = MutableStateFlow(0) + val selectedExpirationTimer: StateFlow = _selectedExpirationTimer + private val _expirationTimerOptions = MutableStateFlow>(emptyList()) val expirationTimerOptions: StateFlow> = _expirationTimerOptions init { viewModelScope.launch { + expirationConfig = storage.getExpirationConfiguration(threadId) val recipient = threadDb.getRecipientForThreadId(threadId) _recipient.value = recipient showExpirationTypeSelector = recipient?.isContactRecipient == true && recipient.isLocalNumber == false - } - if (recipient.value?.isLocalNumber == true || recipient.value?.isClosedGroupRecipient == true) { - _selectedExpirationType.value = ExpirationType.DELETE_AFTER_SEND + if (recipient?.isLocalNumber == true || recipient?.isClosedGroupRecipient == true) { + _selectedExpirationType.value = ExpirationType.DELETE_AFTER_SEND + } + _selectedExpirationTimer.value = expirationConfig?.durationSeconds ?: 0 } selectedExpirationType.mapLatest { when (it) { @@ -60,7 +70,14 @@ class ExpirationSettingsViewModel( } fun onExpirationTimerSelected(option: RadioOption) { + _selectedExpirationTimer.value = option.value.toIntOrNull() ?: 0 + } + fun onSetClick() = viewModelScope.launch { + val expiresIn = _selectedExpirationTimer.value + val expiryType = _selectedExpirationType.value?.number ?: 0 + val expiryChangeTimestamp = System.currentTimeMillis() + threadDb.updateExpiryConfig(threadId, expiresIn, expiryType, expiryChangeTimestamp) } @dagger.assisted.AssistedFactory @@ -77,7 +94,8 @@ class ExpirationSettingsViewModel( @Assisted private val threadId: Long, @Assisted("afterRead") private val afterReadOptions: List, @Assisted("afterSend") private val afterSendOptions: List, - private val threadDb: ThreadDatabase + private val threadDb: ThreadDatabase, + private val storage: Storage ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { @@ -85,7 +103,8 @@ class ExpirationSettingsViewModel( threadId, afterReadOptions, afterSendOptions, - threadDb + threadDb, + storage ) as T } } 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 85ae536155..bf28d663b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -12,7 +12,7 @@ import org.session.libsession.messaging.jobs.Job import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.MessageReceiveJob import org.session.libsession.messaging.jobs.MessageSendJob -import org.session.libsession.messaging.messages.ExpirationSettingsConfiguration +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.MessageRequestResponse @@ -962,12 +962,31 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return recipientDb.blockedContacts } - override fun getExpirationSettingsConfiguration(threadId: Long): ExpirationSettingsConfiguration? { + override fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? { + val threadDb = DatabaseComponent.get(context).threadDatabase() + threadDb.readerFor(threadDb.conversationList).use { reader -> + while (reader.next != null) { + val thread = reader.current + if (thread.recipient.isClosedGroupRecipient || thread.recipient.isContactRecipient) { + return ExpirationConfiguration( + thread.threadId, + thread.expiresIn.toInt(), + thread.expiryType, + thread.expiryChangeTimestamp + ) + } + } + } return null } - override fun addExpirationSettingsConfiguration(config: ExpirationSettingsConfiguration) { - + override fun updateExpirationConfiguration(config: ExpirationConfiguration) { + DatabaseComponent.get(context).threadDatabase().updateExpiryConfig( + config.threadId, + config.durationSeconds, + config.expirationType?.number ?: 0, + config.lastChangeTimestampMs + ) } override fun getExpiringMessages(messageIds: LongArray): List> { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 02a82de1d4..f9f92d18c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -18,6 +18,7 @@ package org.thoughtcrime.securesms.database; import static org.session.libsession.utilities.GroupUtil.CLOSED_GROUP_PREFIX; +import static org.session.libsession.utilities.GroupUtil.OPEN_GROUP_INBOX_PREFIX; import static org.session.libsession.utilities.GroupUtil.OPEN_GROUP_PREFIX; import static org.thoughtcrime.securesms.database.GroupDatabase.GROUP_ID; @@ -96,6 +97,8 @@ public class ThreadDatabase extends Database { public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count"; public static final String READ_RECEIPT_COUNT = "read_receipt_count"; public static final String EXPIRES_IN = "expires_in"; + public static final String EXPIRY_TYPE = "expiry_type"; + public static final String EXPIRY_CHANGE_TIMESTAMP= "expiry_change_timestamp"; public static final String LAST_SEEN = "last_seen"; public static final String HAS_SENT = "has_sent"; public static final String IS_PINNED = "is_pinned"; @@ -118,7 +121,8 @@ public class ThreadDatabase extends Database { private static final String[] THREAD_PROJECTION = { ID, DATE, MESSAGE_COUNT, ADDRESS, SNIPPET, SNIPPET_CHARSET, READ, UNREAD_COUNT, TYPE, ERROR, SNIPPET_TYPE, - SNIPPET_URI, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT, IS_PINNED + SNIPPET_URI, ARCHIVED, STATUS, DELIVERY_RECEIPT_COUNT, EXPIRES_IN, LAST_SEEN, READ_RECEIPT_COUNT, IS_PINNED, + EXPIRY_TYPE, EXPIRY_CHANGE_TIMESTAMP }; private static final List TYPED_THREAD_PROJECTION = Stream.of(THREAD_PROJECTION) @@ -135,6 +139,30 @@ public class ThreadDatabase extends Database { "ADD COLUMN " + IS_PINNED + " INTEGER DEFAULT 0;"; } + public static String getCreateExpiryTypeCommand() { + return "ALTER TABLE "+ TABLE_NAME + " " + + "ADD COLUMN " + EXPIRY_TYPE + " INTEGER DEFAULT 0;"; + } + + public static String getCreateExpiryChangeTimestampCommand() { + return "ALTER TABLE "+ TABLE_NAME + " " + + "ADD COLUMN " + EXPIRY_CHANGE_TIMESTAMP + " INTEGER DEFAULT 0;"; + } + + public static String getUpdateGroupConversationExpiryTypeCommand() { + return "UPDATE " + TABLE_NAME + " SET " + EXPIRY_TYPE + " = 1 " + + "WHERE " + ADDRESS + " LIKE '" + CLOSED_GROUP_PREFIX + "%'" + + "AND " + EXPIRES_IN + " > 0"; + } + + public static String getUpdateOneToOneConversationExpiryTypeCommand() { + return "UPDATE " + TABLE_NAME + " SET " + EXPIRY_TYPE + " = 2 " + + "WHERE " + ADDRESS + " NOT LIKE '" + CLOSED_GROUP_PREFIX + "%'" + + "AND " + ADDRESS + " NOT LIKE '" + OPEN_GROUP_PREFIX + "%'" + + "AND " + ADDRESS + " NOT LIKE '" + OPEN_GROUP_INBOX_PREFIX + "%'" + + "AND " + EXPIRES_IN + " > 0"; + } + public ThreadDatabase(Context context, SQLCipherOpenHelper databaseHelper) { super(context, databaseHelper); } @@ -200,6 +228,18 @@ public class ThreadDatabase extends Database { notifyConversationListListeners(); } + public void updateExpiryConfig(long threadId, int expiresIn, int expiryType, long expiryChangeTimestamp) { + ContentValues contentValues = new ContentValues(3); + + contentValues.put(EXPIRES_IN, expiresIn); + contentValues.put(EXPIRY_TYPE, expiryType); + contentValues.put(EXPIRY_CHANGE_TIMESTAMP, expiryChangeTimestamp); + + SQLiteDatabase db = databaseHelper.getWritableDatabase(); + db.update(TABLE_NAME, contentValues, ID + " = ?", new String[] {threadId + ""}); + notifyConversationListListeners(); + } + private void deleteThread(long threadId) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId + ""}); @@ -909,6 +949,8 @@ public class ThreadDatabase extends Database { int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.DELIVERY_RECEIPT_COUNT)); int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ_RECEIPT_COUNT)); long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN)); + int expiryType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRY_TYPE)); + long expiryChangeTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRY_CHANGE_TIMESTAMP)); long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN)); Uri snippetUri = getSnippetUri(cursor); boolean pinned = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.IS_PINNED)) != 0; @@ -919,7 +961,7 @@ public class ThreadDatabase extends Database { return new ThreadRecord(body, snippetUri, recipient, date, count, unreadCount, threadId, deliveryReceiptCount, status, type, - distributionType, archived, expiresIn, lastSeen, readReceiptCount, pinned); + distributionType, archived, expiresIn, lastSeen, readReceiptCount, pinned, expiryType, expiryChangeTimestamp); } private @Nullable Uri getSnippetUri(Cursor cursor) { 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 d2266b3924..78606d9166 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 @@ -75,9 +75,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { private static final int lokiV36 = 57; private static final int lokiV37 = 58; private static final int lokiV38 = 59; + private static final int lokiV39 = 60; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes - private static final int DATABASE_VERSION = lokiV38; + private static final int DATABASE_VERSION = lokiV39; private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -180,6 +181,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { db.execSQL(LokiAPIDatabase.RESET_SEQ_NO); // probably not needed but consistent with all migrations db.execSQL(EmojiSearchDatabase.CREATE_EMOJI_SEARCH_TABLE_COMMAND); db.execSQL(ReactionDatabase.CREATE_REACTION_TABLE_COMMAND); + db.execSQL(ThreadDatabase.getCreateExpiryTypeCommand()); + db.execSQL(ThreadDatabase.getCreateExpiryChangeTimestampCommand()); executeStatements(db, SmsDatabase.CREATE_INDEXS); executeStatements(db, MmsDatabase.CREATE_INDEXS); @@ -414,6 +417,13 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { db.execSQL(EmojiSearchDatabase.CREATE_EMOJI_SEARCH_TABLE_COMMAND); } + if (oldVersion < lokiV39) { + db.execSQL(ThreadDatabase.getCreateExpiryTypeCommand()); + db.execSQL(ThreadDatabase.getCreateExpiryChangeTimestampCommand()); + db.execSQL(ThreadDatabase.getUpdateGroupConversationExpiryTypeCommand()); + db.execSQL(ThreadDatabase.getUpdateOneToOneConversationExpiryTypeCommand()); + } + db.setTransactionSuccessful(); } finally { db.endTransaction(); 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 6ce69a591a..f02ce2b70a 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 @@ -29,6 +29,7 @@ import androidx.annotation.Nullable; import org.session.libsession.utilities.ExpirationUtil; import org.session.libsession.utilities.recipients.Recipient; +import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType; import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.SmsDatabase; @@ -48,6 +49,8 @@ public class ThreadRecord extends DisplayRecord { private final int distributionType; private final boolean archived; private final long expiresIn; + private final int expiryType; + private final long expiryChangeTimestamp; private final long lastSeen; private final boolean pinned; private final int recipientHash; @@ -56,7 +59,7 @@ public class ThreadRecord extends DisplayRecord { @NonNull Recipient recipient, long date, long count, int unreadCount, long threadId, int deliveryReceiptCount, int status, long snippetType, int distributionType, boolean archived, long expiresIn, long lastSeen, - int readReceiptCount, boolean pinned) + int readReceiptCount, boolean pinned, int expiryType, long expiryChangeTimestamp) { super(body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount); this.snippetUri = snippetUri; @@ -65,6 +68,8 @@ public class ThreadRecord extends DisplayRecord { this.distributionType = distributionType; this.archived = archived; this.expiresIn = expiresIn; + this.expiryType = expiryType; + this.expiryChangeTimestamp = expiryChangeTimestamp; this.lastSeen = lastSeen; this.pinned = pinned; this.recipientHash = recipient.hashCode(); @@ -169,6 +174,15 @@ public class ThreadRecord extends DisplayRecord { return expiresIn; } + @Nullable + public ExpirationType getExpiryType() { + return ExpirationType.valueOf(expiryType); + } + + public long getExpiryChangeTimestamp() { + return expiryChangeTimestamp; + } + public long getLastSeen() { return lastSeen; } diff --git a/app/src/main/res/layout/expiration_dialog.xml b/app/src/main/res/layout/expiration_dialog.xml deleted file mode 100644 index 03b3026611..0000000000 --- a/app/src/main/res/layout/expiration_dialog.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 675ab21b75..d19632b081 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -8,7 +8,7 @@ import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.jobs.AttachmentUploadJob import org.session.libsession.messaging.jobs.Job import org.session.libsession.messaging.jobs.MessageSendJob -import org.session.libsession.messaging.messages.ExpirationSettingsConfiguration +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.MessageRequestResponse @@ -199,7 +199,7 @@ interface StorageProtocol { fun deleteReactions(messageId: Long, mms: Boolean) fun unblock(toUnblock: List) fun blockedContacts(): List - fun getExpirationSettingsConfiguration(threadId: Long): ExpirationSettingsConfiguration? - fun addExpirationSettingsConfiguration(config: ExpirationSettingsConfiguration) + fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? + fun updateExpirationConfiguration(config: ExpirationConfiguration) fun getExpiringMessages(messageIds: LongArray): List> } diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationSettingsConfiguration.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt similarity index 78% rename from libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationSettingsConfiguration.kt rename to libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt index ee11a2c889..508f935a31 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationSettingsConfiguration.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt @@ -2,10 +2,11 @@ package org.session.libsession.messaging.messages import org.session.libsignal.protos.SignalServiceProtos.Content.ExpirationType -class ExpirationSettingsConfiguration( +class ExpirationConfiguration( val threadId: Long = -1, - val isEnabled: Boolean = false, val durationSeconds: Int = 0, val expirationType: ExpirationType? = null, val lastChangeTimestampMs: Long = 0 -) \ No newline at end of file +) { + val isEnabled = durationSeconds > 0 +} \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt index b934254245..30ce3a1ba5 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/Message.kt @@ -41,7 +41,7 @@ abstract class Message { fun setExpirationSettingsConfigIfNeeded(builder: SignalServiceProtos.Content.Builder) { val threadId = threadID ?: return - val config = MessagingModuleConfiguration.shared.storage.getExpirationSettingsConfiguration(threadId) ?: return + val config = MessagingModuleConfiguration.shared.storage.getExpirationConfiguration(threadId) ?: return builder.expirationTimer = config.durationSeconds if (config.isEnabled) { builder.expirationType = config.expirationType diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt index 5a35864ba2..12c8627b8d 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt @@ -227,7 +227,7 @@ object MessageSender { val address = if (isSyncMessage && message is VisibleMessage) message.syncTarget else message.recipient storage.getOrCreateThreadIdFor(address!!) } - val config = storage.getExpirationSettingsConfiguration(threadId) ?: return null + val config = storage.getExpirationConfiguration(threadId) ?: return null return if (config.isEnabled && (config.expirationType == ExpirationType.DELETE_AFTER_SEND || isSyncMessage)) { config.durationSeconds * 1000L } else null 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 7c55c2428b..5249772f08 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 @@ -5,7 +5,7 @@ import org.session.libsession.avatars.AvatarHelper import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.jobs.BackgroundGroupAddJob import org.session.libsession.messaging.jobs.JobQueue -import org.session.libsession.messaging.messages.ExpirationSettingsConfiguration +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage @@ -60,7 +60,7 @@ internal fun MessageReceiver.isBlocked(publicKey: String): Boolean { } fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) { - updateExpirationSettingsConfigIfNeeded(message, proto, openGroupID) + updateExpirationConfigurationIfNeeded(message, proto, openGroupID) when (message) { is ReadReceipt -> handleReadReceipt(message) is TypingIndicator -> handleTypingIndicator(message) @@ -80,24 +80,22 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, } } -fun updateExpirationSettingsConfigIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) { +fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) { if (!proto.hasLastDisappearingMessageChangeTimestamp()) return val storage = MessagingModuleConfiguration.shared.storage val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID) if (threadID <= 0) return - val localConfig = storage.getExpirationSettingsConfiguration(threadID) + val localConfig = storage.getExpirationConfiguration(threadID) if (localConfig == null || localConfig.lastChangeTimestampMs < proto.lastDisappearingMessageChangeTimestamp) return val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0 - val isEnabled = durationSeconds != 0 val type = if (proto.hasExpirationType()) proto.expirationType else null - val remoteConfig = ExpirationSettingsConfiguration( + val remoteConfig = ExpirationConfiguration( threadID, - isEnabled, durationSeconds, type, proto.lastDisappearingMessageChangeTimestamp ) - storage.addExpirationSettingsConfiguration(remoteConfig) + storage.updateExpirationConfiguration(remoteConfig) } // region Control Messages @@ -116,7 +114,7 @@ private fun MessageReceiver.handleSyncedExpiriesMessage(message: SyncedExpiriesM val userPublicKey = storage.getUserPublicKey() ?: return if (userPublicKey != message.sender) return message.conversationExpiries.forEach { (syncTarget, syncedExpiries) -> - val config = storage.getExpirationSettingsConfiguration(storage.getOrCreateThreadIdFor(syncTarget)) ?: return@forEach + val config = storage.getExpirationConfiguration(storage.getOrCreateThreadIdFor(syncTarget)) ?: return@forEach syncedExpiries.forEach { syncedExpiry -> val startedAtMs = syncedExpiry.expirationTimestamp!! - config.durationSeconds * 1000 SSKEnvironment.shared.messageExpirationManager.startAnyExpiration(startedAtMs, syncTarget)