fix: open group threads and avatar downloads

This commit is contained in:
0x330a 2023-05-24 17:34:27 +10:00
parent c5299c1010
commit 78d1e9d387
No known key found for this signature in database
GPG Key ID: 267811D6E6A2698C
9 changed files with 25 additions and 10 deletions

View File

@ -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) { fun setOpenGroupChat(openGroup: OpenGroup, threadID: Long) {
if (threadID < 0) { if (threadID < 0) {
return return

View File

@ -83,6 +83,7 @@ import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.dependencies.ConfigFactory import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.groups.ClosedGroupManager import org.thoughtcrime.securesms.groups.ClosedGroupManager
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.groups.OpenGroupManager import org.thoughtcrime.securesms.groups.OpenGroupManager
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.mms.PartAuthority
@ -95,6 +96,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
ThreadDatabase.ConversationThreadUpdateListener { ThreadDatabase.ConversationThreadUpdateListener {
override fun threadCreated(address: Address, threadId: Long) { 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 val localUserAddress = getUserPublicKey() ?: return
if (!getRecipientApproved(address) && localUserAddress != address.serialize()) return // don't store unapproved / message requests 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) { 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 val volatile = configFactory.convoVolatile ?: return
if (address.isGroup) { if (address.isGroup) {
val groups = configFactory.userGroups ?: return 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? { override fun getThreadId(openGroup: OpenGroup): Long? {
val address = fromSerialized("${openGroup.server}.${openGroup.room}") return GroupManager.getOpenGroupThreadID("${openGroup.server.removeSuffix("/")}.${openGroup.room}", context)
return getThreadId(address)
} }
override fun getThreadId(address: Address): Long? { 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 if (key.size != ProfileKeyUtil.PROFILE_KEY_BYTES) return@forEach
profileManager.setProfilePicture(context, recipient, url, key) profileManager.setProfilePicture(context, recipient, url, key)
profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN) profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN)
} else {
profileManager.setProfilePicture(context, recipient, null, null)
} }
if (contact.priority == PRIORITY_HIDDEN) { if (contact.priority == PRIORITY_HIDDEN) {
getThreadId(fromSerialized(contact.id))?.let { conversationThreadId -> getThreadId(fromSerialized(contact.id))?.let { conversationThreadId ->

View File

@ -43,6 +43,7 @@ object OpenGroupManager {
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val (serverGroups, toDelete) = storage.getAllOpenGroups().values.partition { storage.getThreadId(it) != null } val (serverGroups, toDelete) = storage.getAllOpenGroups().values.partition { storage.getThreadId(it) != null }
toDelete.forEach { openGroup -> toDelete.forEach { openGroup ->
Log.w("Loki", "Need to delete a group")
delete(openGroup.server, openGroup.room, MessagingModuleConfiguration.shared.context) delete(openGroup.server, openGroup.room, MessagingModuleConfiguration.shared.context)
} }
@ -116,7 +117,7 @@ object OpenGroupManager {
val groupID = recipient.address.serialize() val groupID = recipient.address.serialize()
// Stop the poller if needed // Stop the poller if needed
val openGroups = storage.getAllOpenGroups().filter { it.value.server == server } val openGroups = storage.getAllOpenGroups().filter { it.value.server == server }
if (openGroups.count() == 1) { if (openGroups.isNotEmpty()) {
synchronized(pollUpdaterLock) { synchronized(pollUpdaterLock) {
val poller = pollers[server] val poller = pollers[server]
poller?.stop() poller?.stop()

View File

@ -85,10 +85,10 @@ public class RetrieveProfileAvatarJob extends BaseJob {
return; return;
} }
if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) { // if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar); // Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar);
return; // return;
} // }
if (TextUtils.isEmpty(profileAvatar)) { if (TextUtils.isEmpty(profileAvatar)) {
Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize()); Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize());

View File

@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord
fun ConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Boolean { fun ConversationVolatileConfig.getConversationUnread(thread: ThreadRecord): Boolean {
val recipient = thread.recipient val recipient = thread.recipient
if (recipient.isContactRecipient) { if (recipient.isContactRecipient && recipient.isOpenGroupInboxRecipient) {
return getOneToOne(recipient.address.serialize())?.unread == true return getOneToOne(recipient.address.serialize())?.unread == true
} else if (recipient.isClosedGroupRecipient) { } else if (recipient.isClosedGroupRecipient) {
return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true return getLegacyClosedGroup(GroupUtil.doubleDecodeGroupId(recipient.address.toGroupString()))?.unread == true

View File

@ -21,6 +21,7 @@ inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info
approved = info.approved; approved = info.approved;
approvedMe = info.approved_me; approvedMe = info.approved_me;
blocked = info.blocked; blocked = info.blocked;
auto created = info.created;
jobject profilePic = util::serialize_user_pic(env, info.profile_picture); jobject profilePic = util::serialize_user_pic(env, info.profile_picture);
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved, jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved,
approvedMe, blocked, profilePic, info.priority, approvedMe, blocked, profilePic, info.priority,

View File

@ -9,5 +9,5 @@ data class Contact(
var blocked: Boolean = false, var blocked: Boolean = false,
var profilePicture: UserPic = UserPic.DEFAULT, var profilePicture: UserPic = UserPic.DEFAULT,
var priority: Int = 0, var priority: Int = 0,
var expiryMode: ExpiryMode var expiryMode: ExpiryMode,
) )

View File

@ -263,6 +263,8 @@ fun MessageReceiver.handleVisibleMessage(
if ((profileKeyValid && profileKeyChanged) || (profileKeyValid && needsProfilePicture)) { if ((profileKeyValid && profileKeyChanged) || (profileKeyValid && needsProfilePicture)) {
profileManager.setProfilePicture(context, recipient, profile.profilePictureURL, newProfileKey) profileManager.setProfilePicture(context, recipient, profile.profilePictureURL, newProfileKey)
profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN) profileManager.setUnidentifiedAccessMode(context, recipient, Recipient.UnidentifiedAccessMode.UNKNOWN)
} else if (newProfileKey == null || newProfileKey.isEmpty() || profile.profilePictureURL.isNullOrEmpty()) {
profileManager.setProfilePicture(context, recipient, null, null)
} }
} }
} }

View File

@ -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 // 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 // index of the sparse array key iterator should be the request index, with the key being the namespace
configDebouncer.publish { configDebouncer.publish {
// TODO: add in specific ordering of config namespaces for processing
requestSparseArray.keyIterator().withIndex().forEach { (requestIndex, key) -> requestSparseArray.keyIterator().withIndex().forEach { (requestIndex, key) ->
responseList.getOrNull(requestIndex)?.let { rawResponse -> responseList.getOrNull(requestIndex)?.let { rawResponse ->
if (rawResponse["code"] as? Int != 200) { if (rawResponse["code"] as? Int != 200) {