Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ abstract class BaseGroupMembersViewModel(
private val storage: StorageProtocol,
private val configFactory: ConfigFactoryProtocol,
private val avatarUtils: AvatarUtils,
private val recipientRepository: RecipientRepository,
private val recipientRepository: RecipientRepository
) : ViewModel() {
private val groupId = groupAddress.accountId

// Output: the source-of-truth group information. Other states are derived from this.
@OptIn(FlowPreview::class)
protected val groupInfo: StateFlow<Pair<GroupDisplayInfo, List<GroupMemberState>>?> =
(configFactory.configUpdateNotifications
.filter {
Expand All @@ -65,21 +66,26 @@ abstract class BaseGroupMembersViewModel(
val displayInfo = storage.getClosedGroupDisplayInfo(groupId.hexString)
?: return@withContext null

val rawMembers = configFactory.withGroupConfigs(groupId) { it.groupMembers.allWithStatus() }
val rawMembers =
configFactory.withGroupConfigs(groupId) { it.groupMembers.allWithStatus() }

val memberState = mutableListOf<GroupMemberState>()
for ((member, status) in rawMembers) {
memberState.add(createGroupMember(
member = member, status = status,
shouldShowProBadge = recipientRepository.getRecipient(member.accountId().toAddress()).shouldShowProBadge,
myAccountId = currentUserId,
amIAdmin = displayInfo.isUserAdmin
))
memberState.add(
createGroupMember(
member = member, status = status,
shouldShowProBadge = recipientRepository.getRecipient(
member.accountId().toAddress()
).shouldShowProBadge,
myAccountId = currentUserId,
amIAdmin = displayInfo.isUserAdmin
)
)
}

displayInfo to sortMembers(memberState, currentUserId)
}
}.stateIn(viewModelScope, SharingStarted.Eagerly, null)
}.stateIn(viewModelScope, SharingStarted.Eagerly, null)

// Current group name (for header / text, if needed)
val groupName: StateFlow<String> = groupInfo
Expand Down Expand Up @@ -174,7 +180,7 @@ abstract class BaseGroupMembersViewModel(
canResendInvite = amIAdmin && memberAccountId != myAccountId
&& !member.isRemoved(status)
&& (status == GroupMember.Status.INVITE_SENT || status == GroupMember.Status.INVITE_FAILED),
status = status.takeIf { !isMyself }, // Status is only meant for other members
status = status.takeIf { !isMyself }, // status is only for other members
highlightStatus = highlightStatus,
showAsAdmin = member.isAdminOrBeingPromoted(status),
showProBadge = shouldShowProBadge,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import com.squareup.phrase.Phrase
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
import network.loki.messenger.R
import network.loki.messenger.libsession_util.ED25519
import network.loki.messenger.libsession_util.Namespace
Expand Down Expand Up @@ -44,6 +46,7 @@ import org.session.libsession.snode.OwnedSwarmAuth
import org.session.libsession.snode.SnodeMessage
import org.session.libsession.snode.model.BatchResponse
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.Address.Companion.toAddress
import org.session.libsession.utilities.StringSubstitutionConstants.GROUP_NAME_KEY
import org.session.libsession.utilities.getGroup
import org.session.libsession.utilities.recipients.Recipient
Expand Down Expand Up @@ -75,6 +78,7 @@ import org.thoughtcrime.securesms.util.SessionMetaProtocol
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
import kotlin.time.Duration.Companion.seconds

private const val TAG = "GroupManagerV2Impl"

Expand Down Expand Up @@ -520,12 +524,17 @@ class GroupManagerV2Impl @Inject constructor(
// Update the group member's promotion status
members.asSequence()
.mapNotNull { configs.groupMembers.get(it.hexString) }
.onEach(GroupMember::setPromoted)
.onEach(GroupMember::setPromotionSent)
.forEach(configs.groupMembers::set)

configs.groupInfo.getName()
}

// Ensure this push is complete before promotion messages go out
withTimeoutOrNull(10.seconds) {
configFactory.waitUntilGroupConfigsPushed(group)
}

// Build a group update message to the group telling members someone has been promoted
val timestamp = clock.currentTimeMillis()
val signature = ED25519.sign(
Expand Down Expand Up @@ -589,10 +598,11 @@ class GroupManagerV2Impl @Inject constructor(
promotedByMemberIDs.asSequence()
.mapNotNull { (member, result) ->
configs.groupMembers.get(member.hexString)?.apply {
if (result.isSuccess) {
setPromotionSent()
} else {
setPromotionFailed()
if (result.isFailure) {
configs.groupMembers.get(member.hexString)?.let { member ->
member.setPromotionFailed()
configs.groupMembers.set(member)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import org.session.libsession.utilities.ConfigFactoryProtocol
import org.session.libsignal.utilities.AccountId
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.database.RecipientRepository
import org.thoughtcrime.securesms.pro.ProStatusManager
import org.thoughtcrime.securesms.util.AvatarUtils


Expand All @@ -29,7 +28,7 @@ class GroupMembersViewModel @AssistedInject constructor(
storage: StorageProtocol,
configFactory: ConfigFactoryProtocol,
avatarUtils: AvatarUtils,
recipientRepository: RecipientRepository,
recipientRepository: RecipientRepository
) : BaseGroupMembersViewModel(address, context, storage, configFactory, avatarUtils, recipientRepository) {

private val _navigationActions = Channel<Intent>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import network.loki.messenger.R
Expand Down Expand Up @@ -84,7 +82,7 @@ class ManageGroupAdminsViewModel @AssistedInject constructor(
init {
// Build footer from selected admins + collapsed state
viewModelScope.launch {
kotlinx.coroutines.flow.combine(
combine(
selectedAdmins,
footerCollapsed,
::buildFooterState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import network.loki.messenger.R
import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.groups.GroupManagerV2
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ConfigFactoryProtocol
import org.session.libsession.utilities.StringSubstitutionConstants.COUNT_KEY
Expand All @@ -34,7 +31,6 @@ class PromoteMembersViewModel @AssistedInject constructor(
@ApplicationContext private val context: Context,
storage: StorageProtocol,
private val configFactory: ConfigFactoryProtocol,
private val groupManager: GroupManagerV2,
private val recipientRepository: RecipientRepository,
avatarUtils: AvatarUtils,
) : BaseGroupMembersViewModel(
Expand All @@ -45,7 +41,6 @@ class PromoteMembersViewModel @AssistedInject constructor(
avatarUtils = avatarUtils,
recipientRepository = recipientRepository
) {
private val groupId = groupAddress.accountId

private val _mutableSelectedMembers = MutableStateFlow(emptySet<GroupMemberState>())
val selectedMembers: StateFlow<Set<GroupMemberState>> = _mutableSelectedMembers
Expand Down