feat: add almost all group editing cases, need to hook into the thread deletion for groups in the user groups

This commit is contained in:
0x330a
2023-03-15 17:24:17 +11:00
parent eca5712282
commit c28fe290df
14 changed files with 180 additions and 42 deletions

View File

@@ -121,6 +121,8 @@ interface StorageProtocol {
// Closed Groups
fun getGroup(groupID: String): GroupRecord?
fun createGroup(groupID: String, title: String?, members: List<Address>, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List<Address>, formationTimestamp: Long)
fun createInitialConfigGroup(groupPublicKey: String, name: String, members: Map<String, Boolean>, formationTimestamp: Long, encryptionKeyPair: ECKeyPair)
fun updateGroupConfig(groupPublicKey: String)
fun isGroupActive(groupPublicKey: String): Boolean
fun setActive(groupID: String, value: Boolean)
fun getZombieMembers(groupID: String): Set<String>

View File

@@ -73,6 +73,7 @@ fun MessageSender.create(name: String, members: Collection<String>): Promise<Str
// Notify the user
val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
storage.insertOutgoingInfoMessage(context, groupID, SignalServiceGroup.Type.CREATION, name, members, admins, threadID, sentTime)
storage.createInitialConfigGroup(groupPublicKey, name, GroupUtil.createConfigMemberMap(members, admins), sentTime, encryptionKeyPair)
// Notify the PN server
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, groupPublicKey, userPublicKey)
// Start polling
@@ -84,24 +85,6 @@ fun MessageSender.create(name: String, members: Collection<String>): Promise<Str
return deferred.promise
}
fun MessageSender.update(groupPublicKey: String, members: List<String>, 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

View File

@@ -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

View File

@@ -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<String>,
admins: Collection<String>
): Map<String, Boolean> {
// 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
}
}