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 @@ -28,9 +28,12 @@ import com.wire.android.BuildConfig
import com.wire.android.ui.home.conversations.details.participants.usecase.ObserveParticipantsForConversationUseCase
import com.wire.android.ui.navArgs
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.common.functional.onSuccess
import com.wire.kalium.logic.data.conversation.Conversation
import com.wire.kalium.logic.data.conversation.ConversationDetails
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.user.SupportedProtocol
import com.wire.kalium.logic.data.user.type.UserType
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
import com.wire.kalium.logic.feature.conversation.SyncConversationCodeUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationAccessRoleUseCase
Expand All @@ -41,8 +44,8 @@ import com.wire.kalium.logic.feature.conversation.guestroomlink.ObserveGuestRoom
import com.wire.kalium.logic.feature.conversation.guestroomlink.RevokeGuestRoomLinkResult
import com.wire.kalium.logic.feature.conversation.guestroomlink.RevokeGuestRoomLinkUseCase
import com.wire.kalium.logic.feature.user.GetDefaultProtocolUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.logic.feature.user.guestroomlink.ObserveGuestRoomLinkFeatureFlagUseCase
import com.wire.kalium.common.functional.onSuccess
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
Expand Down Expand Up @@ -71,6 +74,7 @@ class EditGuestAccessViewModel @Inject constructor(
private val canCreatePasswordProtectedLinks: CanCreatePasswordProtectedLinksUseCase,
private val syncConversationCode: SyncConversationCodeUseCase,
private val getDefaultProtocol: GetDefaultProtocolUseCase,
private val selfUser: ObserveSelfUserUseCase,
savedStateHandle: SavedStateHandle
) : ViewModel() {

Expand Down Expand Up @@ -142,21 +146,27 @@ class EditGuestAccessViewModel @Inject constructor(

val isMLSTeam = getDefaultProtocol() == SupportedProtocol.MLS

// TODO(refactor): Move all this logic to a UseCase
combine(
conversationDetailsFlow,
isSelfAdminFlow
) { conversationDetails, isSelfAnAdmin ->
isSelfAnAdmin to conversationDetails
}.collect { (isSelfAnAdmin, conversationDetails) ->

isSelfAdminFlow,
selfUser()
) { conversationDetails, isSelfAnAdmin, selfUser ->
Triple(isSelfAnAdmin, conversationDetails, selfUser)
}.collect { (isSelfAnAdmin, conversationDetails, selfUser) ->
val isTeamAdmin = selfUser.userType in setOf(UserType.ADMIN, UserType.OWNER)
val isSelfInConversationTeam = selfUser.teamId == conversationDetails.conversation.teamId
val isSelfChannelTeamAdmin =
(conversationDetails is ConversationDetails.Group.Channel && isTeamAdmin && isSelfInConversationTeam)
val canSelfPerformAdminActions = isSelfAnAdmin || isSelfChannelTeamAdmin
val isGuestAllowed =
conversationDetails.conversation.isGuestAllowed() || conversationDetails.conversation.isNonTeamMemberAllowed()
val isMLSConversation = conversationDetails.conversation.protocol is Conversation.ProtocolInfo.MLS

editGuestAccessState = editGuestAccessState.copy(
isGuestAccessAllowed = isGuestAllowed,
isServicesAccessAllowed = conversationDetails.conversation.isServicesAllowed() && !isMLSTeam && !isMLSConversation,
isUpdatingGuestAccessAllowed = isSelfAnAdmin
isUpdatingGuestAccessAllowed = canSelfPerformAdminActions
)

if (isGuestAllowed) updateConversationCodeOnce()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@
import com.wire.android.ui.home.messagecomposer.SelfDeletionDuration
import com.wire.android.ui.navArgs
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.logic.data.conversation.ConversationDetails
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.user.type.UserType
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
import com.wire.kalium.logic.feature.conversation.messagetimer.UpdateMessageTimerUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
Expand All @@ -48,6 +52,8 @@
private val observeConversationMembers: ObserveParticipantsForConversationUseCase,
private val observeSelfDeletionTimerSettingsForConversation: ObserveSelfDeletionTimerSettingsForConversationUseCase,
private val updateMessageTimer: UpdateMessageTimerUseCase,
private val selfUser: ObserveSelfUserUseCase,
private val conversationDetails: ObserveConversationDetailsUseCase,
savedStateHandle: SavedStateHandle
) : ViewModel() {

Expand All @@ -64,9 +70,25 @@

private fun observeSelfDeletionTimerSettingsForConversation() {
viewModelScope.launch {
// TODO(refactor): Move all this logic to a UseCase
val canPerformAdminActionsFlow = combine(
observeConversationMembers(conversationId).map { it.isSelfAnAdmin },
selfUser(),
conversationDetails(conversationId),
::Triple
).map { (isSelfAnAdmin, selfUser, conversationDetailsResult) ->
if (conversationDetailsResult !is ObserveConversationDetailsUseCase.Result.Success) {
return@map false

Check warning on line 81 in app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesViewModel.kt#L81

Added line #L81 was not covered by tests
}
val conversationDetails = conversationDetailsResult.conversationDetails
val isChannel = conversationDetails is ConversationDetails.Group.Channel
val isTeamAdmin = selfUser.userType in setOf(UserType.ADMIN, UserType.OWNER)
val isSelfUserInConversationTeam = selfUser.teamId == conversationDetails.conversation.teamId
isSelfAnAdmin || (isChannel && isTeamAdmin && isSelfUserInConversationTeam)
}
combine(
observeSelfDeletionTimerSettingsForConversation(conversationId, considerSelfUserSettings = false),
observeConversationMembers(conversationId).map { it.isSelfAnAdmin },
canPerformAdminActionsFlow,
::Pair
)
.distinctUntilChanged()
Expand Down Expand Up @@ -101,14 +123,18 @@
val currentSelectedDuration = state.locallySelected
state = when (updateMessageTimer(conversationId, currentSelectedDuration?.value?.inWholeMilliseconds)) {
is UpdateMessageTimerUseCase.Result.Failure -> {
appLogger.e("Failed to update self deleting enforced duration for conversation=${conversationId.toLogString()} " +
"with new duration=${currentSelectedDuration?.name}")
appLogger.e(
"Failed to update self deleting enforced duration for conversation=${conversationId.toLogString()} " +

Check warning on line 127 in app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editselfdeletingmessages/EditSelfDeletingMessagesViewModel.kt#L126-L127

Added lines #L126 - L127 were not covered by tests
"with new duration=${currentSelectedDuration?.name}"
)
state.copy(isLoading = true)
}

UpdateMessageTimerUseCase.Result.Success -> {
appLogger.d("Success updating self deleting enforced duration for conversation=${conversationId.toLogString()} " +
"with new duration=${currentSelectedDuration?.name}")
appLogger.d(
"Success updating self deleting enforced duration for conversation=${conversationId.toLogString()} " +
"with new duration=${currentSelectedDuration?.name}"
)
state.copy(
isLoading = false,
remotelySelected = currentSelectedDuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.wire.android.config.NavigationTestExtension
import com.wire.android.config.TestDispatcherProvider
import com.wire.android.framework.TestConversation
import com.wire.android.framework.TestConversationDetails
import com.wire.android.framework.TestUser
import com.wire.android.ui.home.conversations.details.participants.model.ConversationParticipantsData
import com.wire.android.ui.home.conversations.details.participants.usecase.ObserveParticipantsForConversationUseCase
import com.wire.android.ui.navArgs
Expand All @@ -44,6 +45,7 @@ import com.wire.kalium.logic.feature.conversation.guestroomlink.ObserveGuestRoom
import com.wire.kalium.logic.feature.conversation.guestroomlink.RevokeGuestRoomLinkResult
import com.wire.kalium.logic.feature.conversation.guestroomlink.RevokeGuestRoomLinkUseCase
import com.wire.kalium.logic.feature.user.GetDefaultProtocolUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.logic.feature.user.guestroomlink.ObserveGuestRoomLinkFeatureFlagUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
Expand Down Expand Up @@ -287,6 +289,9 @@ class EditGuestAccessViewModelTest {
@MockK
lateinit var getDefaultProtocolUseCase: GetDefaultProtocolUseCase

@MockK
lateinit var observeSelfUserUseCase: ObserveSelfUserUseCase

val editGuestAccessViewModel: EditGuestAccessViewModel by lazy {
EditGuestAccessViewModel(
savedStateHandle = savedStateHandle,
Expand All @@ -300,7 +305,8 @@ class EditGuestAccessViewModelTest {
canCreatePasswordProtectedLinks = canCreatePasswordProtectedLinks,
dispatcher = dispatcherProvider,
syncConversationCode = syncConversationCodeUseCase,
getDefaultProtocol = getDefaultProtocolUseCase
getDefaultProtocol = getDefaultProtocolUseCase,
selfUser = observeSelfUserUseCase
)
}

Expand All @@ -319,6 +325,7 @@ class EditGuestAccessViewModelTest {
coEvery { observeGuestRoomLink(any()) } returns flowOf()
coEvery { observeGuestRoomLinkFeatureFlag() } returns flowOf()
coEvery { canCreatePasswordProtectedLinks() } returns true
coEvery { observeSelfUserUseCase() } returns flowOf(TestUser.SELF_USER)
every { getDefaultProtocolUseCase() } returns SupportedProtocol.PROTEUS
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ package com.wire.android.ui.home.conversations.details.editselfdeletingmessages

import androidx.lifecycle.SavedStateHandle
import com.wire.android.config.CoroutineTestExtension
import com.wire.android.config.NavigationTestExtension
import com.wire.android.config.TestDispatcherProvider
import com.wire.android.framework.TestConversation
import com.wire.android.config.NavigationTestExtension
import com.wire.android.framework.TestConversationDetails
import com.wire.android.framework.TestUser
import com.wire.android.ui.home.conversations.details.participants.model.ConversationParticipantsData
import com.wire.android.ui.home.conversations.details.participants.usecase.ObserveParticipantsForConversationUseCase
import com.wire.android.ui.home.messagecomposer.SelfDeletionDuration
import com.wire.android.ui.navArgs
import com.wire.kalium.logic.data.message.SelfDeletionTimer
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
import com.wire.kalium.logic.feature.conversation.messagetimer.UpdateMessageTimerUseCase
import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase
import com.wire.kalium.logic.data.message.SelfDeletionTimer
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.every
Expand All @@ -49,44 +53,38 @@ import kotlin.time.Duration.Companion.minutes
class EditSelfDeletingMessagesViewModelTest {

@Test
fun `given self deleting messages option enabled, when disabling it, then it updates proper state`() =
runTest {
// Given
val (arrangement, viewModel) = Arrangement()
.withSelfDeletingMessagesGroupSettings(SelfDeletionTimer.Enabled(5.minutes))
.withUpdateMessageTimerSuccess()
.arrange()

// When
viewModel.updateSelfDeletingMessageOption(false)
viewModel.applyNewDuration(arrangement.onCompleted)

// Then
assertEquals(false, viewModel.state.isEnabled)
assertEquals(null, viewModel.state.locallySelected)
verify { arrangement.onCompleted() }
}
fun `given self deleting messages option enabled, when disabling it, then it updates proper state`() = runTest {
// Given
val (arrangement, viewModel) = Arrangement().withSelfDeletingMessagesGroupSettings(SelfDeletionTimer.Enabled(5.minutes))
.withUpdateMessageTimerSuccess().arrange()

// When
viewModel.updateSelfDeletingMessageOption(false)
viewModel.applyNewDuration(arrangement.onCompleted)

// Then
assertEquals(false, viewModel.state.isEnabled)
assertEquals(null, viewModel.state.locallySelected)
verify { arrangement.onCompleted() }
}

@Test
fun `given self deleting messages option disabled, when enabling it, then it updates proper state`() =
runTest {
// Given
val newTimer = SelfDeletionDuration.FiveMinutes
val (arrangement, viewModel) = Arrangement()
.withSelfDeletingMessagesGroupSettings(SelfDeletionTimer.Enabled(Duration.ZERO))
.withUpdateMessageTimerSuccess()
.arrange()

// When
viewModel.updateSelfDeletingMessageOption(true)
viewModel.onSelectDuration(newTimer)
viewModel.applyNewDuration(arrangement.onCompleted)

// Then
assertEquals(newTimer, viewModel.state.remotelySelected)
assertEquals(newTimer, viewModel.state.locallySelected)
verify { arrangement.onCompleted() }
}
fun `given self deleting messages option disabled, when enabling it, then it updates proper state`() = runTest {
// Given
val newTimer = SelfDeletionDuration.FiveMinutes
val (arrangement, viewModel) = Arrangement().withSelfDeletingMessagesGroupSettings(SelfDeletionTimer.Enabled(Duration.ZERO))
.withUpdateMessageTimerSuccess().arrange()

// When
viewModel.updateSelfDeletingMessageOption(true)
viewModel.onSelectDuration(newTimer)
viewModel.applyNewDuration(arrangement.onCompleted)

// Then
assertEquals(newTimer, viewModel.state.remotelySelected)
assertEquals(newTimer, viewModel.state.locallySelected)
verify { arrangement.onCompleted() }
}

private class Arrangement {

Expand All @@ -102,6 +100,12 @@ class EditSelfDeletingMessagesViewModelTest {
@MockK
private lateinit var updateMessageTimer: UpdateMessageTimerUseCase

@MockK
private lateinit var selfUser: ObserveSelfUserUseCase

@MockK
private lateinit var conversationDetails: ObserveConversationDetailsUseCase

@MockK(relaxed = true)
lateinit var onCompleted: () -> Unit

Expand All @@ -111,7 +115,9 @@ class EditSelfDeletingMessagesViewModelTest {
dispatcher = TestDispatcherProvider(),
observeConversationMembers = observerConversationMembers,
observeSelfDeletionTimerSettingsForConversation = observeSelfDeletionTimerSettingsForConversation,
updateMessageTimer = updateMessageTimer
updateMessageTimer = updateMessageTimer,
selfUser = selfUser,
conversationDetails = conversationDetails,
)
}

Expand All @@ -121,6 +127,11 @@ class EditSelfDeletingMessagesViewModelTest {
conversationId = TestConversation.ID
)

coEvery { selfUser() } returns flowOf(TestUser.SELF_USER)
coEvery { conversationDetails(any()) } returns flowOf(
ObserveConversationDetailsUseCase.Result.Success(TestConversationDetails.GROUP)
)

coEvery { observerConversationMembers(any()) } returns flowOf(ConversationParticipantsData(isSelfAnAdmin = true))
}

Expand Down
Loading