From 2732b9594061d6c71f8b4dc68c7c614d6bbc97e6 Mon Sep 17 00:00:00 2001 From: nielsandriesse Date: Wed, 2 Sep 2020 11:47:54 +1000 Subject: [PATCH] Show a loader while the group is being created --- res/layout/activity_create_closed_group.xml | 21 ++++- .../activities/CreateClosedGroupActivity.kt | 15 +++- .../loki/protocol/ClosedGroupsProtocol.kt | 79 ++++++++++--------- 3 files changed, 75 insertions(+), 40 deletions(-) diff --git a/res/layout/activity_create_closed_group.xml b/res/layout/activity_create_closed_group.xml index 52a3300865..59d9fe00e0 100644 --- a/res/layout/activity_create_closed_group.xml +++ b/res/layout/activity_create_closed_group.xml @@ -3,7 +3,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@drawable/default_session_background" > + xmlns:app="http://schemas.android.com/apk/res-auto" + android:background="@drawable/default_session_background"> + + + + + + \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt index 16b2304238..30d59281d6 100644 --- a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt @@ -15,6 +15,7 @@ import android.widget.Toast import kotlinx.android.synthetic.main.activity_create_closed_group.* import kotlinx.android.synthetic.main.activity_linked_devices.recyclerView import network.loki.messenger.R +import nl.komponents.kovenant.ui.successUi import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.conversation.ConversationActivity import org.thoughtcrime.securesms.database.Address @@ -22,6 +23,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol +import org.thoughtcrime.securesms.loki.utilities.fadeIn +import org.thoughtcrime.securesms.loki.utilities.fadeOut import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.TextSecurePreferences @@ -122,9 +125,15 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), LoaderM return Toast.makeText(this, R.string.activity_create_closed_group_too_many_group_members_error, Toast.LENGTH_LONG).show() } val userPublicKey = TextSecurePreferences.getLocalNumber(this) - val groupID = ClosedGroupsProtocol.createClosedGroup(this, name.toString(), selectedMembers + setOf( userPublicKey )) - val threadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(Recipient.from(this, Address.fromSerialized(groupID), false)) - openConversationActivity(this, threadID, Recipient.from(this, Address.fromSerialized(groupID), false)) + loader.fadeIn() + ClosedGroupsProtocol.createClosedGroup(this, name.toString(), selectedMembers + setOf( userPublicKey )).successUi { groupID -> + loader.fadeOut() + val threadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(Recipient.from(this, Address.fromSerialized(groupID), false)) + if (!isFinishing) { + openConversationActivity(this, threadID, Recipient.from(this, Address.fromSerialized(groupID), false)) + finish() + } + } } private fun createLegacyClosedGroup() { diff --git a/src/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt b/src/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt index 050b62774a..363a1a7fdf 100644 --- a/src/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt +++ b/src/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocol.kt @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context import android.util.Log import com.google.protobuf.ByteString +import nl.komponents.kovenant.Promise +import nl.komponents.kovenant.deferred import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.database.Address import org.thoughtcrime.securesms.database.DatabaseFactory @@ -34,43 +36,48 @@ object ClosedGroupsProtocol { val isSharedSenderKeysEnabled = false val groupSizeLimit = 10 - public fun createClosedGroup(context: Context, name: String, members: Collection): String { - // Prepare - val userPublicKey = TextSecurePreferences.getLocalNumber(context) - // Generate a key pair for the group - val groupKeyPair = Curve.generateKeyPair() - val groupPublicKey = groupKeyPair.hexEncodedPublicKey // Includes the "05" prefix - val membersAsData = members.map { Hex.fromStringCondensed(it) } - // Create ratchets for all members - val senderKeys: List = members.map { publicKey -> - val ratchet = SharedSenderKeysImplementation.shared.generateRatchet(groupPublicKey, publicKey) - ClosedGroupSenderKey(Hex.fromStringCondensed(ratchet.chainKey), ratchet.keyIndex, Hex.fromStringCondensed(publicKey)) - } - // Create the group - val groupID = doubleEncodeGroupID(groupPublicKey) - val admins = setOf( userPublicKey ) - DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList
(members.map { Address.fromSerialized(it) }), - null, null, LinkedList
(admins.map { Address.fromSerialized(it) })) - DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true) - // Establish sessions if needed - establishSessionsWithMembersIfNeeded(context, members) - // Send a closed group update message to all members using established channels - val adminsAsData = admins.map { Hex.fromStringCondensed(it) } - val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, groupKeyPair.privateKey.serialize(), - senderKeys, membersAsData, adminsAsData) - for (member in members) { - if (member == userPublicKey) { continue } - val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind) - ApplicationContext.getInstance(context).jobManager.add(job) - } - // TODO: Wait for the messages to finish sending - // Add the group to the user's set of public keys to poll for - DatabaseFactory.getSSKDatabase(context).setClosedGroupPrivateKey(groupPublicKey, groupKeyPair.hexEncodedPrivateKey) - // Notify the user - val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) - insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID) + public fun createClosedGroup(context: Context, name: String, members: Collection): Promise { + val deferred = deferred() + Thread { + // Prepare + val userPublicKey = TextSecurePreferences.getLocalNumber(context) + // Generate a key pair for the group + val groupKeyPair = Curve.generateKeyPair() + val groupPublicKey = groupKeyPair.hexEncodedPublicKey // Includes the "05" prefix + val membersAsData = members.map { Hex.fromStringCondensed(it) } + // Create ratchets for all members + val senderKeys: List = members.map { publicKey -> + val ratchet = SharedSenderKeysImplementation.shared.generateRatchet(groupPublicKey, publicKey) + ClosedGroupSenderKey(Hex.fromStringCondensed(ratchet.chainKey), ratchet.keyIndex, Hex.fromStringCondensed(publicKey)) + } + // Create the group + val groupID = doubleEncodeGroupID(groupPublicKey) + val admins = setOf( userPublicKey ) + DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList
(members.map { Address.fromSerialized(it) }), + null, null, LinkedList
(admins.map { Address.fromSerialized(it) })) + DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true) + // Establish sessions if needed + establishSessionsWithMembersIfNeeded(context, members) + // Send a closed group update message to all members using established channels + val adminsAsData = admins.map { Hex.fromStringCondensed(it) } + val closedGroupUpdateKind = ClosedGroupUpdateMessageSendJob.Kind.New(Hex.fromStringCondensed(groupPublicKey), name, groupKeyPair.privateKey.serialize(), + senderKeys, membersAsData, adminsAsData) + for (member in members) { + if (member == userPublicKey) { continue } + val job = ClosedGroupUpdateMessageSendJob(member, closedGroupUpdateKind) + job.setContext(context) + job.onRun() // Run the job immediately + } + // Add the group to the user's set of public keys to poll for + DatabaseFactory.getSSKDatabase(context).setClosedGroupPrivateKey(groupPublicKey, groupKeyPair.hexEncodedPrivateKey) + // Notify the user + val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.from(context, Address.fromSerialized(groupID), false)) + insertOutgoingInfoMessage(context, groupID, GroupContext.Type.UPDATE, name, members, admins, threadID) + // Fulfill the promise + deferred.resolve(groupID) + }.start() // Return - return groupID + return deferred.promise } @JvmStatic