Move expiration configuration to a separate table

This commit is contained in:
charles 2022-12-05 13:00:53 +11:00
parent 92123b2417
commit 8c002247d6
12 changed files with 116 additions and 103 deletions

View File

@ -85,9 +85,9 @@ class ExpirationSettingsViewModel(
fun onSetClick() = viewModelScope.launch { fun onSetClick() = viewModelScope.launch {
val expiresIn = _selectedExpirationTimer.value?.value?.toIntOrNull() ?: 0 val expiresIn = _selectedExpirationTimer.value?.value?.toIntOrNull() ?: 0
val expiryType = _selectedExpirationType.value?.number ?: 0 val expiryType = _selectedExpirationType.value
val expiryChangeTimestamp = System.currentTimeMillis() val expiryChangeTimestampMs = System.currentTimeMillis()
threadDb.updateExpiryConfig(threadId, expiresIn, expiryType, expiryChangeTimestamp) storage.addExpirationConfiguration(ExpirationConfiguration(threadId, expiresIn, expiryType, expiryChangeTimestampMs))
} }
@dagger.assisted.AssistedFactory @dagger.assisted.AssistedFactory

View File

@ -0,0 +1,92 @@
package org.thoughtcrime.securesms.database
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
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) {
companion object {
const val TABLE_NAME = "expiration_configuration"
const val THREAD_ID = "thread_id"
const val DURATION_SECONDS = "duration_seconds"
const val EXPIRATION_TYPE = "expiration_type"
const val UPDATED_TIMESTAMP_MS = "updated_timestamp_ms"
@JvmField
val CREATE_EXPIRATION_CONFIGURATION_TABLE_COMMAND = """
CREATE TABLE $TABLE_NAME (
$THREAD_ID INTEGER NOT NULL PRIMARY KEY ON CONFLICT REPLACE,
$DURATION_SECONDS INTEGER NOT NULL,
$EXPIRATION_TYPE INTEGER DEFAULT NULL,
$UPDATED_TIMESTAMP_MS INTEGER DEFAULT NULL
)
""".trimIndent()
@JvmField
val MIGRATE_GROUP_CONVERSATION_EXPIRY_TYPE_COMMAND = """
INSERT INTO $TABLE_NAME ($THREAD_ID, $DURATION_SECONDS, $EXPIRATION_TYPE) SELECT ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ID}, ${RecipientDatabase.EXPIRE_MESSAGES}, 1
FROM ${ThreadDatabase.TABLE_NAME}, ${RecipientDatabase.TABLE_NAME}
WHERE ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} LIKE '$CLOSED_GROUP_PREFIX%'
AND EXISTS (SELECT ${RecipientDatabase.EXPIRE_MESSAGES} FROM ${RecipientDatabase.TABLE_NAME} WHERE ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} = ${RecipientDatabase.TABLE_NAME}.${RecipientDatabase.ADDRESS} AND ${RecipientDatabase.EXPIRE_MESSAGES} > 0)
""".trimIndent()
@JvmField
val MIGRATE_ONE_TO_ONE_CONVERSATION_EXPIRY_TYPE_COMMAND = """
INSERT INTO $TABLE_NAME ($THREAD_ID, $DURATION_SECONDS, $EXPIRATION_TYPE) SELECT ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ID}, ${RecipientDatabase.EXPIRE_MESSAGES}, 2
FROM ${ThreadDatabase.TABLE_NAME}, ${RecipientDatabase.TABLE_NAME}
WHERE ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} NOT LIKE '$CLOSED_GROUP_PREFIX%'
AND ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} NOT LIKE '$OPEN_GROUP_PREFIX%'
AND ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} NOT LIKE '$OPEN_GROUP_INBOX_PREFIX%'
AND EXISTS (SELECT ${RecipientDatabase.EXPIRE_MESSAGES} FROM ${RecipientDatabase.TABLE_NAME} WHERE ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.ADDRESS} = ${RecipientDatabase.TABLE_NAME}.${RecipientDatabase.ADDRESS} AND ${RecipientDatabase.EXPIRE_MESSAGES} > 0)
""".trimIndent()
private fun readExpirationConfiguration(cursor: Cursor): ExpirationConfiguration {
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))),
updatedTimestampMs = cursor.getLong(cursor.getColumnIndexOrThrow(UPDATED_TIMESTAMP_MS))
)
}
}
fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? {
val query = "$THREAD_ID = ?"
val args = arrayOf("$threadId")
val mappings: MutableList<ExpirationConfiguration> = mutableListOf()
readableDatabase.query(TABLE_NAME, null, query, args, null, null, null).use { cursor ->
while (cursor.moveToNext()) {
mappings += readExpirationConfiguration(cursor)
}
}
return mappings.firstOrNull()
}
fun addExpirationConfiguration(configuration: ExpirationConfiguration) {
writableDatabase.beginTransaction()
try {
val values = ContentValues().apply {
put(THREAD_ID, configuration.threadId)
put(DURATION_SECONDS, configuration.durationSeconds)
put(EXPIRATION_TYPE, configuration.expirationType?.number)
put(UPDATED_TIMESTAMP_MS, configuration.updatedTimestampMs)
}
writableDatabase.insert(TABLE_NAME, null, values)
writableDatabase.setTransactionSuccessful()
} finally {
writableDatabase.endTransaction()
}
}
}

