Connect migrated expiry to settings ui

This commit is contained in:
charles 2022-11-17 15:15:50 +11:00
parent b3e9708649
commit 3bb19e4df8
13 changed files with 143 additions and 155 deletions

View File

@ -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.length;i++) {
expirationDisplayValues[i] = ExpirationUtil.getExpirationDisplayValue(context, expirationTimes[i]);
if ((currentExpiration >= 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);
}
}

View File

@ -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

View File

@ -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<RadioOption>,
private val afterSendOptions: List<RadioOption>,
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<Recipient?>(null)
val recipient: StateFlow<Recipient?> = _recipient
private val _selectedExpirationType = MutableStateFlow<ExpirationType?>(null)
val selectedExpirationType: StateFlow<ExpirationType?> = _selectedExpirationType
private val _selectedExpirationTimer = MutableStateFlow(0)
val selectedExpirationTimer: StateFlow<Int> = _selectedExpirationTimer
private val _expirationTimerOptions = MutableStateFlow<List<RadioOption>>(emptyList())
val expirationTimerOptions: StateFlow<List<RadioOption>> = _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<RadioOption>,
@Assisted("afterSend") private val afterSendOptions: List<RadioOption>,
private val threadDb: ThreadDatabase
private val threadDb: ThreadDatabase,
private val storage: Storage
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@ -85,7 +103,8 @@ class ExpirationSettingsViewModel(
threadId,
afterReadOptions,
afterSendOptions,
threadDb
threadDb,
storage
) as T
}
}

View File

@ -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<Pair<String, Int>> {

View File

@ -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<String> 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) {

View File

@ -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();

View File

@ -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;
}

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="?colorPrimary"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<cn.carbswang.android.numberpickerview.library.NumberPickerView
android:id="@+id/expiration_number_picker"
android:layout_alignParentTop="true"
app:npv_WrapSelectorWheel="false"
app:npv_DividerColor="#cbc8ea"
app:npv_TextColorNormal="?android:textColorPrimary"
app:npv_TextColorSelected="?android:textColorPrimary"
app:npv_ItemPaddingVertical="20dp"
app:npv_TextColorHint="@color/grey_600"
app:npv_TextSizeNormal="16sp"
app:npv_TextSizeSelected="16sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/expiration_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/expiration_number_picker"
android:minLines="3"
android:padding="20dp"
tools:text="Your messages will not expire."/>
</RelativeLayout>

View File

@ -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<Recipient>)
fun blockedContacts(): List<Recipient>
fun getExpirationSettingsConfiguration(threadId: Long): ExpirationSettingsConfiguration?
fun addExpirationSettingsConfiguration(config: ExpirationSettingsConfiguration)
fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration?
fun updateExpirationConfiguration(config: ExpirationConfiguration)
fun getExpiringMessages(messageIds: LongArray): List<Pair<String, Int>>
}

View File

@ -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
)
) {
val isEnabled = durationSeconds > 0
}

View File

@ -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

View File

@ -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

View File

@ -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)