From 78d1e9d3877e34a75e4ac694e48d5d6e3a8e1b9a Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Wed, 24 May 2023 17:34:27 +1000 Subject: [PATCH] fix: open group threads and avatar downloads --- .../securesms/database/LokiThreadDatabase.kt | 7 +++++++ .../java/org/thoughtcrime/securesms/database/Storage.kt | 9 ++++++--- .../thoughtcrime/securesms/groups/OpenGroupManager.kt | 3 ++- .../securesms/jobs/RetrieveProfileAvatarJob.java | 8 ++++---- .../org/thoughtcrime/securesms/util/SharedConfigUtils.kt | 2 +- libsession-util/src/main/cpp/contacts.h | 1 + .../loki/messenger/libsession_util/util/Contact.kt | 2 +- .../sending_receiving/ReceivedMessageHandler.kt | 2 ++ .../messaging/sending_receiving/pollers/Poller.kt | 1 + 9 files changed, 25 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/LokiThreadDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/LokiThreadDatabase.kt index b5a5e24618..1cbbf34c9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/LokiThreadDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/LokiThreadDatabase.kt @@ -52,6 +52,13 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa } } + fun getThreadId(openGroup: OpenGroup): Long? { + val database = databaseHelper.readableDatabase + return database.get(publicChatTable, "$publicChat = ?", arrayOf(JsonUtil.toJson(openGroup.toJson()))) { cursor -> + cursor.getLong(threadID) + } + } + fun setOpenGroupChat(openGroup: OpenGroup, threadID: Long) { if (threadID < 0) { return 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 eb8ad10105..0ed7665a96 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -83,6 +83,7 @@ import org.thoughtcrime.securesms.database.model.ReactionRecord import org.thoughtcrime.securesms.dependencies.ConfigFactory import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.groups.ClosedGroupManager +import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.groups.OpenGroupManager import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob import org.thoughtcrime.securesms.mms.PartAuthority @@ -95,6 +96,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co ThreadDatabase.ConversationThreadUpdateListener { override fun threadCreated(address: Address, threadId: Long) { + Log.wtf("Loki", "Create thread for $address\ncontext:\n${Thread.currentThread().stackTrace.joinToString("\n")}") val localUserAddress = getUserPublicKey() ?: return if (!getRecipientApproved(address) && localUserAddress != address.serialize()) return // don't store unapproved / message requests @@ -136,7 +138,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } override fun threadDeleted(address: Address, threadId: Long) { - + Log.wtf("Loki", "Delete thread for $address\ncontext:\n${Thread.currentThread().stackTrace.joinToString("\n")}") val volatile = configFactory.convoVolatile ?: return if (address.isGroup) { val groups = configFactory.userGroups ?: return @@ -1062,8 +1064,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } override fun getThreadId(openGroup: OpenGroup): Long? { - val address = fromSerialized("${openGroup.server}.${openGroup.room}") - return getThreadId(address) + return GroupManager.getOpenGroupThreadID("${openGroup.server.removeSuffix("/")}.${openGroup.room}", context) } override fun getThreadId(address: Address): Long? { @@ -1140,6 +1141,8 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co if (key.size != ProfileKeyUtil.PROFILE_KEY_BYTES) return@forEach profileManager.setProfilePicture(context, recipient, url, key) profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN) + } else { + profileManager.setProfilePicture(context, recipient, null, null) } if (contact.priority == PRIORITY_HIDDEN) { getThreadId(fromSerialized(contact.id))?.let { conversationThreadId -> 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 df8897a6fe..227621d7fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt @@ -43,6 +43,7 @@ object OpenGroupManager { val storage = MessagingModuleConfiguration.shared.storage val (serverGroups, toDelete) = storage.getAllOpenGroups().values.partition { storage.getThreadId(it) != null } toDelete.forEach { openGroup -> + Log.w("Loki", "Need to delete a group") delete(openGroup.server, openGroup.room, MessagingModuleConfiguration.shared.context) } @@ -116,7 +117,7 @@ object OpenGroupManager { val groupID = recipient.address.serialize() // Stop the poller if needed val openGroups = storage.getAllOpenGroups().filter { it.value.server == server } - if (openGroups.count() == 1) { + if (openGroups.isNotEmpty()) { synchronized(pollUpdaterLock) { val poller = pollers[server] poller?.stop() diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java index 3e80b7c10b..a652cf1e02 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java @@ -85,10 +85,10 @@ public class RetrieveProfileAvatarJob extends BaseJob { return; } - if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) { - Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar); - return; - } +// if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) { +// Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar); +// return; +// } if (TextUtils.isEmpty(profileAvatar)) { Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SharedConfigUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SharedConfigUtils.kt index 699b250e0d..d6b3bd3ed8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SharedConfigUtils.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SharedConfigUtils.kt @@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord fun ConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Boolean { val recipient = thread.recipient - if (recipient.isContactRecipient) { + if (recipient.isContactRecipient && recipient.isOpenGroupInboxRecipient) { return getOneToOne(recipient.address.serialize())?.unread == true } else if (recipient.isClosedGroupRecipient) { return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true diff --git a/libsession-util/src/main/cpp/contacts.h b/libsession-util/src/main/cpp/contacts.h index 75b06fc087..c5496a68c8 100644 --- a/libsession-util/src/main/cpp/contacts.h +++ b/libsession-util/src/main/cpp/contacts.h @@ -21,6 +21,7 @@ inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info approved = info.approved; approvedMe = info.approved_me; blocked = info.blocked; + auto created = info.created; jobject profilePic = util::serialize_user_pic(env, info.profile_picture); jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved, approvedMe, blocked, profilePic, info.priority, diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/Contact.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/Contact.kt index f7f7b0a5b7..8cc22a6afe 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/Contact.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/Contact.kt @@ -9,5 +9,5 @@ data class Contact( var blocked: Boolean = false, var profilePicture: UserPic = UserPic.DEFAULT, var priority: Int = 0, - var expiryMode: ExpiryMode + var expiryMode: ExpiryMode, ) \ No newline at end of file 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 f99d1c2cd7..10e514a702 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 @@ -263,6 +263,8 @@ fun MessageReceiver.handleVisibleMessage( if ((profileKeyValid && profileKeyChanged) || (profileKeyValid && needsProfilePicture)) { profileManager.setProfilePicture(context, recipient, profile.profilePictureURL, newProfileKey) profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN) + } else if (newProfileKey == null || newProfileKey.isEmpty() || profile.profilePictureURL.isNullOrEmpty()) { + profileManager.setProfilePicture(context, recipient, null, null) } } } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt index 967d03da4c..4a9ffb31c8 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt @@ -227,6 +227,7 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti // in case we had null configs, the array won't be fully populated // index of the sparse array key iterator should be the request index, with the key being the namespace configDebouncer.publish { + // TODO: add in specific ordering of config namespaces for processing requestSparseArray.keyIterator().withIndex().forEach { (requestIndex, key) -> responseList.getOrNull(requestIndex)?.let { rawResponse -> if (rawResponse["code"] as? Int != 200) {