From bd2cbeb8e85823742773503d13b8d42ac7855836 Mon Sep 17 00:00:00 2001 From: SessionHero01 <180888785+SessionHero01@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:52:32 +1100 Subject: [PATCH] Use consolidated member state and add pending removal support (#813) * Use consolidated member state and add pending removal support * Updated libsession-util --- .../groups/BaseGroupMembersViewModel.kt | 178 ++++++------------ .../securesms/groups/EditGroupViewModel.kt | 30 +-- .../securesms/groups/GroupManagerV2Impl.kt | 15 +- .../groups/compose/EditGroupScreen.kt | 23 +-- .../groups/compose/GroupMembersScreen.kt | 48 +---- libsession-util/libsession-util | 2 +- .../src/main/cpp/group_members.cpp | 26 ++- libsession-util/src/main/cpp/user_groups.h | 4 +- .../libsession_util/util/GroupMember.kt | 13 +- .../messaging/jobs/InviteContactsJob.kt | 6 +- 10 files changed, 131 insertions(+), 214 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/BaseGroupMembersViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/BaseGroupMembersViewModel.kt index b184a3e50f..624491539d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/BaseGroupMembersViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/BaseGroupMembersViewModel.kt @@ -24,6 +24,7 @@ import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.ConfigUpdateNotification import org.session.libsession.utilities.getMemberName import org.session.libsignal.utilities.AccountId +import java.util.EnumSet abstract class BaseGroupMembersViewModel ( @@ -32,48 +33,35 @@ abstract class BaseGroupMembersViewModel ( private val storage: StorageProtocol, private val configFactory: ConfigFactoryProtocol ) : ViewModel() { - - // Input: invite/promote member's intermediate states. This is needed because we don't have - // a state that we can map into in the config system. The config system only provides "sent", "failed", etc. - // The intermediate states are needed to show the user that the operation is in progress, and the - // states are limited to the view model (i.e. lost if the user navigates away). This is a trade-off - // between the complexity of the config system and the user experience. - protected val memberPendingState = MutableStateFlow>(emptyMap()) - // Output: the source-of-truth group information. Other states are derived from this. protected val groupInfo: StateFlow>?> = - combine( - configFactory.configUpdateNotifications - .filter { - it is ConfigUpdateNotification.GroupConfigsUpdated && it.groupId == groupId || - it is ConfigUpdateNotification.UserConfigsMerged - } - .onStart { emit(ConfigUpdateNotification.GroupConfigsUpdated(groupId)) }, - memberPendingState - ) { _, pending -> - withContext(Dispatchers.Default) { - val currentUserId = AccountId(checkNotNull(storage.getUserPublicKey()) { - "User public key is null" - }) - - val displayInfo = storage.getClosedGroupDisplayInfo(groupId.hexString) - ?: return@withContext null - - val members = storage.getMembers(groupId.hexString) - .filterTo(mutableListOf()) { !it.removed } - - val memberState = members.map { member -> - createGroupMember( - member = member, - myAccountId = currentUserId, - amIAdmin = displayInfo.isUserAdmin, - pendingState = pending[member.accountId] - ) - } - - displayInfo to sortMembers(memberState, currentUserId) + configFactory.configUpdateNotifications + .filter { + it is ConfigUpdateNotification.GroupConfigsUpdated && it.groupId == groupId || + it is ConfigUpdateNotification.UserConfigsMerged } - }.stateIn(viewModelScope, SharingStarted.Eagerly, null) + .onStart { emit(ConfigUpdateNotification.GroupConfigsUpdated(groupId)) } + .map { _ -> + withContext(Dispatchers.Default) { + val currentUserId = AccountId(checkNotNull(storage.getUserPublicKey()) { + "User public key is null" + }) + + val displayInfo = storage.getClosedGroupDisplayInfo(groupId.hexString) + ?: return@withContext null + + val memberState = storage.getMembers(groupId.hexString) + .map { member -> + createGroupMember( + member = member, + myAccountId = currentUserId, + amIAdmin = displayInfo.isUserAdmin, + ) + } + + displayInfo to sortMembers(memberState, currentUserId) + } + }.stateIn(viewModelScope, SharingStarted.Eagerly, null) // Output: the list of the members and their state in the group. val members: StateFlow> = groupInfo @@ -84,54 +72,14 @@ abstract class BaseGroupMembersViewModel ( member: GroupMember, myAccountId: AccountId, amIAdmin: Boolean, - pendingState: MemberPendingState? ): GroupMemberState { - var status = GroupMemberStatus.MEMBER - var highlightStatus = false - var name = member.getMemberName(configFactory) - var isMyself = false - - when { - member.accountIdString() == myAccountId.hexString -> { - name = context.getString(R.string.you) - isMyself = true - } - - member.removed -> { - status = GroupMemberStatus.REMOVED - } - - pendingState == MemberPendingState.Inviting -> { - status = GroupMemberStatus.INVITE_SENDING - } + val name = member.getMemberName(configFactory) + val isMyself = member.accountId == myAccountId - pendingState == MemberPendingState.Promoting -> { - status = GroupMemberStatus.PROMOTION_SENDING - } - - member.status == GroupMember.Status.PROMOTION_SENT -> { - status = GroupMemberStatus.PROMOTION_SENT - } - - member.status == GroupMember.Status.INVITE_SENT -> { - status = GroupMemberStatus.INVITE_SENT - } - - member.status == GroupMember.Status.INVITE_FAILED -> { - status = GroupMemberStatus.INVITE_FAILED - highlightStatus = true - } - - member.status == GroupMember.Status.REMOVED || - member.status == GroupMember.Status.REMOVED_INCLUDING_MESSAGES -> { - status = GroupMemberStatus.REMOVAL_PENDING - } - - member.status == GroupMember.Status.PROMOTION_FAILED -> { - status = GroupMemberStatus.PROMOTION_FAILED - highlightStatus = true - } - } + val highlightStatus = member.status in EnumSet.of( + GroupMember.Status.INVITE_FAILED, + GroupMember.Status.PROMOTION_FAILED + ) return GroupMemberState( accountId = member.accountId, @@ -145,7 +93,7 @@ abstract class BaseGroupMembersViewModel ( canResendInvite = amIAdmin && member.accountId != myAccountId && !member.removed && (member.status == GroupMember.Status.INVITE_SENT || member.status == GroupMember.Status.INVITE_FAILED), - status = status, + status = member.status?.takeIf { !isMyself }, // Status is only meant for other members highlightStatus = highlightStatus, showAsAdmin = member.isAdminOrBeingPromoted, clickable = !isMyself @@ -156,11 +104,11 @@ abstract class BaseGroupMembersViewModel ( members.sortedWith( compareBy{ when (it.status) { - GroupMemberStatus.INVITE_FAILED -> 0 // Failed invite comes first - GroupMemberStatus.INVITE_SENDING -> 1 // then "Sending invite" - GroupMemberStatus.INVITE_SENT -> 2 // then "Invite sent" - GroupMemberStatus.PROMOTION_SENDING -> 3 // then "Sending promotion" - GroupMemberStatus.PROMOTION_SENT -> 4 // then "Promotion sent" + GroupMember.Status.INVITE_FAILED -> 0 // Failed invite comes first + GroupMember.Status.INVITE_NOT_SENT -> 1 // then "Sending invite" + GroupMember.Status.INVITE_SENT -> 2 // then "Invite sent" + GroupMember.Status.PROMOTION_NOT_SENT -> 3 // then "Sending promotion" + GroupMember.Status.PROMOTION_SENT -> 4 // then "Promotion sent" else -> 5 } } @@ -174,17 +122,12 @@ abstract class BaseGroupMembersViewModel ( interface Factory { fun create(groupId: AccountId): EditGroupViewModel } - - protected enum class MemberPendingState { - Inviting, - Promoting, - } } data class GroupMemberState( val accountId: AccountId, val name: String, - val status: GroupMemberStatus, + val status: GroupMember.Status?, val highlightStatus: Boolean, val showAsAdmin: Boolean, val canResendInvite: Boolean, @@ -196,29 +139,22 @@ data class GroupMemberState( val canEdit: Boolean get() = canRemove || canPromote || canResendInvite || canResendPromotion } - -enum class GroupMemberStatus{ - INVITE_FAILED, - INVITE_SENDING, - INVITE_SENT, - PROMOTION_FAILED, - PROMOTION_SENDING, - PROMOTION_SENT, - REMOVAL_PENDING, - REMOVED, - MEMBER; - - // Function to get the label dynamically using the context - fun getLabel(context: Context): String { - return when (this) { - INVITE_FAILED -> context.getString(R.string.groupInviteFailed) - INVITE_SENDING -> context.resources.getQuantityString(R.plurals.groupInviteSending, 1) - INVITE_SENT -> context.getString(R.string.groupInviteSent) - PROMOTION_FAILED -> context.getString(R.string.adminPromotionFailed) - PROMOTION_SENDING -> context.resources.getQuantityString(R.plurals.adminSendingPromotion, 1) - PROMOTION_SENT -> context.getString(R.string.adminPromotionSent) - REMOVAL_PENDING -> context.getString(R.string.groupPendingRemoval) - REMOVED, MEMBER -> "" - } +// Function to get the label dynamically using the context +fun GroupMember.Status.getLabel(context: Context): String { + return when (this) { + GroupMember.Status.INVITE_FAILED -> context.getString(R.string.groupInviteFailed) + GroupMember.Status.INVITE_NOT_SENT -> context.resources.getQuantityString(R.plurals.groupInviteSending, 1) + GroupMember.Status.INVITE_SENT -> context.getString(R.string.groupInviteSent) + GroupMember.Status.PROMOTION_FAILED -> context.getString(R.string.adminPromotionFailed) + GroupMember.Status.PROMOTION_NOT_SENT -> context.resources.getQuantityString(R.plurals.adminSendingPromotion, 1) + GroupMember.Status.PROMOTION_SENT -> context.getString(R.string.adminPromotionSent) + GroupMember.Status.REMOVED, + GroupMember.Status.REMOVED_UNKNOWN, + GroupMember.Status.REMOVED_INCLUDING_MESSAGES -> context.getString(R.string.groupPendingRemoval) + + GroupMember.Status.INVITE_UNKNOWN, + GroupMember.Status.INVITE_ACCEPTED, + GroupMember.Status.PROMOTION_UNKNOWN, + GroupMember.Status.PROMOTION_ACCEPTED -> "" } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/EditGroupViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/EditGroupViewModel.kt index c0e2c606d7..505a45859f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/EditGroupViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/EditGroupViewModel.kt @@ -80,21 +80,11 @@ class EditGroupViewModel @AssistedInject constructor( fun onContactSelected(contacts: Set) { performGroupOperation { - try { - // Mark the contacts as pending - memberPendingState.update { states -> - states + contacts.associateWith { MemberPendingState.Inviting } - } - - groupManager.inviteMembers( - groupId, - contacts.toList(), - shareHistory = false - ) - } finally { - // Remove pending state (so the real state will be revealed) - memberPendingState.update { states -> states - contacts } - } + groupManager.inviteMembers( + groupId, + contacts.toList(), + shareHistory = false + ) } } @@ -104,15 +94,7 @@ class EditGroupViewModel @AssistedInject constructor( fun onPromoteContact(memberSessionId: AccountId) { performGroupOperation { - try { - memberPendingState.update { states -> - states + (memberSessionId to MemberPendingState.Promoting) - } - - groupManager.promoteMember(groupId, listOf(memberSessionId)) - } finally { - memberPendingState.update { states -> states - memberSessionId } - } + groupManager.promoteMember(groupId, listOf(memberSessionId)) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt index 3712c7ced4..760eb1745a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt @@ -227,6 +227,7 @@ class GroupManagerV2Impl @Inject constructor( member.setSupplement(shareHistory) } + toSet.setInvited() configs.groupMembers.set(toSet) } @@ -270,7 +271,7 @@ class GroupManagerV2Impl @Inject constructor( configFactory.withMutableGroupConfigs(group) { configs -> for (newMember in newMembers) { configs.groupMembers.get(newMember.hexString)?.apply { - setInvited(failed = true) + setInviteFailed() configs.groupMembers.set(this) } } @@ -478,7 +479,15 @@ class GroupManagerV2Impl @Inject constructor( members: List ): Unit = withContext(dispatcher + SupervisorJob()) { val adminKey = requireAdminAccess(group) - val groupName = configFactory.withGroupConfigs(group) { it.groupInfo.getName() } + val groupName = configFactory.withMutableGroupConfigs(group) { configs -> + // Update the group member's promotion status + members.asSequence() + .mapNotNull { configs.groupMembers.get(it.hexString) } + .onEach(GroupMember::setPromoted) + .forEach(configs.groupMembers::set) + + configs.groupInfo.getName() + } // Send out the promote message to the members concurrently val promoteMessage = GroupUpdated( @@ -800,7 +809,7 @@ class GroupManagerV2Impl @Inject constructor( val member = configs.groupMembers.get(sender.hexString) if (member != null) { configs.groupMembers.set(member.apply { - setAccepted() + setInviteAccepted() }) } else { Log.e(TAG, "User wasn't in the group membership to add!") diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt index 9924cf6ebd..1be3335175 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/EditGroupScreen.kt @@ -42,12 +42,13 @@ import com.squareup.phrase.Phrase import kotlinx.serialization.Serializable import network.loki.messenger.BuildConfig import network.loki.messenger.R +import network.loki.messenger.libsession_util.util.GroupMember import org.session.libsession.utilities.StringSubstitutionConstants.GROUP_NAME_KEY import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY import org.session.libsignal.utilities.AccountId import org.thoughtcrime.securesms.groups.EditGroupViewModel import org.thoughtcrime.securesms.groups.GroupMemberState -import org.thoughtcrime.securesms.groups.GroupMemberStatus +import org.thoughtcrime.securesms.groups.getLabel import org.thoughtcrime.securesms.ui.AlertDialog import org.thoughtcrime.securesms.ui.DialogButtonModel import org.thoughtcrime.securesms.ui.GetString @@ -425,7 +426,7 @@ fun EditMemberItem( MemberItem( accountId = member.accountId, title = member.name, - subtitle = member.status.getLabel(LocalContext.current), + subtitle = member.status?.getLabel(LocalContext.current), subtitleColor = if (member.highlightStatus) { LocalColors.current.danger } else { @@ -451,7 +452,7 @@ private fun EditGroupPreview3() { val oneMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"), name = "Test User", - status = GroupMemberStatus.INVITE_SENT, + status = GroupMember.Status.INVITE_SENT, highlightStatus = false, canPromote = true, canRemove = true, @@ -463,7 +464,7 @@ private fun EditGroupPreview3() { val twoMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235"), name = "Test User 2", - status = GroupMemberStatus.PROMOTION_FAILED, + status = GroupMember.Status.PROMOTION_FAILED, highlightStatus = true, canPromote = true, canRemove = true, @@ -475,7 +476,7 @@ private fun EditGroupPreview3() { val threeMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1236"), name = "Test User 3", - status = GroupMemberStatus.MEMBER, + status = null, highlightStatus = false, canPromote = true, canRemove = true, @@ -525,7 +526,7 @@ private fun EditGroupPreview() { val oneMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"), name = "Test User", - status = GroupMemberStatus.INVITE_SENT, + status = GroupMember.Status.INVITE_SENT, highlightStatus = false, canPromote = true, canRemove = true, @@ -537,7 +538,7 @@ private fun EditGroupPreview() { val twoMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235"), name = "Test User 2", - status = GroupMemberStatus.PROMOTION_FAILED, + status = GroupMember.Status.PROMOTION_FAILED, highlightStatus = true, canPromote = true, canRemove = true, @@ -549,7 +550,7 @@ private fun EditGroupPreview() { val threeMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1236"), name = "Test User 3", - status = GroupMemberStatus.MEMBER, + status = null, highlightStatus = false, canPromote = true, canRemove = true, @@ -599,7 +600,7 @@ private fun EditGroupEditNamePreview() { val oneMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"), name = "Test User", - status = GroupMemberStatus.INVITE_SENT, + status = GroupMember.Status.INVITE_SENT, highlightStatus = false, canPromote = true, canRemove = true, @@ -611,7 +612,7 @@ private fun EditGroupEditNamePreview() { val twoMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235"), name = "Test User 2", - status = GroupMemberStatus.PROMOTION_FAILED, + status = GroupMember.Status.PROMOTION_FAILED, highlightStatus = true, canPromote = true, canRemove = true, @@ -623,7 +624,7 @@ private fun EditGroupEditNamePreview() { val threeMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1236"), name = "Test User 3", - status = GroupMemberStatus.MEMBER, + status = null, highlightStatus = false, canPromote = true, canRemove = true, diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/GroupMembersScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/GroupMembersScreen.kt index 1ab3e7cf33..08a52ae34b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/compose/GroupMembersScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/compose/GroupMembersScreen.kt @@ -1,62 +1,26 @@ package org.thoughtcrime.securesms.groups.compose -import android.widget.Toast -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment.Companion.CenterHorizontally -import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import com.squareup.phrase.Phrase -import network.loki.messenger.BuildConfig import network.loki.messenger.R -import org.session.libsession.utilities.StringSubstitutionConstants.GROUP_NAME_KEY -import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY +import network.loki.messenger.libsession_util.util.GroupMember import org.session.libsignal.utilities.AccountId import org.thoughtcrime.securesms.groups.GroupMemberState -import org.thoughtcrime.securesms.groups.GroupMemberStatus import org.thoughtcrime.securesms.groups.GroupMembersViewModel -import org.thoughtcrime.securesms.ui.AlertDialog -import org.thoughtcrime.securesms.ui.DialogButtonModel -import org.thoughtcrime.securesms.ui.GetString -import org.thoughtcrime.securesms.ui.components.ActionSheet -import org.thoughtcrime.securesms.ui.components.ActionSheetItemData +import org.thoughtcrime.securesms.groups.getLabel import org.thoughtcrime.securesms.ui.components.BackAppBar -import org.thoughtcrime.securesms.ui.components.PrimaryOutlineButton -import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField -import org.thoughtcrime.securesms.ui.qaTag import org.thoughtcrime.securesms.ui.theme.LocalColors -import org.thoughtcrime.securesms.ui.theme.LocalDimensions -import org.thoughtcrime.securesms.ui.theme.LocalType import org.thoughtcrime.securesms.ui.theme.PreviewTheme @Composable @@ -98,7 +62,7 @@ fun GroupMembers( MemberItem( accountId = member.accountId, title = member.name, - subtitle = member.status.getLabel(LocalContext.current), + subtitle = member.status?.getLabel(LocalContext.current), subtitleColor = if (member.highlightStatus) { LocalColors.current.danger } else { @@ -120,7 +84,7 @@ private fun EditGroupPreview() { val oneMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"), name = "Test User", - status = GroupMemberStatus.INVITE_SENT, + status = GroupMember.Status.INVITE_SENT, highlightStatus = false, canPromote = true, canRemove = true, @@ -132,7 +96,7 @@ private fun EditGroupPreview() { val twoMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235"), name = "Test User 2", - status = GroupMemberStatus.PROMOTION_FAILED, + status = GroupMember.Status.PROMOTION_FAILED, highlightStatus = true, canPromote = true, canRemove = true, @@ -144,7 +108,7 @@ private fun EditGroupPreview() { val threeMember = GroupMemberState( accountId = AccountId("05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1236"), name = "Test User 3", - status = GroupMemberStatus.MEMBER, + status = null, highlightStatus = false, canPromote = true, canRemove = true, diff --git a/libsession-util/libsession-util b/libsession-util/libsession-util index 1ed9170c73..43b1c6c341 160000 --- a/libsession-util/libsession-util +++ b/libsession-util/libsession-util @@ -1 +1 @@ -Subproject commit 1ed9170c7329512f78b25cb2bcb7ecaa9a416d39 +Subproject commit 43b1c6c341ee8739a8678c631d0713136dbfd05f diff --git a/libsession-util/src/main/cpp/group_members.cpp b/libsession-util/src/main/cpp/group_members.cpp index 41d433bfc1..f12bcab7eb 100644 --- a/libsession-util/src/main/cpp/group_members.cpp +++ b/libsession-util/src/main/cpp/group_members.cpp @@ -89,16 +89,29 @@ Java_network_loki_messenger_libsession_1util_GroupMembersConfig_set(JNIEnv *env, extern "C" JNIEXPORT void JNICALL Java_network_loki_messenger_libsession_1util_util_GroupMember_setInvited(JNIEnv *env, - jobject thiz, - jboolean failed) { - ptrToMember(env, thiz)->set_invited(failed); + jobject thiz) { + ptrToMember(env, thiz)->invite_status = session::config::groups::STATUS_NOT_SENT; +} + +extern "C" +JNIEXPORT void JNICALL +Java_network_loki_messenger_libsession_1util_util_GroupMember_setInviteSent(JNIEnv *env, + jobject thiz) { + ptrToMember(env, thiz)->set_invite_sent(); +} + +extern "C" +JNIEXPORT void JNICALL +Java_network_loki_messenger_libsession_1util_util_GroupMember_setInviteFailed(JNIEnv *env, + jobject thiz) { + ptrToMember(env, thiz)->set_invite_failed(); } extern "C" JNIEXPORT void JNICALL -Java_network_loki_messenger_libsession_1util_util_GroupMember_setAccepted(JNIEnv *env, +Java_network_loki_messenger_libsession_1util_util_GroupMember_setInviteAccepted(JNIEnv *env, jobject thiz) { - ptrToMember(env, thiz)->set_accepted(); + ptrToMember(env, thiz)->set_invite_accepted(); } extern "C" @@ -210,4 +223,5 @@ Java_network_loki_messenger_libsession_1util_util_GroupMember_setSupplement(JNIE jobject thiz, jboolean supplement) { ptrToMember(env, thiz)->supplement = supplement; -} \ No newline at end of file +} + diff --git a/libsession-util/src/main/cpp/user_groups.h b/libsession-util/src/main/cpp/user_groups.h index fc9bd42a4f..6255a8d04b 100644 --- a/libsession-util/src/main/cpp/user_groups.h +++ b/libsession-util/src/main/cpp/user_groups.h @@ -135,7 +135,7 @@ inline jobject serialize_closed_group_info(JNIEnv* env, session::config::group_i jclass group_info_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo"); jmethodID constructor = env->GetMethodID(group_info_class, "","(Lorg/session/libsignal/utilities/AccountId;[B[BJZLjava/lang/String;Z)V"); jobject return_object = env->NewObject(group_info_class,constructor, - session_id, admin_bytes, auth_bytes, (jlong)info.priority, info.invited, name, info.isDestroyed()); + session_id, admin_bytes, auth_bytes, (jlong)info.priority, info.invited, name, info.is_destroyed()); return return_object; } @@ -167,7 +167,7 @@ inline session::config::group_info deserialize_closed_group_info(JNIEnv* env, jo group_info.invited = env->GetBooleanField(info_serialized, invited_field); group_info.name = name; if (env->GetBooleanField(info_serialized, destroy_field)) { - group_info.markDestroyed(); + group_info.mark_destroyed(); } return group_info; diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupMember.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupMember.kt index d6327e37bc..6fc086d0e8 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupMember.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupMember.kt @@ -9,19 +9,26 @@ import java.util.EnumSet * Note: unlike a read-only data class, this class is mutable and it is not thread-safe * in general. You have to synchronize access to it if you are going to use it in multiple threads. */ -class GroupMember private constructor(@Suppress("CanBeParameter") private val nativePtr: Long) { +class GroupMember private constructor( + // Constructed and used by native code. + @Suppress("CanBeParameter") private val nativePtr: Long +) { init { if (nativePtr == 0L) { throw NullPointerException("Native pointer is null") } } - external fun setInvited(failed: Boolean = false) - external fun setAccepted() + external fun setInvited() + external fun setInviteSent() + external fun setInviteFailed() + external fun setInviteAccepted() + external fun setPromoted() external fun setPromotionSent() external fun setPromotionFailed() external fun setPromotionAccepted() + external fun setRemoved(alsoRemoveMessages: Boolean) private external fun statusInt(): Int diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/InviteContactsJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/InviteContactsJob.kt index a1041bb23d..5277bd0835 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/InviteContactsJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/InviteContactsJob.kt @@ -91,7 +91,11 @@ class InviteContactsJob(val groupSessionId: String, val memberSessionIds: Array< configs.withMutableGroupConfigs(sessionId) { configs -> results.forEach { (memberSessionId, result) -> configs.groupMembers.get(memberSessionId)?.let { member -> - member.setInvited(failed = result.isFailure) + if (result.isFailure) { + member.setInviteFailed() + } else { + member.setInviteSent() + } configs.groupMembers.set(member) } }