mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 20:45:17 +00:00
feat: open group joining should work now
This commit is contained in:
parent
c28fe290df
commit
061cff8437
@ -40,7 +40,7 @@ class JoinOpenGroupDialog(private val name: String, private val url: String) : B
|
||||
ThreadUtils.queue {
|
||||
try {
|
||||
OpenGroupManager.add(openGroup.server, openGroup.room, openGroup.serverPublicKey, activity)
|
||||
MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(openGroup.server)
|
||||
MessagingModuleConfiguration.shared.storage.onOpenGroupAdded(openGroup.server, openGroup.room)
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(activity)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(activity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
|
||||
|
@ -7,13 +7,18 @@ import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||
import network.loki.messenger.libsession_util.UserProfile
|
||||
import network.loki.messenger.libsession_util.util.*
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsession.avatars.AvatarHelper
|
||||
import org.session.libsession.database.StorageProtocol
|
||||
import org.session.libsession.messaging.BlindedIdMapping
|
||||
import org.session.libsession.messaging.calls.CallMessageType
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
||||
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
|
||||
import org.session.libsession.messaging.jobs.ConfigurationSyncJob
|
||||
import org.session.libsession.messaging.jobs.GroupAvatarDownloadJob
|
||||
import org.session.libsession.messaging.jobs.Job
|
||||
@ -64,6 +69,7 @@ import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.KeyHelper
|
||||
import org.session.libsignal.utilities.Log
|
||||
@ -400,8 +406,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val lgc = userGroups.allLegacyGroupInfo()
|
||||
val allOpenGroups = getAllOpenGroups()
|
||||
val toDeleteCommunities = allOpenGroups.filter { it.value.joinURL !in communities.map { it.community.fullUrl() } }
|
||||
val existingOpenGroups: Map<Long, OpenGroup> = allOpenGroups.filterKeys { it !in toDeleteCommunities.keys }
|
||||
val existingJoinUrls = existingOpenGroups.values.map { it.joinURL }
|
||||
|
||||
val existingCommunities: Map<Long, OpenGroup> = allOpenGroups.filterKeys { it !in toDeleteCommunities.keys }
|
||||
val toAddCommunities = communities.filter { it.community.fullUrl() !in existingCommunities.map { it.value.joinURL } }
|
||||
|
||||
val existingJoinUrls = existingCommunities.values.map { it.joinURL }
|
||||
val existingClosedGroups = getAllGroups()
|
||||
val lgcIds = lgc.map { it.sessionId }
|
||||
val toDeleteClosedGroups = existingClosedGroups.filter { group ->
|
||||
@ -422,6 +431,14 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
}
|
||||
}
|
||||
|
||||
toAddCommunities.forEach { toAddCommunity ->
|
||||
val joinUrl = toAddCommunity.community.fullUrl()
|
||||
if (!hasBackgroundGroupAddJob(joinUrl)) {
|
||||
Log.d("Loki-DBG", "Doesn't contain background job for open group, adding from config update")
|
||||
JobQueue.shared.add(BackgroundGroupAddJob(joinUrl))
|
||||
}
|
||||
}
|
||||
|
||||
for (groupInfo in communities) {
|
||||
val groupBaseCommunity = groupInfo.community
|
||||
if (groupBaseCommunity.fullUrl() !in existingJoinUrls) {
|
||||
@ -429,7 +446,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val (threadId, _) = OpenGroupManager.add(groupBaseCommunity.baseUrl, groupBaseCommunity.room, groupBaseCommunity.pubKeyHex, context)
|
||||
threadDb.setPinned(threadId, groupInfo.priority >= 1)
|
||||
} else {
|
||||
val (threadId, _) = existingOpenGroups.entries.first { (_, v) -> v.joinURL == groupInfo.community.fullUrl() }
|
||||
val (threadId, _) = existingCommunities.entries.first { (_, v) -> v.joinURL == groupInfo.community.fullUrl() }
|
||||
threadDb.setPinned(threadId, groupInfo.priority >= 1)
|
||||
}
|
||||
}
|
||||
@ -699,6 +716,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val existingGroup = getGroup(groupID)
|
||||
?: return Log.w("Loki-DBG", "No existing group for ${groupPublicKey.take(4)}...${groupPublicKey.takeLast(4)} when updating group config")
|
||||
val userGroups = configFactory.userGroups ?: return
|
||||
if (!existingGroup.isActive) {
|
||||
userGroups.eraseLegacyGroup(groupPublicKey)
|
||||
return
|
||||
}
|
||||
val name = existingGroup.title
|
||||
val admins = existingGroup.admins.map { it.serialize() }
|
||||
val members = existingGroup.members.map { it.serialize() }
|
||||
@ -855,8 +876,19 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return OpenGroupManager.addOpenGroup(urlAsString, context)
|
||||
}
|
||||
|
||||
override fun onOpenGroupAdded(server: String) {
|
||||
override fun onOpenGroupAdded(server: String, room: String) {
|
||||
OpenGroupManager.restartPollerForServer(server.removeSuffix("/"))
|
||||
val groups = configFactory.userGroups ?: return
|
||||
val volatileConfig = configFactory.convoVolatile ?: return
|
||||
val openGroup = getOpenGroup(room, server) ?: return
|
||||
val (infoServer, infoRoom, pubKey) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return
|
||||
val pubKeyHex = Hex.toStringCondensed(pubKey)
|
||||
val communityInfo = groups.getOrConstructCommunityInfo(infoServer, infoRoom, pubKeyHex)
|
||||
groups.set(communityInfo)
|
||||
val volatile = volatileConfig.getOrConstructCommunity(infoServer, infoRoom, pubKey).copy(
|
||||
lastRead = SnodeAPI.nowWithOffset,
|
||||
)
|
||||
volatileConfig.set(volatile)
|
||||
}
|
||||
|
||||
override fun hasBackgroundGroupAddJob(groupJoinUrl: String): Boolean {
|
||||
|
@ -11,6 +11,7 @@ import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class ConfigFactory(private val context: Context,
|
||||
private val configDatabase: ConfigDatabase,
|
||||
@ -34,6 +35,7 @@ class ConfigFactory(private val context: Context,
|
||||
private var _convoVolatileConfig: ConversationVolatileConfig? = null
|
||||
private val userGroupsLock = Object()
|
||||
private var _userGroups: UserGroupsConfig? = null
|
||||
private val factoryExecutor = Executors.newSingleThreadExecutor()
|
||||
|
||||
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
|
||||
fun registerListener(listener: ConfigFactoryUpdateListener) { listeners += listener }
|
||||
@ -127,6 +129,7 @@ class ConfigFactory(private val context: Context,
|
||||
}
|
||||
|
||||
override fun persist(forConfigObject: ConfigBase) {
|
||||
factoryExecutor.submit {
|
||||
listeners.forEach { listener ->
|
||||
listener.notifyUpdates(forConfigObject)
|
||||
}
|
||||
@ -138,5 +141,6 @@ class ConfigFactory(private val context: Context,
|
||||
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -79,7 +79,7 @@ class JoinCommunityFragment : Fragment() {
|
||||
val openGroupID = "$sanitizedServer.${openGroup.room}"
|
||||
OpenGroupManager.add(sanitizedServer, openGroup.room, openGroup.serverPublicKey, requireContext())
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
storage.onOpenGroupAdded(sanitizedServer)
|
||||
storage.onOpenGroupAdded(sanitizedServer, openGroup.room)
|
||||
val threadID = GroupManager.getOpenGroupThreadID(openGroupID, requireContext())
|
||||
val groupID = GroupUtil.getEncodedOpenGroupID(openGroupID.toByteArray())
|
||||
|
||||
|
@ -3,9 +3,11 @@ package org.thoughtcrime.securesms.sskenvironment
|
||||
import android.content.Context
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.messaging.utilities.SessionId
|
||||
import org.session.libsession.utilities.SSKEnvironment
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
@ -86,6 +88,8 @@ class ProfileManager(private val context: Context, private val configFactory: Co
|
||||
override fun contactUpdatedInternal(contact: Contact) {
|
||||
val contactConfig = configFactory.contacts ?: return
|
||||
if (contact.sessionID == TextSecurePreferences.getLocalNumber(context)) return
|
||||
val sessionId = SessionId(contact.sessionID)
|
||||
if (sessionId.prefix != IdPrefix.STANDARD) return // only internally store standard session IDs
|
||||
contactConfig.upsertContact(contact.sessionID) {
|
||||
this.name = contact.name.orEmpty()
|
||||
this.nickname = contact.nickname.orEmpty()
|
||||
|
@ -6,7 +6,11 @@ import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||
import network.loki.messenger.libsession_util.UserGroupsConfig
|
||||
import network.loki.messenger.libsession_util.UserProfile
|
||||
import network.loki.messenger.libsession_util.util.*
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import nl.komponents.kovenant.Promise
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.ConfigurationSyncJob
|
||||
@ -17,7 +21,6 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.messaging.utilities.SessionId
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.SSKEnvironment
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.Log
|
||||
@ -167,6 +170,7 @@ object ConfigurationMessageUtilities {
|
||||
}
|
||||
val dump = contactConfig.dump()
|
||||
contactConfig.free()
|
||||
if (dump.isEmpty()) return null
|
||||
return dump
|
||||
}
|
||||
|
||||
@ -177,7 +181,7 @@ object ConfigurationMessageUtilities {
|
||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDb.approvedConversationList.use { cursor ->
|
||||
val reader = threadDb.readerFor(cursor)
|
||||
var current = reader.current
|
||||
var current = reader.next
|
||||
while (current != null) {
|
||||
val recipient = current.recipient
|
||||
val contact = when {
|
||||
@ -210,6 +214,7 @@ object ConfigurationMessageUtilities {
|
||||
|
||||
val dump = convoConfig.dump()
|
||||
convoConfig.free()
|
||||
if (dump.isEmpty()) return null
|
||||
return dump
|
||||
}
|
||||
|
||||
@ -226,7 +231,7 @@ object ConfigurationMessageUtilities {
|
||||
GroupInfo.CommunityGroupInfo(baseInfo, if (isPinned) 1 else 0)
|
||||
}
|
||||
|
||||
val allLgc = storage.getAllGroups().filter { it.isClosedGroup }.mapNotNull { group ->
|
||||
val allLgc = storage.getAllGroups().filter { it.isClosedGroup && it.isActive }.mapNotNull { group ->
|
||||
val groupAddress = Address.fromSerialized(group.encodedId)
|
||||
val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupAddress.serialize()).toHexString()
|
||||
val recipient = storage.getRecipientSettings(groupAddress) ?: return@mapNotNull null
|
||||
@ -252,6 +257,7 @@ object ConfigurationMessageUtilities {
|
||||
}
|
||||
val dump = groupConfig.dump()
|
||||
groupConfig.free()
|
||||
if (dump.isEmpty()) return null
|
||||
return dump
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_00024Companion_new
|
||||
|
||||
auto* user_groups = new session::config::UserGroups(secret_key, initial);
|
||||
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
|
||||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(user_groups));
|
||||
|
||||
@ -126,40 +126,21 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_CommunityGroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject community_info) {
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto deserialized = deserialize_community_info(env, community_info, conf);
|
||||
conf->set(deserialized);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_LegacyGroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject legacy_group_info) {
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject group_info) {
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto deserialized = deserialize_legacy_group_info(env, legacy_group_info, conf);
|
||||
conf->set(deserialized);
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_CommunityGroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject community_info) {
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto deserialized = deserialize_community_info(env, community_info, conf);
|
||||
auto communityInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacyInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
if (env->GetObjectClass(group_info) == communityInfo) {
|
||||
auto deserialized = deserialize_community_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_LegacyGroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject legacy_group_info) {
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto deserialized = deserialize_legacy_group_info(env, legacy_group_info, conf);
|
||||
} else if (env->GetObjectClass(group_info) == legacyInfo) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -1,6 +1,11 @@
|
||||
package network.loki.messenger.libsession_util
|
||||
|
||||
import network.loki.messenger.libsession_util.util.*
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.ConfigPush
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
||||
|
||||
|
||||
@ -152,10 +157,7 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun getOrConstructCommunityInfo(baseUrl: String, room: String, pubKeyHex: String): GroupInfo.CommunityGroupInfo
|
||||
external fun getOrConstructLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo
|
||||
external fun set(groupInfo: GroupInfo)
|
||||
external fun set(communityInfo: GroupInfo.CommunityGroupInfo)
|
||||
external fun set(legacyGroupInfo: GroupInfo.LegacyGroupInfo)
|
||||
external fun erase(communityInfo: GroupInfo.CommunityGroupInfo)
|
||||
external fun erase(legacyGroupInfo: GroupInfo.LegacyGroupInfo)
|
||||
external fun erase(communityInfo: GroupInfo)
|
||||
external fun eraseCommunity(baseCommunityInfo: BaseCommunityInfo): Boolean
|
||||
external fun eraseLegacyGroup(sessionId: String): Boolean
|
||||
external fun sizeCommunityInfo(): Int
|
||||
|
@ -72,7 +72,7 @@ interface StorageProtocol {
|
||||
fun updateOpenGroup(openGroup: OpenGroup)
|
||||
fun getOpenGroup(threadId: Long): OpenGroup?
|
||||
fun addOpenGroup(urlAsString: String): OpenGroupApi.RoomInfo?
|
||||
fun onOpenGroupAdded(server: String)
|
||||
fun onOpenGroupAdded(server: String, room: String)
|
||||
fun hasBackgroundGroupAddJob(groupJoinUrl: String): Boolean
|
||||
fun setOpenGroupServerMessageID(messageID: Long, serverID: Long, threadID: Long, isSms: Boolean)
|
||||
fun getOpenGroup(room: String, server: String): OpenGroup?
|
||||
|
@ -45,7 +45,7 @@ class BackgroundGroupAddJob(val joinUrl: String): Job {
|
||||
JobQueue.shared.add(GroupAvatarDownloadJob(openGroup.server, openGroup.room, imageId))
|
||||
}
|
||||
Log.d(KEY, "onOpenGroupAdded(${openGroup.server})")
|
||||
storage.onOpenGroupAdded(openGroup.server)
|
||||
storage.onOpenGroupAdded(openGroup.server, openGroup.room)
|
||||
} catch (e: Exception) {
|
||||
Log.e("OpenGroupDispatcher", "Failed to add group because",e)
|
||||
delegate?.handleJobFailed(this, dispatcherName, e)
|
||||
|
@ -165,9 +165,9 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) {
|
||||
.replace(OpenGroupApi.httpDefaultServer, OpenGroupApi.defaultServer)
|
||||
}) {
|
||||
if (allV2OpenGroups.contains(openGroup)) continue
|
||||
Log.d("OpenGroup", "All open groups doesn't contain $openGroup")
|
||||
Log.d("OpenGroup", "All open groups doesn't contain open group")
|
||||
if (!storage.hasBackgroundGroupAddJob(openGroup)) {
|
||||
Log.d("OpenGroup", "Doesn't contain background job for $openGroup, adding")
|
||||
Log.d("OpenGroup", "Doesn't contain background job for open group, adding")
|
||||
JobQueue.shared.add(BackgroundGroupAddJob(openGroup))
|
||||
}
|
||||
}
|
||||
|
@ -136,9 +136,9 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
||||
snode,
|
||||
userPublicKey,
|
||||
namespace,
|
||||
updateLatestHash = false,
|
||||
updateStoredHashes = false,
|
||||
).filter { (_, hash) -> !forConfigObject.currentHashes().contains(hash) }
|
||||
updateLatestHash = true,
|
||||
updateStoredHashes = true,
|
||||
) // TODO: might not be needed anymore .filter { (_, hash) -> !forConfigObject.currentHashes().contains(hash) }
|
||||
|
||||
if (messages.isEmpty()) {
|
||||
// no new messages to process
|
||||
|
Loading…
Reference in New Issue
Block a user