View File

@ -963,32 +963,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
} }
override fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? { override fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? {
val threadDb = DatabaseComponent.get(context).threadDatabase() return DatabaseComponent.get(context).expirationConfigurationDatabase().getExpirationConfiguration(threadId)
threadDb.readerFor(threadDb.conversationList).use { reader ->
while (reader.next != null) {
val thread = reader.current
if (thread.threadId == threadId &&
(thread.recipient.isClosedGroupRecipient || thread.recipient.isContactRecipient)
) {
return ExpirationConfiguration(
thread.threadId,
thread.expiresIn.toInt(),
thread.expiryType,
thread.expiryChangeTimestamp
)
}
}
}
return null
} }
override fun updateExpirationConfiguration(config: ExpirationConfiguration) { override fun addExpirationConfiguration(config: ExpirationConfiguration) {
DatabaseComponent.get(context).threadDatabase().updateExpiryConfig( DatabaseComponent.get(context).expirationConfigurationDatabase().addExpirationConfiguration(config)
config.threadId,
config.durationSeconds,
config.expirationType?.number ?: 0,
config.lastChangeTimestampMs
)
} }
override fun getExpiringMessages(messageIds: LongArray): List<Pair<String, Int>> { override fun getExpiringMessages(messageIds: LongArray): List<Pair<String, Int>> {

View File

@ -18,7 +18,6 @@
package org.thoughtcrime.securesms.database; package org.thoughtcrime.securesms.database;
import static org.session.libsession.utilities.GroupUtil.CLOSED_GROUP_PREFIX; 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.session.libsession.utilities.GroupUtil.OPEN_GROUP_PREFIX;
import static org.thoughtcrime.securesms.database.GroupDatabase.GROUP_ID; import static org.thoughtcrime.securesms.database.GroupDatabase.GROUP_ID;
@ -97,8 +96,6 @@ public class ThreadDatabase extends Database {
public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count"; public static final String DELIVERY_RECEIPT_COUNT = "delivery_receipt_count";
public static final String READ_RECEIPT_COUNT = "read_receipt_count"; public static final String READ_RECEIPT_COUNT = "read_receipt_count";
public static final String EXPIRES_IN = "expires_in"; 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 LAST_SEEN = "last_seen";
public static final String HAS_SENT = "has_sent"; public static final String HAS_SENT = "has_sent";
public static final String IS_PINNED = "is_pinned"; public static final String IS_PINNED = "is_pinned";
@ -121,8 +118,7 @@ public class ThreadDatabase extends Database {
private static final String[] THREAD_PROJECTION = { private static final String[] THREAD_PROJECTION = {
ID, DATE, MESSAGE_COUNT, ADDRESS, SNIPPET, SNIPPET_CHARSET, READ, UNREAD_COUNT, TYPE, ERROR, SNIPPET_TYPE, 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) private static final List<String> TYPED_THREAD_PROJECTION = Stream.of(THREAD_PROJECTION)
@ -139,36 +135,6 @@ public class ThreadDatabase extends Database {
"ADD COLUMN " + IS_PINNED + " INTEGER DEFAULT 0;"; "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, " +
EXPIRES_IN + " = (SELECT " + RecipientDatabase.EXPIRE_MESSAGES + " FROM " + RecipientDatabase.TABLE_NAME +
" WHERE " + TABLE_NAME + "." + ADDRESS + " = " + RecipientDatabase.TABLE_NAME + "." + RecipientDatabase.ADDRESS + " AND " + RecipientDatabase.EXPIRE_MESSAGES + " > 0 )" +
"WHERE " + TABLE_NAME + "." + ADDRESS + " LIKE '" + CLOSED_GROUP_PREFIX + "%' " +
"AND EXISTS (SELECT " + RecipientDatabase.EXPIRE_MESSAGES + " FROM " + RecipientDatabase.TABLE_NAME +
" WHERE " + TABLE_NAME + "." + ADDRESS + " = " + RecipientDatabase.TABLE_NAME + "." + RecipientDatabase.ADDRESS + " AND " + RecipientDatabase.EXPIRE_MESSAGES + " > 0 )";
}
public static String getUpdateOneToOneConversationExpiryTypeCommand() {
return "UPDATE " + TABLE_NAME + " SET " + EXPIRY_TYPE + " = 2, " +
EXPIRES_IN + " = (SELECT " + RecipientDatabase.EXPIRE_MESSAGES + " FROM " + RecipientDatabase.TABLE_NAME +
" WHERE " + TABLE_NAME + "." + ADDRESS + " = " + RecipientDatabase.TABLE_NAME + "." + RecipientDatabase.ADDRESS + " AND " + RecipientDatabase.EXPIRE_MESSAGES + " > 0 )" +
"WHERE " + ADDRESS + " NOT LIKE '" + CLOSED_GROUP_PREFIX + "%'" +
"AND " + ADDRESS + " NOT LIKE '" + OPEN_GROUP_PREFIX + "%'" +
"AND " + ADDRESS + " NOT LIKE '" + OPEN_GROUP_INBOX_PREFIX + "%'" +
"AND EXISTS (SELECT " + RecipientDatabase.EXPIRE_MESSAGES + " FROM " + RecipientDatabase.TABLE_NAME +
" WHERE " + TABLE_NAME + "." + ADDRESS + " = " + RecipientDatabase.TABLE_NAME + "." + RecipientDatabase.ADDRESS + " AND " + RecipientDatabase.EXPIRE_MESSAGES + " > 0 )";
}
public ThreadDatabase(Context context, SQLCipherOpenHelper databaseHelper) { public ThreadDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
super(context, databaseHelper); super(context, databaseHelper);
} }
@ -234,18 +200,6 @@ public class ThreadDatabase extends Database {
notifyConversationListListeners(); 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) { private void deleteThread(long threadId) {
SQLiteDatabase db = databaseHelper.getWritableDatabase(); SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId + ""}); db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId + ""});
@ -955,8 +909,6 @@ public class ThreadDatabase extends Database {
int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.DELIVERY_RECEIPT_COUNT)); int deliveryReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.DELIVERY_RECEIPT_COUNT));
int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ_RECEIPT_COUNT)); int readReceiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.READ_RECEIPT_COUNT));
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN)); 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)); long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN));
Uri snippetUri = getSnippetUri(cursor); Uri snippetUri = getSnippetUri(cursor);
boolean pinned = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.IS_PINNED)) != 0; boolean pinned = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.IS_PINNED)) != 0;
@ -967,7 +919,7 @@ public class ThreadDatabase extends Database {
return new ThreadRecord(body, snippetUri, recipient, date, count, return new ThreadRecord(body, snippetUri, recipient, date, count,
unreadCount, threadId, deliveryReceiptCount, status, type, unreadCount, threadId, deliveryReceiptCount, status, type,
distributionType, archived, expiresIn, lastSeen, readReceiptCount, pinned, expiryType, expiryChangeTimestamp); distributionType, archived, expiresIn, lastSeen, readReceiptCount, pinned);
} }
private @Nullable Uri getSnippetUri(Cursor cursor) { private @Nullable Uri getSnippetUri(Cursor cursor) {

View File

@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.BlindedIdMappingDatabase; import org.thoughtcrime.securesms.database.BlindedIdMappingDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.EmojiSearchDatabase; import org.thoughtcrime.securesms.database.EmojiSearchDatabase;
import org.thoughtcrime.securesms.database.ExpirationConfigurationDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupMemberDatabase; import org.thoughtcrime.securesms.database.GroupMemberDatabase;
import org.thoughtcrime.securesms.database.GroupReceiptDatabase; import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
@ -181,8 +182,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
db.execSQL(LokiAPIDatabase.RESET_SEQ_NO); // probably not needed but consistent with all migrations db.execSQL(LokiAPIDatabase.RESET_SEQ_NO); // probably not needed but consistent with all migrations
db.execSQL(EmojiSearchDatabase.CREATE_EMOJI_SEARCH_TABLE_COMMAND); db.execSQL(EmojiSearchDatabase.CREATE_EMOJI_SEARCH_TABLE_COMMAND);
db.execSQL(ReactionDatabase.CREATE_REACTION_TABLE_COMMAND); db.execSQL(ReactionDatabase.CREATE_REACTION_TABLE_COMMAND);
db.execSQL(ThreadDatabase.getCreateExpiryTypeCommand()); db.execSQL(ExpirationConfigurationDatabase.CREATE_EXPIRATION_CONFIGURATION_TABLE_COMMAND);
db.execSQL(ThreadDatabase.getCreateExpiryChangeTimestampCommand());
executeStatements(db, SmsDatabase.CREATE_INDEXS); executeStatements(db, SmsDatabase.CREATE_INDEXS);
executeStatements(db, MmsDatabase.CREATE_INDEXS); executeStatements(db, MmsDatabase.CREATE_INDEXS);
@ -418,10 +418,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
} }
if (oldVersion < lokiV39) { if (oldVersion < lokiV39) {
db.execSQL(ThreadDatabase.getCreateExpiryTypeCommand()); db.execSQL(ExpirationConfigurationDatabase.CREATE_EXPIRATION_CONFIGURATION_TABLE_COMMAND);
db.execSQL(ThreadDatabase.getCreateExpiryChangeTimestampCommand()); db.execSQL(ExpirationConfigurationDatabase.MIGRATE_GROUP_CONVERSATION_EXPIRY_TYPE_COMMAND);
db.execSQL(ThreadDatabase.getUpdateGroupConversationExpiryTypeCommand()); db.execSQL(ExpirationConfigurationDatabase.MIGRATE_ONE_TO_ONE_CONVERSATION_EXPIRY_TYPE_COMMAND);
db.execSQL(ThreadDatabase.getUpdateOneToOneConversationExpiryTypeCommand());
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();

View File

@ -29,7 +29,6 @@ import androidx.annotation.Nullable;
import org.session.libsession.utilities.ExpirationUtil; import org.session.libsession.utilities.ExpirationUtil;
import org.session.libsession.utilities.recipients.Recipient; 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.MmsSmsColumns;
import org.thoughtcrime.securesms.database.SmsDatabase; import org.thoughtcrime.securesms.database.SmsDatabase;
@ -49,8 +48,6 @@ public class ThreadRecord extends DisplayRecord {
private final int distributionType; private final int distributionType;
private final boolean archived; private final boolean archived;
private final long expiresIn; private final long expiresIn;
private final int expiryType;
private final long expiryChangeTimestamp;
private final long lastSeen; private final long lastSeen;
private final boolean pinned; private final boolean pinned;
private final int recipientHash; private final int recipientHash;
@ -59,7 +56,7 @@ public class ThreadRecord extends DisplayRecord {
@NonNull Recipient recipient, long date, long count, int unreadCount, @NonNull Recipient recipient, long date, long count, int unreadCount,
long threadId, int deliveryReceiptCount, int status, long snippetType, long threadId, int deliveryReceiptCount, int status, long snippetType,
int distributionType, boolean archived, long expiresIn, long lastSeen, int distributionType, boolean archived, long expiresIn, long lastSeen,
int readReceiptCount, boolean pinned, int expiryType, long expiryChangeTimestamp) int readReceiptCount, boolean pinned)
{ {
super(body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount); super(body, recipient, date, date, threadId, status, deliveryReceiptCount, snippetType, readReceiptCount);
this.snippetUri = snippetUri; this.snippetUri = snippetUri;
@ -68,8 +65,6 @@ public class ThreadRecord extends DisplayRecord {
this.distributionType = distributionType; this.distributionType = distributionType;
this.archived = archived; this.archived = archived;
this.expiresIn = expiresIn; this.expiresIn = expiresIn;
this.expiryType = expiryType;
this.expiryChangeTimestamp = expiryChangeTimestamp;
this.lastSeen = lastSeen; this.lastSeen = lastSeen;
this.pinned = pinned; this.pinned = pinned;
this.recipientHash = recipient.hashCode(); this.recipientHash = recipient.hashCode();
@ -174,15 +169,6 @@ public class ThreadRecord extends DisplayRecord {
return expiresIn; return expiresIn;
} }
@Nullable
public ExpirationType getExpiryType() {
return ExpirationType.valueOf(expiryType);
}
public long getExpiryChangeTimestamp() {
return expiryChangeTimestamp;
}
public long getLastSeen() { public long getLastSeen() {
return lastSeen; return lastSeen;
} }

View File

@ -46,4 +46,5 @@ interface DatabaseComponent {
fun attachmentProvider(): MessageDataProvider fun attachmentProvider(): MessageDataProvider
fun blindedIdMappingDatabase(): BlindedIdMappingDatabase fun blindedIdMappingDatabase(): BlindedIdMappingDatabase
fun groupMemberDatabase(): GroupMemberDatabase fun groupMemberDatabase(): GroupMemberDatabase
fun expirationConfigurationDatabase(): ExpirationConfigurationDatabase
} }

View File

@ -133,6 +133,10 @@ object DatabaseModule {
@Singleton @Singleton
fun provideEmojiSearchDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = EmojiSearchDatabase(context, openHelper) fun provideEmojiSearchDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = EmojiSearchDatabase(context, openHelper)
@Provides
@Singleton
fun provideExpirationConfigurationDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = ExpirationConfigurationDatabase(context, openHelper)
@Provides @Provides
@Singleton @Singleton
fun provideStorage(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = Storage(context,openHelper) fun provideStorage(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = Storage(context,openHelper)

View File

@ -200,6 +200,6 @@ interface StorageProtocol {
fun unblock(toUnblock: List<Recipient>) fun unblock(toUnblock: List<Recipient>)
fun blockedContacts(): List<Recipient> fun blockedContacts(): List<Recipient>
fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration?
fun updateExpirationConfiguration(config: ExpirationConfiguration) fun addExpirationConfiguration(config: ExpirationConfiguration)
fun getExpiringMessages(messageIds: LongArray): List<Pair<String, Int>> fun getExpiringMessages(messageIds: LongArray): List<Pair<String, Int>>
} }

View File

@ -6,7 +6,7 @@ class ExpirationConfiguration(
val threadId: Long = -1, val threadId: Long = -1,
val durationSeconds: Int = 0, val durationSeconds: Int = 0,
val expirationType: ExpirationType? = null, val expirationType: ExpirationType? = null,
val lastChangeTimestampMs: Long = 0 val updatedTimestampMs: Long = 0
) { ) {
val isEnabled = durationSeconds > 0 val isEnabled = durationSeconds > 0
} }

View File

@ -45,7 +45,7 @@ abstract class Message {
builder.expirationTimer = config.durationSeconds builder.expirationTimer = config.durationSeconds
if (config.isEnabled) { if (config.isEnabled) {
builder.expirationType = config.expirationType builder.expirationType = config.expirationType
builder.lastDisappearingMessageChangeTimestamp = config.lastChangeTimestampMs builder.lastDisappearingMessageChangeTimestamp = config.updatedTimestampMs
} }
} }
} }

View File

@ -88,7 +88,7 @@ fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalService
val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID) val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID)
if (threadID <= 0) return if (threadID <= 0) return
val localConfig = storage.getExpirationConfiguration(threadID) val localConfig = storage.getExpirationConfiguration(threadID)
if (localConfig == null || localConfig.lastChangeTimestampMs < proto.lastDisappearingMessageChangeTimestamp) return if (localConfig == null || localConfig.updatedTimestampMs < proto.lastDisappearingMessageChangeTimestamp) return
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0 val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
val type = if (proto.hasExpirationType()) proto.expirationType else null val type = if (proto.hasExpirationType()) proto.expirationType else null
val remoteConfig = ExpirationConfiguration( val remoteConfig = ExpirationConfiguration(
@ -97,7 +97,7 @@ fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalService
type, type,
proto.lastDisappearingMessageChangeTimestamp proto.lastDisappearingMessageChangeTimestamp
) )
storage.updateExpirationConfiguration(remoteConfig) storage.addExpirationConfiguration(remoteConfig)
} }
// region Control Messages // region Control Messages