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 98bd0c8e7e..f765a02ae1 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -7,10 +7,7 @@ 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.BaseCommunityInfo
-import network.loki.messenger.libsession_util.util.Conversation
-import network.loki.messenger.libsession_util.util.ExpiryMode
-import network.loki.messenger.libsession_util.util.UserPic
+import network.loki.messenger.libsession_util.util.*
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.BlindedIdMapping
@@ -468,6 +465,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
// Notify the user
val threadID = getOrCreateThreadIdFor(Address.fromSerialized(groupId))
insertOutgoingInfoMessage(context, groupId, SignalServiceGroup.Type.CREATION, title, members.map { it.serialize() }, admins.map { it.serialize() }, threadID, formationTimestamp)
+ // Don't create config group here, it's from a config update
// Start polling
ClosedGroupPollerV2.shared.startPolling(group.sessionId)
}
@@ -671,14 +669,55 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
override fun createGroup(groupId: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List, formationTimestamp: Long) {
DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
+ }
+
+ override fun createInitialConfigGroup(groupPublicKey: String, name: String, members: Map, formationTimestamp: Long, encryptionKeyPair: ECKeyPair) {
val volatiles = configFactory.convoVolatile ?: return
- val groupPublicKey = GroupUtil.doubleDecodeGroupId(groupId)
+ val userGroups = configFactory.userGroups ?: return
val groupVolatileConfig = volatiles.getOrConstructLegacyGroup(groupPublicKey)
groupVolatileConfig.lastRead = formationTimestamp
volatiles.set(groupVolatileConfig)
+ val groupInfo = GroupInfo.LegacyGroupInfo(
+ sessionId = groupPublicKey,
+ name = name,
+ members = members,
+ hidden = false,
+ encPubKey = encryptionKeyPair.publicKey.serialize(),
+ encSecKey = encryptionKeyPair.privateKey.serialize(),
+ disappearingTimer = 0L
+ )
+ // shouldn't exist, don't use getOrConstruct + copy
+ userGroups.set(groupInfo)
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
}
+ override fun updateGroupConfig(groupPublicKey: String) {
+ val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
+ val groupAddress = fromSerialized(groupID)
+ // TODO: probably add a check in here for isActive?
+ // TODO: also check if local user is a member / maybe run delete otherwise?
+ 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
+ val name = existingGroup.title
+ val admins = existingGroup.admins.map { it.serialize() }
+ val members = existingGroup.members.map { it.serialize() }
+ val membersMap = GroupUtil.createConfigMemberMap(admins = admins, members = members)
+ val latestKeyPair = getLatestClosedGroupEncryptionKeyPair(groupPublicKey)
+ ?: return Log.w("Loki-DBG", "No latest closed group encryption key pair for ${groupPublicKey.take(4)}...${groupPublicKey.takeLast(4)} when updating group config")
+ val recipientSettings = getRecipientSettings(groupAddress) ?: return
+ val threadID = getThreadId(groupAddress) ?: return
+ val groupInfo = userGroups.getOrConstructLegacyGroupInfo(groupPublicKey).copy(
+ name = name,
+ members = membersMap,
+ encPubKey = latestKeyPair.publicKey.serialize(),
+ encSecKey = latestKeyPair.privateKey.serialize(),
+ priority = if (isPinned(threadID)) 1 else 0,
+ disappearingTimer = recipientSettings.expireMessages.toLong()
+ )
+ userGroups.set(groupInfo)
+ }
+
override fun isGroupActive(groupPublicKey: String): Boolean {
return DatabaseComponent.get(context).groupDatabase().getGroup(GroupUtil.doubleEncodeGroupID(groupPublicKey)).orNull()?.isActive == true
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ClosedGroupManager.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/ClosedGroupManager.kt
index a61feaef1b..b11c3ebc91 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/groups/ClosedGroupManager.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ClosedGroupManager.kt
@@ -1,11 +1,17 @@
package org.thoughtcrime.securesms.groups
import android.content.Context
+import network.loki.messenger.libsession_util.util.GroupInfo
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
import org.session.libsession.utilities.Address
+import org.session.libsession.utilities.GroupRecord
+import org.session.libsession.utilities.GroupUtil
+import org.session.libsession.utilities.recipients.Recipient
+import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.ApplicationContext
+import org.thoughtcrime.securesms.dependencies.ConfigFactory
object ClosedGroupManager {
@@ -28,4 +34,31 @@ object ClosedGroupManager {
}
}
+ fun ConfigFactory.removeLegacyGroup(group: GroupRecord): Boolean {
+ val groups = userGroups ?: return false
+ if (!group.isClosedGroup) return false
+ val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
+ return groups.eraseLegacyGroup(groupPublicKey)
+ }
+
+ fun ConfigFactory.updateLegacyGroup(groupRecipientSettings: Recipient.RecipientSettings, group: GroupRecord) {
+ val groups = userGroups ?: return
+ if (!group.isClosedGroup) return
+ val storage = MessagingModuleConfiguration.shared.storage
+ val threadId = storage.getThreadId(group.encodedId) ?: return
+ val groupPublicKey = GroupUtil.doubleEncodeGroupID(group.getId())
+ val latestKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: return
+ val legacyInfo = groups.getOrConstructLegacyGroupInfo(groupPublicKey)
+ val latestMemberMap = GroupUtil.createConfigMemberMap(group.members.map(Address::serialize), group.admins.map(Address::serialize))
+ val toSet = legacyInfo.copy(
+ members = latestMemberMap,
+ name = group.title,
+ disappearingTimer = groupRecipientSettings.expireMessages.toLong(),
+ priority = if (storage.isPinned(threadId)) 1 else 0,
+ encSecKey = latestKeyPair.privateKey.serialize(),
+ encPubKey = latestKeyPair.publicKey.serialize()
+ )
+ groups.set(toSet)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt
index 62e762316b..5dd2074ba2 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt
@@ -16,6 +16,7 @@ import androidx.loader.app.LoaderManager
import androidx.loader.content.Loader
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.task
@@ -28,16 +29,28 @@ import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.ThemeUtil
import org.session.libsession.utilities.recipients.Recipient
+import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.contacts.SelectContactsActivity
+import org.thoughtcrime.securesms.database.Storage
+import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
+import org.thoughtcrime.securesms.groups.ClosedGroupManager.updateLegacyGroup
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
import java.io.IOException
+import javax.inject.Inject
+@AndroidEntryPoint
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
+
+ @Inject
+ lateinit var groupConfigFactory: ConfigFactory
+ @Inject
+ lateinit var storage: Storage
+
private val originalMembers = HashSet()
private val zombies = HashSet()
private val members = HashSet()
@@ -306,6 +319,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
promise.successUi {
loaderContainer.fadeOut()
isLoading = false
+ updateGroupConfig()
finish()
}.failUi { exception ->
val message = if (exception is MessageSender.Error) exception.description else "An error occurred"
@@ -316,5 +330,13 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
}
}
- class GroupMembers(val members: List, val zombieMembers: List) { }
+ private fun updateGroupConfig() {
+ val latestRecipient = storage.getRecipientSettings(Address.fromSerialized(groupID))
+ ?: return Log.w("Loki", "No recipient settings when trying to update group config")
+ val latestGroup = storage.getGroup(groupID)
+ ?: return Log.w("Loki", "No group record when trying to update group config")
+ groupConfigFactory.updateLegacyGroup(latestRecipient, latestGroup)
+ }
+
+ class GroupMembers(val members: List, val zombieMembers: List)
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java
index a3d0e6d252..d4c5acf4ed 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java
@@ -6,6 +6,7 @@ import android.graphics.Bitmap;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.DistributionTypes;
import org.session.libsession.utilities.GroupUtil;
@@ -16,11 +17,14 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
import org.thoughtcrime.securesms.util.BitmapUtil;
+import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;
+import network.loki.messenger.libsession_util.UserGroupsConfig;
+
public class GroupManager {
public static long getOpenGroupThreadID(String id, @NonNull Context context) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
index 13c74980e0..bbdd48d129 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
@@ -625,7 +625,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
OpenGroupManager.delete(v2OpenGroup.server, v2OpenGroup.room, this@HomeActivity)
} else {
lifecycleScope.launch(Dispatchers.IO) {
- threadDb.deleteConversation(threadID)
+ storage.deleteConversation(threadID)
}
}
// Update the badge count
diff --git a/app/src/main/java/org/thoughtcrime/securesms/repository/ConversationRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/repository/ConversationRepository.kt
index b880c10ad7..4e08a4510a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/repository/ConversationRepository.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/repository/ConversationRepository.kt
@@ -257,13 +257,13 @@ class DefaultConversationRepository @Inject constructor(
override suspend fun deleteThread(threadId: Long): ResultOf {
sessionJobDb.cancelPendingMessageSendJobs(threadId)
- threadDb.deleteConversation(threadId)
+ storage.deleteConversation(threadId)
return ResultOf.Success(Unit)
}
override suspend fun deleteMessageRequest(thread: ThreadRecord): ResultOf {
sessionJobDb.cancelPendingMessageSendJobs(thread.threadId)
- threadDb.deleteConversation(thread.threadId)
+ storage.deleteConversation(thread.threadId)
return ResultOf.Success(Unit)
}
@@ -290,7 +290,7 @@ class DefaultConversationRepository @Inject constructor(
override fun declineMessageRequest(threadId: Long) {
sessionJobDb.cancelPendingMessageSendJobs(threadId)
- threadDb.deleteConversation(threadId)
+ storage.deleteConversation(threadId)
}
override fun hasReceived(threadId: Long): Boolean {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt
index 0850ba1f75..5a405a8bf7 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConfigurationMessageUtilities.kt
@@ -6,11 +6,7 @@ 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.BaseCommunityInfo
-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 network.loki.messenger.libsession_util.util.*
import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.jobs.ConfigurationSyncJob
@@ -21,6 +17,7 @@ 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
@@ -163,7 +160,8 @@ object ConfigurationMessageUtilities {
approved = settings.isApproved,
approvedMe = settings.hasApprovedMe(),
profilePicture = userPic ?: UserPic.DEFAULT,
- priority = if (isPinned) 1 else 0
+ priority = if (isPinned) 1 else 0,
+ expiryMode = if (settings.expireMessages == 0) ExpiryMode.NONE else ExpiryMode.AfterRead(settings.expireMessages.toLong())
)
contactConfig.set(contactInfo)
}
@@ -185,7 +183,7 @@ object ConfigurationMessageUtilities {
val contact = when {
recipient.isOpenGroupRecipient -> {
val openGroup = storage.getOpenGroup(current.threadId) ?: continue
- val (base, room, pubKey) = Conversation.Community.parseFullUrl(openGroup.joinURL) ?: continue
+ val (base, room, pubKey) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: continue
convoConfig.getOrConstructCommunity(base, room, pubKey)
}
recipient.isClosedGroupRecipient -> {
@@ -229,7 +227,9 @@ object ConfigurationMessageUtilities {
}
val allLgc = storage.getAllGroups().filter { it.isClosedGroup }.mapNotNull { group ->
- val groupPublicKey = GroupUtil.doubleDecodeGroupID(group.encodedId).toHexString()
+ val groupAddress = Address.fromSerialized(group.encodedId)
+ val groupPublicKey = GroupUtil.doubleDecodeGroupID(groupAddress.serialize()).toHexString()
+ val recipient = storage.getRecipientSettings(groupAddress) ?: return@mapNotNull null
val encryptionKeyPair = storage.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) ?: return@mapNotNull null
val threadId = storage.getThreadId(group.encodedId)
val isPinned = threadId?.let { storage.isPinned(threadId) } ?: false
@@ -243,7 +243,8 @@ object ConfigurationMessageUtilities {
hidden = threadId == null,
priority = if (isPinned) 1 else 0,
encPubKey = encryptionKeyPair.publicKey.serialize(),
- encSecKey = encryptionKeyPair.privateKey.serialize()
+ encSecKey = encryptionKeyPair.privateKey.serialize(),
+ disappearingTimer = recipient.expireMessages.toLong()
)
}
(allOpenGroups + allLgc).forEach { groupInfo ->
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/MockDataGenerator.kt b/app/src/main/java/org/thoughtcrime/securesms/util/MockDataGenerator.kt
index d4822ea6ab..06fda29306 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/MockDataGenerator.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/MockDataGenerator.kt
@@ -233,6 +233,7 @@ object MockDataGenerator {
val encryptionKeyPair = Curve.generateKeyPair()
storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, randomGroupPublicKey, System.currentTimeMillis())
storage.setExpirationTimer(groupId, 0)
+ storage.createInitialConfigGroup(randomGroupPublicKey, groupName, GroupUtil.createConfigMemberMap(members, setOf(adminUserId)), System.currentTimeMillis(), encryptionKeyPair)
// Add the group created message
if (userSessionId == adminUserId) {
diff --git a/libsession-util/src/main/cpp/user_groups.cpp b/libsession-util/src/main/cpp/user_groups.cpp
index 87bf697626..d2e416f399 100644
--- a/libsession-util/src/main/cpp/user_groups.cpp
+++ b/libsession-util/src/main/cpp/user_groups.cpp
@@ -232,4 +232,24 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_allLegacyGroupInfo
auto conf = ptrToUserGroups(env, thiz);
jobject legacy_stack = iterator_as_java_stack(env, conf->begin_legacy_groups(), conf->end());
return legacy_stack;
+}
+extern "C"
+JNIEXPORT jboolean JNICALL
+Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseCommunity(JNIEnv *env,
+ jobject thiz,
+ jobject base_community_info) {
+ auto conf = ptrToUserGroups(env, thiz);
+ auto base_community = util::deserialize_base_community(env, base_community_info);
+ return conf->erase_community(base_community.base_url(),base_community.room());
+}
+extern "C"
+JNIEXPORT jboolean JNICALL
+Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseLegacyGroup(JNIEnv *env,
+ jobject thiz,
+ jstring session_id) {
+ auto conf = ptrToUserGroups(env, thiz);
+ auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
+ bool return_bool = conf->erase_legacy_group(session_id_bytes);
+ env->ReleaseStringUTFChars(session_id, session_id_bytes);
+ return return_bool;
}
\ No newline at end of file
diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt
index 7aa5546a67..c3f92d1206 100644
--- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt
+++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt
@@ -1,10 +1,6 @@
package network.loki.messenger.libsession_util
-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 network.loki.messenger.libsession_util.util.*
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
@@ -160,6 +156,8 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
external fun set(legacyGroupInfo: GroupInfo.LegacyGroupInfo)
external fun erase(communityInfo: GroupInfo.CommunityGroupInfo)
external fun erase(legacyGroupInfo: GroupInfo.LegacyGroupInfo)
+ external fun eraseCommunity(baseCommunityInfo: BaseCommunityInfo): Boolean
+ external fun eraseLegacyGroup(sessionId: String): Boolean
external fun sizeCommunityInfo(): Int
external fun sizeLegacyGroupInfo(): Int
external fun size(): Int
diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
index 0606ebbdd6..2539547977 100644
--- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
+++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt
@@ -121,6 +121,8 @@ interface StorageProtocol {
// Closed Groups
fun getGroup(groupID: String): GroupRecord?
fun createGroup(groupID: String, title: String?, members: List, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List, formationTimestamp: Long)
+ fun createInitialConfigGroup(groupPublicKey: String, name: String, members: Map, formationTimestamp: Long, encryptionKeyPair: ECKeyPair)
+ fun updateGroupConfig(groupPublicKey: String)
fun isGroupActive(groupPublicKey: String): Boolean
fun setActive(groupID: String, value: Boolean)
fun getZombieMembers(groupID: String): Set
diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt
index b6bb5170e1..d3c9effd35 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt
@@ -73,6 +73,7 @@ fun MessageSender.create(name: String, members: Collection): Promise): Promise, name: String) {
- val context = MessagingModuleConfiguration.shared.context
- val storage = MessagingModuleConfiguration.shared.storage
- val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
- val group = storage.getGroup(groupID) ?: run {
- Log.d("Loki", "Can't update nonexistent closed group.")
- throw Error.NoThread
- }
- // Update name if needed
- if (name != group.title) { setName(groupPublicKey, name) }
- // Add members if needed
- val addedMembers = members - group.members.map { it.serialize() }
- if (!addedMembers.isEmpty()) { addMembers(groupPublicKey, addedMembers) }
- // Remove members if needed
- val removedMembers = group.members.map { it.serialize() } - members
- if (removedMembers.isEmpty()) { removeMembers(groupPublicKey, removedMembers) }
-}
-
fun MessageSender.setName(groupPublicKey: String, newName: String) {
val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage
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 e7019709bc..680a583bec 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
@@ -437,8 +437,23 @@ private fun MessageReceiver.handleClosedGroupControlMessage(message: ClosedGroup
is ClosedGroupControlMessage.Kind.MembersRemoved -> handleClosedGroupMembersRemoved(message)
is ClosedGroupControlMessage.Kind.MemberLeft -> handleClosedGroupMemberLeft(message)
}
+ if (message.kind !is ClosedGroupControlMessage.Kind.New) {
+ // update the config
+ val closedGroupPublicKey = message.getPublicKey()
+ val storage = MessagingModuleConfiguration.shared.storage
+ storage.updateGroupConfig(closedGroupPublicKey)
+ }
}
+private fun ClosedGroupControlMessage.getPublicKey(): String = kind!!.let { when (it) {
+ is ClosedGroupControlMessage.Kind.New -> it.publicKey.toByteArray().toHexString()
+ is ClosedGroupControlMessage.Kind.EncryptionKeyPair -> it.publicKey?.toByteArray()?.toHexString() ?: groupPublicKey!!
+ is ClosedGroupControlMessage.Kind.MemberLeft -> groupPublicKey!!
+ is ClosedGroupControlMessage.Kind.MembersAdded -> groupPublicKey!!
+ is ClosedGroupControlMessage.Kind.MembersRemoved -> groupPublicKey!!
+ is ClosedGroupControlMessage.Kind.NameChange -> groupPublicKey!!
+}}
+
private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMessage) {
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.New ?: return
val recipient = Recipient.from(MessagingModuleConfiguration.shared.context, Address.fromSerialized(message.sender!!), false)
@@ -476,6 +491,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
storage.addClosedGroupPublicKey(groupPublicKey)
// Store the encryption key pair
storage.addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey, sentTimestamp)
+ storage.createInitialConfigGroup(groupPublicKey, name, GroupUtil.createConfigMemberMap(members, admins), formationTimestamp, encryptionKeyPair)
// Set expiration timer
storage.setExpirationTimer(groupID, expireTimer)
// Notify the PN server
diff --git a/libsession/src/main/java/org/session/libsession/utilities/GroupUtil.kt b/libsession/src/main/java/org/session/libsession/utilities/GroupUtil.kt
index 3f1563e3d1..bfab2585de 100644
--- a/libsession/src/main/java/org/session/libsession/utilities/GroupUtil.kt
+++ b/libsession/src/main/java/org/session/libsession/utilities/GroupUtil.kt
@@ -1,5 +1,6 @@
package org.session.libsession.utilities
+import network.loki.messenger.libsession_util.util.GroupInfo
import org.session.libsignal.messages.SignalServiceGroup
import org.session.libsignal.utilities.Hex
import java.io.IOException
@@ -102,4 +103,22 @@ object GroupUtil {
fun doubleDecodeGroupId(groupID: String): String {
return Hex.toStringCondensed(getDecodedGroupIDAsData(getDecodedGroupID(groupID)))
}
+
+ fun createConfigMemberMap(
+ members: Collection,
+ admins: Collection
+ ): Map {
+ // Start with admins
+ val memberMap = admins.associate {
+ it to true
+ }.toMutableMap()
+
+ // Add the remaining members (there may be duplicates, so only add ones that aren't already in there from admins)
+ for (member in members) {
+ if (!memberMap.contains(member)) {
+ memberMap[member] = false
+ }
+ }
+ return memberMap
+ }
}
\ No newline at end of file