refactor: turn inner wrapped group edit calls into synchronous calls to remove unnecessary nesting

This commit is contained in:
jubb 2021-02-18 11:56:45 +11:00
parent f45a285141
commit c8f1c862fb
2 changed files with 107 additions and 141 deletions

View File

@ -280,18 +280,15 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
ClosedGroupsProtocolV2.explicitLeave(this, groupPublicKey!!) ClosedGroupsProtocolV2.explicitLeave(this, groupPublicKey!!)
} else { } else {
task { task {
val name = if (hasNameChanged) {
if (hasNameChanged) ClosedGroupsProtocolV2.explicitNameChange(this@EditClosedGroupActivity,groupPublicKey!!,name) ClosedGroupsProtocolV2.explicitNameChange(this@EditClosedGroupActivity, groupPublicKey!!, name)
else Promise.of(Unit) }
name.get()
members.filterNot { it in originalMembers }.let { adds -> members.filterNot { it in originalMembers }.let { adds ->
if (adds.isNotEmpty()) ClosedGroupsProtocolV2.explicitAddMembers(this@EditClosedGroupActivity, groupPublicKey!!, adds.map { it.address.serialize() }) if (adds.isNotEmpty()) ClosedGroupsProtocolV2.explicitAddMembers(this@EditClosedGroupActivity, groupPublicKey!!, adds.map { it.address.serialize() })
else Promise.of(Unit) }
}.get()
originalMembers.filterNot { it in members }.let { removes -> originalMembers.filterNot { it in members }.let { removes ->
if (removes.isNotEmpty()) ClosedGroupsProtocolV2.explicitRemoveMembers(this@EditClosedGroupActivity, groupPublicKey!!, removes.map { it.address.serialize() }) if (removes.isNotEmpty()) ClosedGroupsProtocolV2.explicitRemoveMembers(this@EditClosedGroupActivity, groupPublicKey!!, removes.map { it.address.serialize() })
else Promise.of(Unit) }
}.get()
} }
} }
promise.successUi { promise.successUi {

View File

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.loki.protocol
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import androidx.annotation.WorkerThread
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
import nl.komponents.kovenant.Promise import nl.komponents.kovenant.Promise
import nl.komponents.kovenant.deferred import nl.komponents.kovenant.deferred
@ -129,19 +130,16 @@ object ClosedGroupsProtocolV2 {
} }
@JvmStatic @JvmStatic
fun explicitAddMembers(context: Context, groupPublicKey: String, membersToAdd: List<String>): Promise<Any, java.lang.Exception> { fun explicitAddMembers(context: Context, groupPublicKey: String, membersToAdd: List<String>) {
return task {
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
return@task Error.NoThread throw Error.NoThread
} }
val updatedMembers = group.members.map { it.serialize() }.toSet() + membersToAdd val updatedMembers = group.members.map { it.serialize() }.toSet() + membersToAdd
// Save the new group members
groupDB.updateMembers(groupID, updatedMembers.map { Address.fromSerialized(it) })
val membersAsData = updatedMembers.map { Hex.fromStringCondensed(it) } val membersAsData = updatedMembers.map { Hex.fromStringCondensed(it) }
val newMembersAsData = membersToAdd.map { Hex.fromStringCondensed(it) } val newMembersAsData = membersToAdd.map { Hex.fromStringCondensed(it) }
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
@ -152,7 +150,7 @@ object ClosedGroupsProtocolV2 {
}.orNull() }.orNull()
if (encryptionKeyPair == null) { if (encryptionKeyPair == null) {
Log.d("Loki", "Couldn't get encryption key pair for closed group.") Log.d("Loki", "Couldn't get encryption key pair for closed group.")
return@task Error.NoKeyPair throw Error.NoKeyPair
} }
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
@ -160,6 +158,8 @@ object ClosedGroupsProtocolV2 {
val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime) val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime)
job.setContext(context) job.setContext(context)
job.onRun() // Run the job immediately job.onRun() // Run the job immediately
// Save the new group members
groupDB.updateMembers(groupID, updatedMembers.map { Address.fromSerialized(it) })
// Notify the user // Notify the user
val infoType = GroupContext.Type.UPDATE val infoType = GroupContext.Type.UPDATE
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false))
@ -173,11 +173,9 @@ object ClosedGroupsProtocolV2 {
ApplicationContext.getInstance(context).jobManager.add(newMemberJob) ApplicationContext.getInstance(context).jobManager.add(newMemberJob)
} }
} }
}
@JvmStatic @JvmStatic
fun explicitRemoveMembers(context: Context, groupPublicKey: String, membersToRemove: List<String>): Promise<Any, Exception> { fun explicitRemoveMembers(context: Context, groupPublicKey: String, membersToRemove: List<String>) {
return task {
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val apiDB = DatabaseFactory.getLokiAPIDatabase(context) val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
@ -185,22 +183,20 @@ object ClosedGroupsProtocolV2 {
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
return@task Error.NoThread throw Error.NoThread
} }
val updatedMembers = group.members.map { it.serialize() }.toSet() - membersToRemove val updatedMembers = group.members.map { it.serialize() }.toSet() - membersToRemove
// Save the new group members
groupDB.updateMembers(groupID, updatedMembers.map { Address.fromSerialized(it) })
val removeMembersAsData = membersToRemove.map { Hex.fromStringCondensed(it) } val removeMembersAsData = membersToRemove.map { Hex.fromStringCondensed(it) }
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
val sentTime = System.currentTimeMillis() val sentTime = System.currentTimeMillis()
val encryptionKeyPair = apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey) val encryptionKeyPair = apiDB.getLatestClosedGroupEncryptionKeyPair(groupPublicKey)
if (encryptionKeyPair == null) { if (encryptionKeyPair == null) {
Log.d("Loki", "Couldn't get encryption key pair for closed group.") Log.d("Loki", "Couldn't get encryption key pair for closed group.")
return@task Error.NoKeyPair throw Error.NoKeyPair
} }
if (membersToRemove.any { it in admins } && updatedMembers.isNotEmpty()) { if (membersToRemove.any { it in admins } && updatedMembers.isNotEmpty()) {
Log.d("Loki", "Can't remove admin from closed group unless the group is destroyed entirely.") Log.d("Loki", "Can't remove admin from closed group unless the group is destroyed entirely.")
return@task Error.InvalidUpdate throw Error.InvalidUpdate
} }
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
@ -208,6 +204,8 @@ object ClosedGroupsProtocolV2 {
val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime) val job = ClosedGroupUpdateMessageSendJobV2(groupPublicKey, memberUpdateKind, sentTime)
job.setContext(context) job.setContext(context)
job.onRun() // Run the job immediately job.onRun() // Run the job immediately
// Save the new group members
groupDB.updateMembers(groupID, updatedMembers.map { Address.fromSerialized(it) })
// Notify the user // Notify the user
val infoType = GroupContext.Type.UPDATE val infoType = GroupContext.Type.UPDATE
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false))
@ -216,14 +214,10 @@ object ClosedGroupsProtocolV2 {
if (isCurrentUserAdmin) { if (isCurrentUserAdmin) {
generateAndSendNewEncryptionKeyPair(context, groupPublicKey, updatedMembers) generateAndSendNewEncryptionKeyPair(context, groupPublicKey, updatedMembers)
} }
return@task Unit
}
} }
@JvmStatic @JvmStatic
fun explicitNameChange(context: Context, groupPublicKey: String, newName: String): Promise<Unit, Exception> { fun explicitNameChange(context: Context, groupPublicKey: String, newName: String) {
val deferred = deferred<Unit, Exception>()
ThreadUtils.queue {
val groupDB = DatabaseFactory.getGroupDatabase(context) val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey) val groupID = doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull() val group = groupDB.getGroup(groupID).orNull()
@ -232,7 +226,7 @@ object ClosedGroupsProtocolV2 {
val sentTime = System.currentTimeMillis() val sentTime = System.currentTimeMillis()
if (group == null) { if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.") Log.d("Loki", "Can't leave nonexistent closed group.")
return@queue deferred.reject(Error.NoThread) throw Error.NoThread
} }
// Send the update to the group // Send the update to the group
val kind = ClosedGroupUpdateMessageSendJobV2.Kind.NameChange(newName) val kind = ClosedGroupUpdateMessageSendJobV2.Kind.NameChange(newName)
@ -245,31 +239,6 @@ object ClosedGroupsProtocolV2 {
insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime) insertOutgoingInfoMessage(context, groupID, infoType, newName, members, admins, threadID, sentTime)
// Update the group // Update the group
groupDB.updateTitle(groupID, newName) groupDB.updateTitle(groupID, newName)
deferred.resolve(Unit)
}
return deferred.promise
}
@JvmStatic
fun leave(context: Context, groupPublicKey: String): Promise<Unit, Exception> {
val userPublicKey = TextSecurePreferences.getLocalNumber(context)!!
val groupDB = DatabaseFactory.getGroupDatabase(context)
val groupID = doubleEncodeGroupID(groupPublicKey)
val group = groupDB.getGroup(groupID).orNull()
if (group == null) {
Log.d("Loki", "Can't leave nonexistent closed group.")
return Promise.ofFail(Error.NoThread)
}
val name = group.title
val oldMembers = group.members.map { it.serialize() }.toSet()
val newMembers: Set<String>
val isCurrentUserAdmin = group.admins.map { it.toString() }.contains(userPublicKey)
if (!isCurrentUserAdmin) {
newMembers = oldMembers.minus(userPublicKey)
} else {
newMembers = setOf() // If the admin leaves the group is destroyed
}
return update(context, groupPublicKey, newMembers, name)
} }
fun update(context: Context, groupPublicKey: String, members: Collection<String>, name: String): Promise<Unit, Exception> { fun update(context: Context, groupPublicKey: String, members: Collection<String>, name: String): Promise<Unit, Exception> {