From 5afd6476867956b4c286ca51b82d9f1f8c3fed3e Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 9 Jan 2023 15:22:29 +1100 Subject: [PATCH] Tweaked some open group handling and a couple of onboarding issues Updated the OpenGroup adding and polling logic to reduce duplicate API calls Updated the BackgroundGroupAddJob to start a GroupAvatarDownloadJob instead of running the download itself (to appear to run faster) Defaulted OpenGroups to use blinded auth when no server capabilities are present Fixed an issue where the background poller could be started even though the onboarding hadn't been completed Fixed an issue where the database could get into an invalid state if the app was restarted during onboarding --- .../securesms/ApplicationContext.java | 6 +++++ .../securesms/database/LokiAPIDatabase.kt | 10 ++++++++ .../securesms/groups/OpenGroupManager.kt | 24 +++++++++---------- .../notifications/BackgroundPollWorker.kt | 2 +- .../onboarding/LinkDeviceActivity.kt | 9 +++++++ .../RecoveryPhraseRestoreActivity.kt | 9 +++++++ .../securesms/onboarding/RegisterActivity.kt | 9 +++++++ .../messaging/jobs/BackgroundGroupAddJob.kt | 11 +++------ .../messaging/jobs/GroupAvatarDownloadJob.kt | 5 ++-- .../messaging/open_groups/OpenGroup.kt | 14 +++++++---- .../messaging/open_groups/OpenGroupApi.kt | 19 +++++++-------- .../pollers/OpenGroupPoller.kt | 24 +++++++------------ .../database/LokiAPIDatabaseProtocol.kt | 2 ++ 13 files changed, 89 insertions(+), 55 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index e253d0b962..4f1270acc5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -245,6 +245,12 @@ public class ApplicationContext extends Application implements DefaultLifecycleO Log.i(TAG, "App is now visible."); KeyCachingService.onAppForegrounded(this); + // If the user account hasn't been created or onboarding wasn't finished then don't start + // the pollers + if (TextSecurePreferences.getLocalNumber(this) == null || !TextSecurePreferences.hasSeenWelcomeScreen(this)) { + return; + } + ThreadUtils.queue(()->{ if (poller != null) { poller.setCaughtUp(false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt index 6aeadc2b7b..0300f1fccf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/LokiAPIDatabase.kt @@ -300,6 +300,11 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database( val lastHash = database.insertOrUpdate(lastMessageHashValueTable2, row, query, arrayOf( snode.toString(), publicKey, namespace.toString() )) } + override fun clearAllLastMessageHashes() { + val database = databaseHelper.writableDatabase + database.delete(lastMessageHashValueTable2, null, null) + } + override fun getReceivedMessageHashValues(publicKey: String, namespace: Int): Set? { val database = databaseHelper.readableDatabase val query = "${Companion.publicKey} = ? AND ${Companion.receivedMessageHashNamespace} = ?" @@ -321,6 +326,11 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database( database.insertOrUpdate(receivedMessageHashValuesTable, row, query, arrayOf( publicKey, namespace.toString() )) } + override fun clearReceivedMessageHashValues() { + val database = databaseHelper.writableDatabase + database.delete(receivedMessageHashValuesTable, null, null) + } + override fun getAuthToken(server: String): String? { val database = databaseHelper.readableDatabase return database.get(openGroupAuthTokenTable, "${Companion.server} = ?", wrap(server)) { cursor -> diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt index d39ba709df..09c6f19dab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt @@ -58,14 +58,14 @@ object OpenGroupManager { } @WorkerThread - fun add(server: String, room: String, publicKey: String, context: Context) { + fun add(server: String, room: String, publicKey: String, context: Context): OpenGroupApi.RoomInfo? { val openGroupID = "$server.$room" var threadID = GroupManager.getOpenGroupThreadID(openGroupID, context) val storage = MessagingModuleConfiguration.shared.storage val threadDB = DatabaseComponent.get(context).lokiThreadDatabase() // Check it it's added already val existingOpenGroup = threadDB.getOpenGroupChat(threadID) - if (existingOpenGroup != null) { return } + if (existingOpenGroup != null) { return null } // Clear any existing data if needed storage.removeLastDeletionServerID(room, server) storage.removeLastMessageServerID(room, server) @@ -73,18 +73,17 @@ object OpenGroupManager { storage.removeLastOutboxMessageId(server) // Store the public key storage.setOpenGroupPublicKey(server, publicKey) - // Get capabilities - val capabilities = OpenGroupApi.getCapabilities(server).get() + // Get capabilities & room info + val (capabilities, info) = OpenGroupApi.getCapabilitiesAndRoomInfo(room, server).get() storage.setServerCapabilities(server, capabilities.capabilities) - // Get room info - val info = OpenGroupApi.getRoomInfo(room, server).get() storage.setUserCount(room, server, info.activeUsers) // Create the group locally if not available already if (threadID < 0) { threadID = GroupManager.createOpenGroup(openGroupID, context, null, info.name).threadId } - val openGroup = OpenGroup(server, room, info.name, info.infoUpdates, publicKey) + val openGroup = OpenGroup(server, room, publicKey, info.name, info.imageId, info.infoUpdates) threadDB.setOpenGroupChat(openGroup, threadID) + return info } fun restartPollerForServer(server: String) { @@ -130,12 +129,13 @@ object OpenGroupManager { } } - fun addOpenGroup(urlAsString: String, context: Context) { - val url = HttpUrl.parse(urlAsString) ?: return + fun addOpenGroup(urlAsString: String, context: Context): OpenGroupApi.RoomInfo? { + val url = HttpUrl.parse(urlAsString) ?: return null val server = OpenGroup.getServer(urlAsString) - val room = url.pathSegments().firstOrNull() ?: return - val publicKey = url.queryParameter("public_key") ?: return - add(server.toString().removeSuffix("/"), room, publicKey, context) // assume migrated from calling function + val room = url.pathSegments().firstOrNull() ?: return null + val publicKey = url.queryParameter("public_key") ?: return null + + return add(server.toString().removeSuffix("/"), room, publicKey, context) // assume migrated from calling function } fun updateOpenGroup(openGroup: OpenGroup, context: Context) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/BackgroundPollWorker.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/BackgroundPollWorker.kt index 48a5725521..5a0438e15d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/BackgroundPollWorker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/BackgroundPollWorker.kt @@ -44,7 +44,7 @@ class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Wor } override fun doWork(): Result { - if (TextSecurePreferences.getLocalNumber(context) == null) { + if (TextSecurePreferences.getLocalNumber(context) == null || !TextSecurePreferences.hasSeenWelcomeScreen(context)) { Log.v(TAG, "User not registered yet.") return Result.failure() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt index ee1631a00d..31117ae94d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt @@ -22,8 +22,10 @@ import kotlinx.coroutines.launch import network.loki.messenger.R import network.loki.messenger.databinding.ActivityLinkDeviceBinding import network.loki.messenger.databinding.FragmentRecoveryPhraseBinding +import org.session.libsession.snode.SnodeModule import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.MnemonicCodec +import org.session.libsignal.database.LokiAPIDatabaseProtocol import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.Log @@ -39,6 +41,8 @@ import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate { private lateinit var binding: ActivityLinkDeviceBinding + internal val database: LokiAPIDatabaseProtocol + get() = SnodeModule.shared.storage private val adapter = LinkDeviceActivityAdapter(this) private var restoreJob: Job? = null @@ -99,6 +103,11 @@ class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDel if (restoreJob?.isActive == true) return restoreJob = lifecycleScope.launch { + // This is here to resolve a case where the app restarts before a user completes onboarding + // which can result in an invalid database state + database.clearAllLastMessageHashes() + database.clearReceivedMessageHashValues() + // RestoreActivity handles seed this way val keyPairGenerationResult = KeyPairUtilities.generate(seed) val x25519KeyPair = keyPairGenerationResult.x25519KeyPair diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPhraseRestoreActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPhraseRestoreActivity.kt index 6a1c785ad6..5531fea491 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPhraseRestoreActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPhraseRestoreActivity.kt @@ -13,8 +13,10 @@ import android.view.View import android.widget.Toast import network.loki.messenger.R import network.loki.messenger.databinding.ActivityRecoveryPhraseRestoreBinding +import org.session.libsession.snode.SnodeModule import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.MnemonicCodec +import org.session.libsignal.database.LokiAPIDatabaseProtocol import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.hexEncodedPublicKey @@ -26,6 +28,8 @@ import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo class RecoveryPhraseRestoreActivity : BaseActionBarActivity() { private lateinit var binding: ActivityRecoveryPhraseRestoreBinding + internal val database: LokiAPIDatabaseProtocol + get() = SnodeModule.shared.storage // region Lifecycle override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -64,6 +68,11 @@ class RecoveryPhraseRestoreActivity : BaseActionBarActivity() { private fun restore() { val mnemonic = binding.mnemonicEditText.text.toString() try { + // This is here to resolve a case where the app restarts before a user completes onboarding + // which can result in an invalid database state + database.clearAllLastMessageHashes() + database.clearReceivedMessageHashValues() + val loadFileContents: (String) -> String = { fileName -> MnemonicUtilities.loadFileContents(this, fileName) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RegisterActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/RegisterActivity.kt index 0105fbedf0..b6fdaf9cf9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RegisterActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/RegisterActivity.kt @@ -18,8 +18,10 @@ import android.widget.Toast import com.goterl.lazysodium.utils.KeyPair import network.loki.messenger.R import network.loki.messenger.databinding.ActivityRegisterBinding +import org.session.libsession.snode.SnodeModule import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.crypto.ecc.ECKeyPair +import org.session.libsignal.database.LokiAPIDatabaseProtocol import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.hexEncodedPublicKey import org.thoughtcrime.securesms.BaseActionBarActivity @@ -29,6 +31,8 @@ import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo class RegisterActivity : BaseActionBarActivity() { private lateinit var binding: ActivityRegisterBinding + internal val database: LokiAPIDatabaseProtocol + get() = SnodeModule.shared.storage private var seed: ByteArray? = null private var ed25519KeyPair: KeyPair? = null private var x25519KeyPair: ECKeyPair? = null @@ -109,6 +113,11 @@ class RegisterActivity : BaseActionBarActivity() { // region Interaction private fun register() { + // This is here to resolve a case where the app restarts before a user completes onboarding + // which can result in an invalid database state + database.clearAllLastMessageHashes() + database.clearReceivedMessageHashValues() + KeyPairUtilities.store(this, seed!!, ed25519KeyPair!!, x25519KeyPair!!) val userHexEncodedPublicKey = x25519KeyPair!!.hexEncodedPublicKey val registrationID = KeyHelper.generateRegistrationId(false) diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/BackgroundGroupAddJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/BackgroundGroupAddJob.kt index aa37e0f0a8..c679724b9f 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/BackgroundGroupAddJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/BackgroundGroupAddJob.kt @@ -41,15 +41,10 @@ class BackgroundGroupAddJob(val joinUrl: String): Job { } // get image storage.setOpenGroupPublicKey(openGroup.server, openGroup.serverPublicKey) - val (capabilities, info) = OpenGroupApi.getCapabilitiesAndRoomInfo(openGroup.room, openGroup.server, false).get() - storage.setServerCapabilities(openGroup.server, capabilities.capabilities) - val imageId = info.imageId - storage.addOpenGroup(openGroup.joinUrl()) + val info = storage.addOpenGroup(openGroup.joinUrl()) + val imageId = info?.imageId if (imageId != null) { - val bytes = OpenGroupApi.downloadOpenGroupProfilePicture(openGroup.server, openGroup.room, imageId).get() - val groupId = GroupUtil.getEncodedOpenGroupID("${openGroup.server}.${openGroup.room}".toByteArray()) - storage.updateProfilePicture(groupId, bytes) - storage.updateTimestampUpdated(groupId, System.currentTimeMillis()) + JobQueue.shared.add(GroupAvatarDownloadJob(openGroup.room, openGroup.server)) } Log.d(KEY, "onOpenGroupAdded(${openGroup.server})") storage.onOpenGroupAdded(openGroup.server) diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/GroupAvatarDownloadJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/GroupAvatarDownloadJob.kt index 38e8831fba..02f792117c 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/GroupAvatarDownloadJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/GroupAvatarDownloadJob.kt @@ -14,10 +14,9 @@ class GroupAvatarDownloadJob(val room: String, val server: String) : Job { override fun execute() { val storage = MessagingModuleConfiguration.shared.storage + val imageId = storage.getOpenGroup(room, server)?.imageId ?: return try { - val info = OpenGroupApi.getRoomInfo(room, server).get() - val imageId = info.imageId ?: return - val bytes = OpenGroupApi.downloadOpenGroupProfilePicture(server, info.token, imageId).get() + val bytes = OpenGroupApi.downloadOpenGroupProfilePicture(server, room, imageId).get() val groupId = GroupUtil.getEncodedOpenGroupID("$server.$room".toByteArray()) storage.updateProfilePicture(groupId, bytes) storage.updateTimestampUpdated(groupId, System.currentTimeMillis()) diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroup.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroup.kt index 9efeaf15d0..b2bdd6384a 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroup.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroup.kt @@ -11,15 +11,17 @@ data class OpenGroup( val id: String, val name: String, val publicKey: String, + val imageId: String?, val infoUpdates: Int, ) { - constructor(server: String, room: String, name: String, infoUpdates: Int, publicKey: String) : this( + constructor(server: String, room: String, publicKey: String, name: String, imageId: String?, infoUpdates: Int) : this( server = server, room = room, id = "$server.$room", name = name, publicKey = publicKey, + imageId = imageId, infoUpdates = infoUpdates, ) @@ -31,11 +33,12 @@ data class OpenGroup( if (!json.has("room")) return null val room = json.get("room").asText().toLowerCase(Locale.US) val server = json.get("server").asText().toLowerCase(Locale.US) - val displayName = json.get("displayName").asText() val publicKey = json.get("publicKey").asText() + val displayName = json.get("displayName").asText() + val imageId = json.get("imageId")?.asText() val infoUpdates = json.get("infoUpdates")?.asText()?.toIntOrNull() ?: 0 val capabilities = json.get("capabilities")?.asText()?.split(",") ?: emptyList() - OpenGroup(server, room, displayName, infoUpdates, publicKey) + OpenGroup(server, room, displayName, publicKey, imageId, infoUpdates) } catch (e: Exception) { Log.w("Loki", "Couldn't parse open group from JSON: $jsonAsString.", e); null @@ -53,11 +56,12 @@ data class OpenGroup( } } - fun toJson(): Map = mapOf( + fun toJson(): Map = mapOf( "room" to room, "server" to server, - "displayName" to name, "publicKey" to publicKey, + "displayName" to name, + "imageId" to imageId, "infoUpdates" to infoUpdates.toString(), ) diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt index d5bc6dde08..51f7108f5a 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt @@ -91,7 +91,7 @@ object OpenGroupApi { val created: Long = 0, val activeUsers: Int = 0, val activeUsersCutoff: Int = 0, - val imageId: Long? = null, + val imageId: String? = null, val pinnedMessages: List = emptyList(), val admin: Boolean = false, val globalAdmin: Boolean = false, @@ -337,7 +337,7 @@ object OpenGroupApi { .plus(request.verb.rawValue.toByteArray()) .plus("/${request.endpoint.value}".toByteArray()) .plus(bodyHash) - if (serverCapabilities.contains(Capability.BLIND.name.lowercase())) { + if (serverCapabilities.isEmpty() || serverCapabilities.contains(Capability.BLIND.name.lowercase())) { SodiumUtilities.blindedKeyPair(publicKey, ed25519KeyPair)?.let { keyPair -> pubKey = SessionId( IdPrefix.BLINDED, @@ -395,13 +395,13 @@ object OpenGroupApi { fun downloadOpenGroupProfilePicture( server: String, roomID: String, - imageId: Long + imageId: String ): Promise { val request = Request( verb = GET, room = roomID, server = server, - endpoint = Endpoint.RoomFileIndividual(roomID, imageId.toString()) + endpoint = Endpoint.RoomFileIndividual(roomID, imageId) ) return getResponseBody(request) } @@ -794,16 +794,14 @@ object OpenGroupApi { private fun sequentialBatch( server: String, - requests: MutableList>, - authRequired: Boolean = true + requests: MutableList> ): Promise>, Exception> { val request = Request( verb = POST, room = null, server = server, endpoint = Endpoint.Sequence, - parameters = requests.map { it.request }, - isAuthRequired = authRequired + parameters = requests.map { it.request } ) return getBatchResponseJson(request, requests) } @@ -912,8 +910,7 @@ object OpenGroupApi { fun getCapabilitiesAndRoomInfo( room: String, - server: String, - authRequired: Boolean = true + server: String ): Promise, Exception> { val requests = mutableListOf>( BatchRequestInfo( @@ -933,7 +930,7 @@ object OpenGroupApi { responseType = object : TypeReference(){} ) ) - return sequentialBatch(server, requests, authRequired).map { + return sequentialBatch(server, requests).map { val capabilities = it.firstOrNull()?.body as? Capabilities ?: throw Error.ParsingFailed val roomInfo = it.lastOrNull()?.body as? RoomInfo ?: throw Error.ParsingFailed capabilities to roomInfo diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt index 145155e97c..595f7d4dc1 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/OpenGroupPoller.kt @@ -59,7 +59,7 @@ class OpenGroupPoller(private val server: String, private val executorService: S fun poll(isPostCapabilitiesRetry: Boolean = false): Promise { val storage = MessagingModuleConfiguration.shared.storage val rooms = storage.getAllOpenGroups().values.filter { it.server == server }.map { it.room } - rooms.forEach { downloadGroupAvatarIfNeeded(it) } + return OpenGroupApi.poll(rooms, server).successBackground { responses -> responses.filterNot { it.body == null }.forEach { response -> when (response.endpoint) { @@ -123,9 +123,10 @@ class OpenGroupPoller(private val server: String, private val executorService: S val openGroup = OpenGroup( server = server, room = pollInfo.token, - name = pollInfo.details?.name ?: "", - infoUpdates = pollInfo.details?.infoUpdates ?: 0, + name = if (pollInfo.details != null) { pollInfo.details.name } else { existingOpenGroup.name }, + infoUpdates = if (pollInfo.details != null) { pollInfo.details.infoUpdates } else { existingOpenGroup.infoUpdates }, publicKey = publicKey, + imageId = if (pollInfo.details != null) { pollInfo.details.imageId } else { existingOpenGroup.imageId } ) // - Open Group changes storage.updateOpenGroup(openGroup) @@ -155,6 +156,11 @@ class OpenGroupPoller(private val server: String, private val executorService: S GroupMember(groupId, it, GroupMemberRole.HIDDEN_ADMIN) }) } + + // Start downloading the room image (if we don't have one or it's been updated) + if (pollInfo.details?.imageId != null && pollInfo.details.imageId != existingOpenGroup.imageId) { + JobQueue.shared.add(GroupAvatarDownloadJob(roomToken, server)) + } } private fun handleMessages( @@ -284,16 +290,4 @@ class OpenGroupPoller(private val server: String, private val executorService: S JobQueue.shared.add(deleteJob) } } - - private fun downloadGroupAvatarIfNeeded(room: String) { - val storage = MessagingModuleConfiguration.shared.storage - if (storage.getGroupAvatarDownloadJob(server, room) != null) return - val groupId = GroupUtil.getEncodedOpenGroupID("$server.$room".toByteArray()) - storage.getGroup(groupId)?.let { - if (System.currentTimeMillis() > it.updatedTimestamp + TimeUnit.DAYS.toMillis(7)) { - JobQueue.shared.add(GroupAvatarDownloadJob(room, server)) - } - } - } - } \ No newline at end of file diff --git a/libsignal/src/main/java/org/session/libsignal/database/LokiAPIDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/database/LokiAPIDatabaseProtocol.kt index a1866bf21e..18880f5538 100644 --- a/libsignal/src/main/java/org/session/libsignal/database/LokiAPIDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/database/LokiAPIDatabaseProtocol.kt @@ -16,8 +16,10 @@ interface LokiAPIDatabaseProtocol { fun setSwarm(publicKey: String, newValue: Set) fun getLastMessageHashValue(snode: Snode, publicKey: String, namespace: Int): String? fun setLastMessageHashValue(snode: Snode, publicKey: String, newValue: String, namespace: Int) + fun clearAllLastMessageHashes() fun getReceivedMessageHashValues(publicKey: String, namespace: Int): Set? fun setReceivedMessageHashValues(publicKey: String, newValue: Set, namespace: Int) + fun clearReceivedMessageHashValues() fun getAuthToken(server: String): String? fun setAuthToken(server: String, newValue: String?) fun setUserCount(room: String, server: String, newValue: Int)