From 5aaa29bbfd405ccf74984fa88fb45979f1b71292 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Wed, 20 Sep 2023 11:35:23 +0200 Subject: [PATCH 01/10] feat: added archive use case stubs --- .../main/kotlin/com/wire/android/di/CoreLogicModule.kt | 9 +++++++++ kalium | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt index cadddf234d3..5dae03d9ae6 100644 --- a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt @@ -72,6 +72,7 @@ import com.wire.kalium.logic.feature.conversation.ObserveUserListByIdUseCase import com.wire.kalium.logic.feature.conversation.RefreshConversationsWithoutMetadataUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationAccessRoleUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationReadDateUseCase @@ -768,6 +769,14 @@ class UseCaseModule { ): UpdateConversationMutedStatusUseCase = coreLogic.getSessionScope(currentAccount).conversations.updateConversationMutedStatus + @ViewModelScoped + @Provides + fun provideUpdateConversationArchivedStatusUseCase( + @KaliumCoreLogic coreLogic: CoreLogic, + @CurrentAccount currentAccount: UserId + ): UpdateConversationArchivedStatusUseCase = + coreLogic.getSessionScope(currentAccount).conversations.updateConversationArchivedStatus + @ViewModelScoped @Provides fun provideUpdateConversationReceiptModeUseCase( diff --git a/kalium b/kalium index a0ff361daec..bf09e785b1d 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit a0ff361daecd9528f263868e5a7bef1d2c87a8d5 +Subproject commit bf09e785b1d68542d56d1eb2dfedc2f8c81032ea From ef0a8faf5d4debbec3c3510b9ddce971b1af0fd0 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Fri, 22 Sep 2023 13:13:15 +0200 Subject: [PATCH 02/10] feat: added archiving logic to user and group details screen + snackbar messages --- .../conversation/ConversationSheetContent.kt | 4 +-- .../conversation/HomeSheetContent.kt | 36 +++++++++++-------- .../com/wire/android/ui/home/HomeScreen.kt | 3 ++ .../wire/android/ui/home/HomeSnackbarState.kt | 2 ++ .../details/GroupConversationDetailsScreen.kt | 8 ++++- .../GroupConversationDetailsViewModel.kt | 19 ++++++++-- ...ersationDetailsBottomSheetEventsHandler.kt | 8 ++--- .../ConversationListViewModel.kt | 24 ++++++++++--- .../conversationslist/ConversationRouter.kt | 8 ++++- .../ImportMediaAuthenticatedViewModel.kt | 2 +- .../other/OtherUserProfileEventsHandlers.kt | 4 +-- .../other/OtherUserProfileInfoMessageType.kt | 6 ++-- .../other/OtherUserProfileScreenViewModel.kt | 20 +++++++++-- .../OtherUserProfileBottomSheet.kt | 2 +- app/src/main/res/values/strings.xml | 2 ++ kalium | 2 +- 16 files changed, 109 insertions(+), 41 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt index 21c9a8eeda0..f268710d81b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt @@ -41,7 +41,7 @@ fun ConversationSheetContent( onMutingConversationStatusChange: () -> Unit, addConversationToFavourites: () -> Unit, moveConversationToFolder: () -> Unit, - moveConversationToArchive: () -> Unit, + moveConversationToArchive: (DialogState) -> Unit, clearConversationContent: (DialogState) -> Unit, blockUser: (BlockUserDialogState) -> Unit, unblockUser: (UnblockUserDialogState) -> Unit, @@ -61,7 +61,7 @@ fun ConversationSheetContent( // // addConversationToFavourites = addConversationToFavourites, // moveConversationToFolder = moveConversationToFolder, -// moveConversationToArchive = moveConversationToArchive, + moveConversationToArchive = moveConversationToArchive, clearConversationContent = clearConversationContent, blockUserClick = blockUser, unblockUserClick = unblockUser, diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt index ae20cfd006b..b2f5e9562cc 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/HomeSheetContent.kt @@ -58,10 +58,9 @@ import com.wire.kalium.logic.data.user.ConnectionState internal fun ConversationMainSheetContent( conversationSheetContent: ConversationSheetContent, // TODO(profile): enable when implemented -// // addConversationToFavourites: () -> Unit, // moveConversationToFolder: () -> Unit, -// moveConversationToArchive: () -> Unit, + moveConversationToArchive: (DialogState) -> Unit, clearConversationContent: (DialogState) -> Unit, blockUserClick: (BlockUserDialogState) -> Unit, unblockUserClick: (UnblockUserDialogState) -> Unit, @@ -135,18 +134,27 @@ internal fun ConversationMainSheetContent( // onItemClick = moveConversationToFolder // ) // } -// add { -// MenuBottomSheetItem( -// icon = { -// MenuItemIcon( -// id = R.drawable.ic_archive, -// contentDescription = stringResource(R.string.content_description_move_to_archive), -// ) -// }, -// title = stringResource(R.string.label_move_to_archive), -// onItemClick = moveConversationToArchive -// ) -// } + add { + MenuBottomSheetItem( + icon = { + MenuItemIcon( + id = R.drawable.ic_archive, + contentDescription = stringResource(R.string.content_description_move_to_archive), + ) + }, + title = stringResource(R.string.label_move_to_archive), + onItemClick = { + with(conversationSheetContent) { + moveConversationToArchive( + DialogState( + conversationId, + title, + conversationTypeDetail + ) + ) + } + }) + } add { MenuBottomSheetItem( icon = { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt index a3937541753..fa2c4ce80d0 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt @@ -362,6 +362,9 @@ private fun handleSnackBarMessage( is HomeSnackbarState.ClearConversationContentSuccess -> stringResource( if (messageType.isGroup) R.string.group_content_deleted else R.string.conversation_content_deleted ) + + HomeSnackbarState.ArchivingConversationError -> stringResource(id = R.string.error_archiving_conversation) + HomeSnackbarState.ArchivingConversationSuccess -> stringResource(id = R.string.success_archiving_conversation) } LaunchedEffect(messageType) { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt b/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt index c94adf91293..5356c0af4ee 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt @@ -35,4 +35,6 @@ sealed class HomeSnackbarState { object DeleteConversationGroupError : HomeSnackbarState() object LeftConversationSuccess : HomeSnackbarState() object LeaveConversationError : HomeSnackbarState() + object ArchivingConversationSuccess: HomeSnackbarState() + object ArchivingConversationError: HomeSnackbarState() } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index 2772040cc3e..e2e008d5fdb 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -358,7 +358,13 @@ private fun GroupConversationDetailsContent( }, addConversationToFavourites = bottomSheetEventsHandler::onAddConversationToFavourites, moveConversationToFolder = bottomSheetEventsHandler::onMoveConversationToFolder, - moveConversationToArchive = bottomSheetEventsHandler::onMoveConversationToArchive, + moveConversationToArchive = { + bottomSheetEventsHandler.onMoveConversationToArchive( + conversationId = conversationSheetContent!!.conversationId, + shouldArchive = true, + closeBottomSheetAndShowSnackbarMessage + ) + }, clearConversationContent = clearConversationDialogState::show, blockUser = {}, unblockUser = {}, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt index afdfdff645d..5fe38ce911b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt @@ -45,12 +45,14 @@ import com.wire.kalium.logic.data.conversation.ConversationDetails import com.wire.kalium.logic.data.conversation.MutedConversationStatus import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.id.QualifiedID +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.ConversationUpdateReceiptModeResult import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationAccessRoleUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationReceiptModeUseCase import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase @@ -91,6 +93,7 @@ class GroupConversationDetailsViewModel @Inject constructor( private val clearConversationContent: ClearConversationContentUseCase, private val updateConversationReceiptMode: UpdateConversationReceiptModeUseCase, private val observeSelfDeletionTimerSettingsForConversation: ObserveSelfDeletionTimerSettingsForConversationUseCase, + private val updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase, override val savedStateHandle: SavedStateHandle, private val isMLSEnabled: IsMLSEnabledUseCase, refreshUsersWithoutMetadata: RefreshUsersWithoutMetadataUseCase, @@ -375,8 +378,20 @@ class GroupConversationDetailsViewModel @Inject constructor( override fun onMoveConversationToFolder(conversationId: ConversationId?) { } - @Suppress("EmptyFunctionBlock") - override fun onMoveConversationToArchive(conversationId: ConversationId?) { + override fun onMoveConversationToArchive( + conversationId: ConversationId, + shouldArchive: Boolean, + onMessage: (UIText) -> Unit + ) { + viewModelScope.launch { + requestInProgress = true + val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, shouldArchive) } + requestInProgress = false + when (result) { + ArchiveStatusUpdateResult.Failure -> onMessage(UIText.StringResource(R.string.error_archiving_conversation)) + ArchiveStatusUpdateResult.Success -> onMessage(UIText.StringResource(R.string.success_archiving_conversation)) + } + } } companion object { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt index 928bba67336..a8f56872121 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt @@ -30,20 +30,18 @@ interface GroupConversationDetailsBottomSheetEventsHandler { fun onMutingConversationStatusChange(conversationId: ConversationId?, status: MutedConversationStatus, onMessage: (UIText) -> Unit) fun onAddConversationToFavourites(conversationId: ConversationId? = null) fun onMoveConversationToFolder(conversationId: ConversationId? = null) - fun onMoveConversationToArchive(conversationId: ConversationId? = null) + fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchive: Boolean, onMessage: (UIText) -> Unit) fun onClearConversationContent(dialogState: DialogState, onMessage: (UIText) -> Unit) companion object { @Suppress("TooManyFunctions") val PREVIEW = object : GroupConversationDetailsBottomSheetEventsHandler { override fun onMutingConversationStatusChange( - conversationId: ConversationId?, - status: MutedConversationStatus, - onMessage: (UIText) -> Unit + conversationId: ConversationId?, status: MutedConversationStatus, onMessage: (UIText) -> Unit ) {} override fun onAddConversationToFavourites(conversationId: ConversationId?) {} override fun onMoveConversationToFolder(conversationId: ConversationId?) {} - override fun onMoveConversationToArchive(conversationId: ConversationId?) {} + override fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchive: Boolean, onMessage: (UIText) -> Unit) {} override fun onClearConversationContent(dialogState: DialogState, onMessage: (UIText) -> Unit) {} } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt index da76577eb6b..50a4a1ab8d2 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt @@ -66,12 +66,14 @@ import com.wire.kalium.logic.feature.connection.BlockUserResult import com.wire.kalium.logic.feature.connection.BlockUserUseCase import com.wire.kalium.logic.feature.connection.UnblockUserResult import com.wire.kalium.logic.feature.connection.UnblockUserUseCase +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.LeaveConversationUseCase import com.wire.kalium.logic.feature.conversation.ObserveConversationListDetailsUseCase import com.wire.kalium.logic.feature.conversation.RefreshConversationsWithoutMetadataUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase @@ -108,7 +110,8 @@ class ConversationListViewModel @Inject constructor( private val userTypeMapper: UserTypeMapper, private val endCall: EndCallUseCase, private val refreshUsersWithoutMetadata: RefreshUsersWithoutMetadataUseCase, - private val refreshConversationsWithoutMetadata: RefreshConversationsWithoutMetadataUseCase + private val refreshConversationsWithoutMetadata: RefreshConversationsWithoutMetadataUseCase, + private val updateConversationArchivedStatusUseCase: UpdateConversationArchivedStatusUseCase, ) : ViewModel() { var conversationListState by mutableStateOf(ConversationListState()) @@ -148,7 +151,7 @@ class ConversationListViewModel @Inject constructor( } viewModelScope.launch { searchQueryFlow.combine( - observeConversationListDetails() + observeConversationListDetails(fetchArchivedConversations = false) .map { it.map { conversationDetails -> conversationDetails.toConversationItem( @@ -417,9 +420,20 @@ class ConversationListViewModel @Inject constructor( fun moveConversationToFolder(id: String = "") { } - // TODO: needs to be implemented - @Suppress("EmptyFunctionBlock") - fun moveConversationToArchive(id: String = "") { + fun moveConversationToArchive(conversationId: ConversationId, isArchiving: Boolean) { + viewModelScope.launch { + requestInProgress = true + val result = withContext(dispatcher.io()) { updateConversationArchivedStatusUseCase(conversationId, isArchiving) } + requestInProgress = false + when (result) { + is ArchiveStatusUpdateResult.Failure -> { + homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationError) + } + is ArchiveStatusUpdateResult.Success -> { + homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationSuccess) + } + } + } } fun clearConversationContent(dialogState: DialogState) { diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt index 1f8010ef5d6..b9870c88202 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt @@ -149,7 +149,13 @@ fun ConversationRouterHomeBridge( }, addConversationToFavourites = viewModel::addConversationToFavourites, moveConversationToFolder = viewModel::moveConversationToFolder, - moveConversationToArchive = viewModel::moveConversationToArchive, + moveConversationToArchive = { + viewModel.moveConversationToArchive( + conversationId = it.conversationId, + isArchiving = true // All conversations at this point are not archived + ) + onCloseBottomSheet() + }, clearConversationContent = clearContentDialogState::show, blockUser = blockUserDialogState::show, unblockUser = unblockUserDialogState::show, diff --git a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt index e902fa38bdf..cf9d342baad 100644 --- a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt @@ -119,7 +119,7 @@ class ImportMediaAuthenticatedViewModel @Inject constructor( @OptIn(ExperimentalCoroutinesApi::class) private suspend fun observeConversationWithSearch() = viewModelScope.launch { searchQueryFlow.mapLatest { searchQuery -> - val conversations = observeConversationListDetails().first() + val conversations = observeConversationListDetails(fetchArchivedConversations = false).first() .mapNotNull { conversationDetails -> conversationDetails.toConversationItem( wireSessionImageLoader, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileEventsHandlers.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileEventsHandlers.kt index 9b4473edef3..67ad451915d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileEventsHandlers.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileEventsHandlers.kt @@ -71,7 +71,7 @@ interface OtherUserProfileBottomSheetEventsHandler { fun onMutingConversationStatusChange(conversationId: ConversationId?, status: MutedConversationStatus) fun onAddConversationToFavourites(conversationId: ConversationId? = null) fun onMoveConversationToFolder(conversationId: ConversationId? = null) - fun onMoveConversationToArchive(conversationId: ConversationId? = null) + fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchiveConversation: Boolean) fun onClearConversationContent(dialogState: DialogState) companion object { @@ -81,7 +81,7 @@ interface OtherUserProfileBottomSheetEventsHandler { override fun onMutingConversationStatusChange(conversationId: ConversationId?, status: MutedConversationStatus) {} override fun onAddConversationToFavourites(conversationId: ConversationId?) {} override fun onMoveConversationToFolder(conversationId: ConversationId?) {} - override fun onMoveConversationToArchive(conversationId: ConversationId?) {} + override fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchiveConversation: Boolean) {} override fun onClearConversationContent(dialogState: DialogState) {} } } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt index ff82d061134..2058a90a306 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt @@ -48,14 +48,12 @@ sealed class OtherUserProfileInfoMessageType(override val uiText: UIText) : Snac object BlockingUserOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_blocking_user)) class BlockingUserOperationSuccess(val name: String) : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.blocking_user_success, name)) - object MutingOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_updating_muting_setting)) - object UnblockingUserOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_unblocking_user)) - object ConversationContentDeleted : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.conversation_content_deleted)) - object ConversationContentDeleteFailure : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.conversation_content_delete_failure)) + object ArchiveConversationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_archiving_conversation)) + object ArchiveConversationSuccess : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.success_archiving_conversation)) } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt index d58439fe151..33a27987c69 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt @@ -61,10 +61,12 @@ import com.wire.kalium.logic.feature.connection.BlockUserResult import com.wire.kalium.logic.feature.connection.BlockUserUseCase import com.wire.kalium.logic.feature.connection.UnblockUserResult import com.wire.kalium.logic.feature.connection.UnblockUserUseCase +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.GetOneToOneConversationUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleResult import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase @@ -100,6 +102,7 @@ class OtherUserProfileScreenViewModel @Inject constructor( private val observeClientList: ObserveClientsByUserIdUseCase, private val persistOtherUserClients: PersistOtherUserClientsUseCase, private val clearConversationContentUseCase: ClearConversationContentUseCase, + private val updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase, savedStateHandle: SavedStateHandle ) : ViewModel(), OtherUserProfileEventsHandler, OtherUserProfileBottomSheetEventsHandler { @@ -292,8 +295,21 @@ class OtherUserProfileScreenViewModel @Inject constructor( override fun onMoveConversationToFolder(conversationId: ConversationId?) { } - @Suppress("EmptyFunctionBlock") - override fun onMoveConversationToArchive(conversationId: ConversationId?) { + override fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchiveConversation: Boolean) { + viewModelScope.launch { + requestInProgress = true + val result = withContext(dispatchers.io()) { updateConversationArchivedStatus(conversationId, shouldArchiveConversation) } + requestInProgress = false + when (result) { + ArchiveStatusUpdateResult.Failure -> { + closeBottomSheetAndShowInfoMessage(OtherUserProfileInfoMessageType.ArchiveConversationError) + } + + ArchiveStatusUpdateResult.Success -> { + closeBottomSheetAndShowInfoMessage(OtherUserProfileInfoMessageType.ArchiveConversationSuccess) + } + } + } } override fun onClearConversationContent(dialogState: DialogState) { diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/bottomsheet/OtherUserProfileBottomSheet.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/bottomsheet/OtherUserProfileBottomSheet.kt index 109956057fb..293ff54525b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/bottomsheet/OtherUserProfileBottomSheet.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/bottomsheet/OtherUserProfileBottomSheet.kt @@ -53,7 +53,7 @@ fun OtherUserProfileBottomSheetContent( }, addConversationToFavourites = eventsHandler::onAddConversationToFavourites, moveConversationToFolder = eventsHandler::onMoveConversationToFolder, - moveConversationToArchive = eventsHandler::onMoveConversationToArchive, + moveConversationToArchive = { eventsHandler.onMoveConversationToArchive(it.conversationId, true) }, clearConversationContent = clearContent, blockUser = blockUser, unblockUser = unblockUser, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 11f963c728f..f5506580b9a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -714,6 +714,8 @@ User could not be unblocked There was an error while deleting conversation You can only send up to 20 files at once + Conversation was archived + Conversation could not be archived MessageComposeInputState transition Collapse button rotation degree transition diff --git a/kalium b/kalium index bf09e785b1d..697fb8f1afd 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit bf09e785b1d68542d56d1eb2dfedc2f8c81032ea +Subproject commit 697fb8f1afd8458f9257c6b46f21dba2ff3bba13 From 72f8a82e9ef157a1a33f5aec1b246f236a604741 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Fri, 22 Sep 2023 15:25:56 +0200 Subject: [PATCH 03/10] feat: adapted tests --- .../home/conversationslist/ConversationListViewModel.kt | 4 ++-- .../conversationslist/ConversationListViewModelTest.kt | 9 +++++++-- kalium | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt index 50a4a1ab8d2..cb110ddd9bc 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt @@ -111,7 +111,7 @@ class ConversationListViewModel @Inject constructor( private val endCall: EndCallUseCase, private val refreshUsersWithoutMetadata: RefreshUsersWithoutMetadataUseCase, private val refreshConversationsWithoutMetadata: RefreshConversationsWithoutMetadataUseCase, - private val updateConversationArchivedStatusUseCase: UpdateConversationArchivedStatusUseCase, + private val updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase, ) : ViewModel() { var conversationListState by mutableStateOf(ConversationListState()) @@ -423,7 +423,7 @@ class ConversationListViewModel @Inject constructor( fun moveConversationToArchive(conversationId: ConversationId, isArchiving: Boolean) { viewModelScope.launch { requestInProgress = true - val result = withContext(dispatcher.io()) { updateConversationArchivedStatusUseCase(conversationId, isArchiving) } + val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, isArchiving) } requestInProgress = false when (result) { is ArchiveStatusUpdateResult.Failure -> { diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt index 2e5b97cf801..76265b2045d 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt @@ -48,6 +48,7 @@ import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.LeaveConversationUseCase import com.wire.kalium.logic.feature.conversation.ObserveConversationListDetailsUseCase import com.wire.kalium.logic.feature.conversation.RefreshConversationsWithoutMetadataUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase @@ -111,6 +112,9 @@ class ConversationListViewModelTest { @MockK private lateinit var refreshConversationsWithoutMetadata: RefreshConversationsWithoutMetadataUseCase + @MockK + private lateinit var updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase + @MockK(relaxed = true) private lateinit var onJoined: (ConversationId) -> Unit @@ -119,7 +123,7 @@ class ConversationListViewModelTest { MockKAnnotations.init(this, relaxUnitFun = true) coEvery { observeEstablishedCalls.invoke() } returns emptyFlow() - coEvery { observeConversationListDetailsUseCase.invoke() } returns emptyFlow() + coEvery { observeConversationListDetailsUseCase.invoke(any()) } returns emptyFlow() mockUri() conversationListViewModel = @@ -139,9 +143,10 @@ class ConversationListViewModelTest { refreshUsersWithoutMetadata = refreshUsersWithoutMetadata, refreshConversationsWithoutMetadata = refreshConversationsWithoutMetadata, userTypeMapper = UserTypeMapper(), + updateConversationArchivedStatus = updateConversationArchivedStatus ) - coEvery { observeConversationListDetailsUseCase() } returns flowOf(listOf()) + coEvery { observeConversationListDetailsUseCase(any()) } returns flowOf(listOf()) } @Test diff --git a/kalium b/kalium index 697fb8f1afd..9ae739a4057 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 697fb8f1afd8458f9257c6b46f21dba2ff3bba13 +Subproject commit 9ae739a4057ce998035a4320d81793056ba3b37e From 1ec8fcf478665d12cc4b70d4761c33b2fe745db1 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Fri, 22 Sep 2023 17:59:52 +0200 Subject: [PATCH 04/10] fix: detekt issues --- app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt | 1 - .../main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt | 4 ++-- .../menu/GroupConversationDetailsBottomSheetEventsHandler.kt | 4 +++- .../ui/userprofile/other/OtherUserProfileInfoMessageType.kt | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt index de0d57ca58b..db8e1ecf662 100644 --- a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt @@ -35,7 +35,6 @@ import com.wire.kalium.logic.feature.connection.BlockUserUseCase import com.wire.kalium.logic.feature.connection.UnblockUserUseCase import com.wire.kalium.logic.feature.conversation.ObserveOtherUserSecurityClassificationLabelUseCase import com.wire.kalium.logic.feature.conversation.ObserveSecurityClassificationLabelUseCase -import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUseCase import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveSelfDeletionTimerSettingsForConversationUseCase import com.wire.kalium.logic.feature.selfDeletingMessages.ObserveTeamSettingsSelfDeletingStatusUseCase diff --git a/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt b/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt index 5356c0af4ee..15ccf7e134d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/HomeSnackbarState.kt @@ -35,6 +35,6 @@ sealed class HomeSnackbarState { object DeleteConversationGroupError : HomeSnackbarState() object LeftConversationSuccess : HomeSnackbarState() object LeaveConversationError : HomeSnackbarState() - object ArchivingConversationSuccess: HomeSnackbarState() - object ArchivingConversationError: HomeSnackbarState() + object ArchivingConversationSuccess : HomeSnackbarState() + object ArchivingConversationError : HomeSnackbarState() } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt index a8f56872121..cb85f1d65db 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt @@ -38,7 +38,9 @@ interface GroupConversationDetailsBottomSheetEventsHandler { val PREVIEW = object : GroupConversationDetailsBottomSheetEventsHandler { override fun onMutingConversationStatusChange( conversationId: ConversationId?, status: MutedConversationStatus, onMessage: (UIText) -> Unit - ) {} + ) { + } + override fun onAddConversationToFavourites(conversationId: ConversationId?) {} override fun onMoveConversationToFolder(conversationId: ConversationId?) {} override fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchive: Boolean, onMessage: (UIText) -> Unit) {} diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt index 2058a90a306..3c2348d3edf 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileInfoMessageType.kt @@ -48,11 +48,13 @@ sealed class OtherUserProfileInfoMessageType(override val uiText: UIText) : Snac object BlockingUserOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_blocking_user)) class BlockingUserOperationSuccess(val name: String) : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.blocking_user_success, name)) + object MutingOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_updating_muting_setting)) object UnblockingUserOperationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_unblocking_user)) object ConversationContentDeleted : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.conversation_content_deleted)) object ConversationContentDeleteFailure : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.conversation_content_delete_failure)) + object ArchiveConversationError : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.error_archiving_conversation)) object ArchiveConversationSuccess : OtherUserProfileInfoMessageType(UIText.StringResource(R.string.success_archiving_conversation)) From a8e76ab1850eb661e2bf626b82a62d99014aba1c Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Sat, 23 Sep 2023 10:37:37 +0200 Subject: [PATCH 05/10] more detekt pain --- .../menu/GroupConversationDetailsBottomSheetEventsHandler.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt index cb85f1d65db..42dba998ea8 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt @@ -37,7 +37,9 @@ interface GroupConversationDetailsBottomSheetEventsHandler { @Suppress("TooManyFunctions") val PREVIEW = object : GroupConversationDetailsBottomSheetEventsHandler { override fun onMutingConversationStatusChange( - conversationId: ConversationId?, status: MutedConversationStatus, onMessage: (UIText) -> Unit + conversationId: ConversationId?, + status: MutedConversationStatus, + onMessage: (UIText) -> Unit ) { } From f2188cbb1fa9188f32df1aa2e867a8ef8876eb5c Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Mon, 25 Sep 2023 12:53:26 +0200 Subject: [PATCH 06/10] renamed vars and fixed tests --- .../details/GroupConversationDetailsScreen.kt | 24 +++++++++++-------- .../ConversationListViewModel.kt | 2 +- .../ImportMediaAuthenticatedViewModel.kt | 2 +- .../OtherUserProfileViewModelArrangement.kt | 7 ++++++ kalium | 2 +- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index e2e008d5fdb..b783e28a24c 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -350,20 +350,24 @@ private fun GroupConversationDetailsContent( isBottomSheetVisible = getBottomSheetVisibility, conversationSheetState = conversationSheetState, onMutingConversationStatusChange = { - bottomSheetEventsHandler.onMutingConversationStatusChange( - conversationSheetState.conversationId, - conversationSheetState.conversationSheetContent!!.mutingConversationState, - closeBottomSheetAndShowSnackbarMessage - ) + conversationSheetContent?.let { + bottomSheetEventsHandler.onMutingConversationStatusChange( + conversationSheetState.conversationId, + it.mutingConversationState, + closeBottomSheetAndShowSnackbarMessage + ) + } }, addConversationToFavourites = bottomSheetEventsHandler::onAddConversationToFavourites, moveConversationToFolder = bottomSheetEventsHandler::onMoveConversationToFolder, moveConversationToArchive = { - bottomSheetEventsHandler.onMoveConversationToArchive( - conversationId = conversationSheetContent!!.conversationId, - shouldArchive = true, - closeBottomSheetAndShowSnackbarMessage - ) + conversationSheetContent?.let { + bottomSheetEventsHandler.onMoveConversationToArchive( + conversationId = it.conversationId, + shouldArchive = true, + closeBottomSheetAndShowSnackbarMessage + ) + } }, clearConversationContent = clearConversationDialogState::show, blockUser = {}, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt index cb110ddd9bc..ba05e850687 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt @@ -151,7 +151,7 @@ class ConversationListViewModel @Inject constructor( } viewModelScope.launch { searchQueryFlow.combine( - observeConversationListDetails(fetchArchivedConversations = false) + observeConversationListDetails(includeArchived = false) .map { it.map { conversationDetails -> conversationDetails.toConversationItem( diff --git a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt index cf9d342baad..68183813bcc 100644 --- a/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/sharing/ImportMediaAuthenticatedViewModel.kt @@ -119,7 +119,7 @@ class ImportMediaAuthenticatedViewModel @Inject constructor( @OptIn(ExperimentalCoroutinesApi::class) private suspend fun observeConversationWithSearch() = viewModelScope.launch { searchQueryFlow.mapLatest { searchQuery -> - val conversations = observeConversationListDetails(fetchArchivedConversations = false).first() + val conversations = observeConversationListDetails(includeArchived = false).first() .mapNotNull { conversationDetails -> conversationDetails.toConversationItem( wireSessionImageLoader, diff --git a/app/src/test/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileViewModelArrangement.kt b/app/src/test/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileViewModelArrangement.kt index 24dfd47b05c..39f2fb89b0d 100644 --- a/app/src/test/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileViewModelArrangement.kt +++ b/app/src/test/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileViewModelArrangement.kt @@ -37,9 +37,11 @@ import com.wire.kalium.logic.feature.client.PersistOtherUserClientsUseCase import com.wire.kalium.logic.feature.connection.BlockUserResult import com.wire.kalium.logic.feature.connection.BlockUserUseCase import com.wire.kalium.logic.feature.connection.UnblockUserUseCase +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.GetOneToOneConversationUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleResult import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase @@ -99,6 +101,9 @@ internal class OtherUserProfileViewModelArrangement { @MockK lateinit var clearConversationContent: ClearConversationContentUseCase + @MockK + lateinit var updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase + private val viewModel by lazy { OtherUserProfileScreenViewModel( TestDispatcherProvider(), @@ -115,6 +120,7 @@ internal class OtherUserProfileViewModelArrangement { observeClientList, persistOtherUserClientsUseCase, clearConversationContent, + updateConversationArchivedStatus, savedStateHandle ) } @@ -138,6 +144,7 @@ internal class OtherUserProfileViewModelArrangement { ) ) coEvery { observeSelfUser() } returns flowOf(TestUser.SELF_USER) + coEvery { updateConversationArchivedStatus(any(), any()) } returns ArchiveStatusUpdateResult.Success every { userTypeMapper.toMembership(any()) } returns Membership.None coEvery { getOneToOneConversation(USER_ID) } returns flowOf( GetOneToOneConversationUseCase.Result.Success(OtherUserProfileScreenViewModelTest.CONVERSATION) diff --git a/kalium b/kalium index 9ae739a4057..e51ad570493 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 9ae739a4057ce998035a4320d81793056ba3b37e +Subproject commit e51ad570493017e0d4ce4d5396f743a2212d51d5 From bc8666538c44bce9c24c67735d5e514e1cd78824 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Mon, 25 Sep 2023 17:31:55 +0200 Subject: [PATCH 07/10] fix: added VM tests --- .../details/GroupConversationDetailsScreen.kt | 2 +- .../GroupConversationDetailsViewModel.kt | 4 +- ...ersationDetailsBottomSheetEventsHandler.kt | 18 +++- .../ConversationListViewModel.kt | 10 ++- .../GroupConversationDetailsViewModelTest.kt | 84 +++++++++++++++++++ .../ConversationListViewModelTest.kt | 21 ++++- kalium | 2 +- 7 files changed, 131 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index b783e28a24c..6b0b6d5e0e1 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -365,7 +365,7 @@ private fun GroupConversationDetailsContent( bottomSheetEventsHandler.onMoveConversationToArchive( conversationId = it.conversationId, shouldArchive = true, - closeBottomSheetAndShowSnackbarMessage + onMessage = closeBottomSheetAndShowSnackbarMessage ) } }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt index 5fe38ce911b..44c29dbd7da 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModel.kt @@ -381,11 +381,13 @@ class GroupConversationDetailsViewModel @Inject constructor( override fun onMoveConversationToArchive( conversationId: ConversationId, shouldArchive: Boolean, + timestamp: Long, onMessage: (UIText) -> Unit ) { viewModelScope.launch { requestInProgress = true - val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, shouldArchive) } + val result = + withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, shouldArchive, timestamp) } requestInProgress = false when (result) { ArchiveStatusUpdateResult.Failure -> onMessage(UIText.StringResource(R.string.error_archiving_conversation)) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt index 42dba998ea8..25c8465d323 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/menu/GroupConversationDetailsBottomSheetEventsHandler.kt @@ -24,13 +24,20 @@ import com.wire.android.ui.home.conversationslist.model.DialogState import com.wire.android.util.ui.UIText import com.wire.kalium.logic.data.conversation.MutedConversationStatus import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.util.DateTimeUtil @Suppress("TooManyFunctions") interface GroupConversationDetailsBottomSheetEventsHandler { fun onMutingConversationStatusChange(conversationId: ConversationId?, status: MutedConversationStatus, onMessage: (UIText) -> Unit) fun onAddConversationToFavourites(conversationId: ConversationId? = null) fun onMoveConversationToFolder(conversationId: ConversationId? = null) - fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchive: Boolean, onMessage: (UIText) -> Unit) + fun onMoveConversationToArchive( + conversationId: ConversationId, + shouldArchive: Boolean, + timestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds(), + onMessage: (UIText) -> Unit + ) + fun onClearConversationContent(dialogState: DialogState, onMessage: (UIText) -> Unit) companion object { @@ -45,7 +52,14 @@ interface GroupConversationDetailsBottomSheetEventsHandler { override fun onAddConversationToFavourites(conversationId: ConversationId?) {} override fun onMoveConversationToFolder(conversationId: ConversationId?) {} - override fun onMoveConversationToArchive(conversationId: ConversationId, shouldArchive: Boolean, onMessage: (UIText) -> Unit) {} + override fun onMoveConversationToArchive( + conversationId: ConversationId, + shouldArchive: Boolean, + timestamp: Long, + onMessage: (UIText) -> Unit + ) { + } + override fun onClearConversationContent(dialogState: DialogState, onMessage: (UIText) -> Unit) {} } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt index ba05e850687..fde5aca9bd4 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt @@ -79,6 +79,7 @@ import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCa import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase import com.wire.kalium.logic.feature.team.Result import com.wire.kalium.logic.functional.combine +import com.wire.kalium.util.DateTimeUtil import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.delay @@ -420,15 +421,20 @@ class ConversationListViewModel @Inject constructor( fun moveConversationToFolder(id: String = "") { } - fun moveConversationToArchive(conversationId: ConversationId, isArchiving: Boolean) { + fun moveConversationToArchive( + conversationId: ConversationId, + isArchiving: Boolean, + timestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds() + ) { viewModelScope.launch { requestInProgress = true - val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, isArchiving) } + val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, isArchiving, timestamp) } requestInProgress = false when (result) { is ArchiveStatusUpdateResult.Failure -> { homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationError) } + is ArchiveStatusUpdateResult.Success -> { homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationSuccess) } diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModelTest.kt index 024603d2a50..b8958f8ba77 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsViewModelTest.kt @@ -39,12 +39,14 @@ import com.wire.kalium.logic.data.conversation.MutedConversationStatus import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.id.TeamId import com.wire.kalium.logic.data.team.Team +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.ConversationUpdateReceiptModeResult import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase import com.wire.kalium.logic.feature.conversation.RemoveMemberFromConversationUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationAccessRoleUseCase +import com.wire.kalium.logic.feature.conversation.UpdateConversationArchivedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase import com.wire.kalium.logic.feature.conversation.UpdateConversationReceiptModeUseCase import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase @@ -123,6 +125,78 @@ class GroupConversationDetailsViewModelTest { assertEquals(details2.conversation.name, viewModel.groupOptionsState.value.groupName) } + @Test + fun `given some conversation details, when archiving that conversation, then the use case is invoked`() = runTest { + // Given + val members = buildList { + for (i in 1..5) { + add(testUIParticipant(i)) + } + } + val archivingEventTimestamp = 123456789L + val conversationParticipantsData = ConversationParticipantsData( + participants = members.take(GroupConversationDetailsViewModel.MAX_NUMBER_OF_PARTICIPANTS), + allParticipantsCount = members.size + ) + + val conversationDetails = testGroup.copy(conversation = testGroup.conversation.copy(name = "Group name 1")) + val (arrangement, viewModel) = GroupConversationDetailsViewModelArrangement() + .withConversationDetailUpdate(conversationDetails) + .withConversationMembersUpdate(conversationParticipantsData) + .withUpdateArchivedStatus(ArchiveStatusUpdateResult.Success) + .arrange() + + // When + viewModel.onMoveConversationToArchive( + conversationId = viewModel.conversationId, + shouldArchive = true, + timestamp = archivingEventTimestamp + ) {} + + // Then + coVerify(exactly = 1) { + arrangement.updateConversationArchivedStatus( + conversationId = viewModel.conversationId, + shouldArchiveConversation = true, + archivedStatusTimestamp = archivingEventTimestamp + ) + } + } + + @Test + fun `given some conversation details, when un-archiving that conversation, then the use case is invoked`() = runTest { + // Given + val members = buildList { + for (i in 1..5) { + add(testUIParticipant(i)) + } + } + val archivingEventTimestamp = 123456789L + val conversationParticipantsData = ConversationParticipantsData( + participants = members.take(GroupConversationDetailsViewModel.MAX_NUMBER_OF_PARTICIPANTS), + allParticipantsCount = members.size + ) + + val conversationDetails = testGroup.copy(conversation = testGroup.conversation.copy(name = "Group name 1")) + val (arrangement, viewModel) = GroupConversationDetailsViewModelArrangement() + .withConversationDetailUpdate(conversationDetails) + .withConversationMembersUpdate(conversationParticipantsData) + .withUpdateArchivedStatus(ArchiveStatusUpdateResult.Success) + .arrange() + + // When + viewModel.onMoveConversationToArchive(viewModel.conversationId, false, archivingEventTimestamp) {} + + // Then + coVerify(exactly = 1) { + arrangement.updateConversationArchivedStatus( + conversationId = viewModel.conversationId, + shouldArchiveConversation = false, + archivedStatusTimestamp = archivingEventTimestamp + ) + } + } + @Test fun `given a group conversation, when solving the state, then the state is correct`() = runTest { // Given @@ -541,6 +615,9 @@ internal class GroupConversationDetailsViewModelArrangement { @MockK lateinit var observeSelfDeletionTimerSettingsForConversation: ObserveSelfDeletionTimerSettingsForConversationUseCase + @MockK + lateinit var updateConversationArchivedStatus: UpdateConversationArchivedStatusUseCase + private val conversationDetailsChannel = Channel(capacity = Channel.UNLIMITED) private val observeParticipantsForConversationChannel = Channel(capacity = Channel.UNLIMITED) @@ -565,6 +642,7 @@ internal class GroupConversationDetailsViewModelArrangement { isMLSEnabled = isMLSEnabledUseCase, observeSelfDeletionTimerSettingsForConversation = observeSelfDeletionTimerSettingsForConversation, refreshUsersWithoutMetadata = refreshUsersWithoutMetadata, + updateConversationArchivedStatus = updateConversationArchivedStatus ) } @@ -590,6 +668,7 @@ internal class GroupConversationDetailsViewModelArrangement { coEvery { isMLSEnabledUseCase() } returns true coEvery { updateConversationMutedStatus(any(), any(), any()) } returns ConversationUpdateStatusResult.Success coEvery { observeSelfDeletionTimerSettingsForConversation(any(), any()) } returns flowOf(SelfDeletionTimer.Disabled) + coEvery { updateConversationArchivedStatus(any(), any()) } returns ArchiveStatusUpdateResult.Success } suspend fun withConversationDetailUpdate(conversationDetails: ConversationDetails) = apply { @@ -615,5 +694,10 @@ internal class GroupConversationDetailsViewModelArrangement { coEvery { updateConversationReceiptMode(any(), any()) } returns ConversationUpdateReceiptModeResult.Success } + suspend fun withUpdateArchivedStatus(result: ArchiveStatusUpdateResult) = apply { + coEvery { updateConversationArchivedStatus(any(), any()) } returns result + coEvery { updateConversationArchivedStatus(any(), any(), any()) } returns result + } + fun arrange() = this to viewModel } diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt index 76265b2045d..0c88c270775 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt @@ -26,6 +26,7 @@ import com.wire.android.config.mockUri import com.wire.android.mapper.UserTypeMapper import com.wire.android.model.UserAvatarData import com.wire.android.ui.common.dialogs.BlockUserDialogState +import com.wire.android.ui.home.HomeSnackbarState import com.wire.android.ui.home.conversations.model.UILastMessageContent import com.wire.android.ui.home.conversationslist.model.BadgeEventType import com.wire.android.ui.home.conversationslist.model.BlockingState @@ -43,6 +44,7 @@ import com.wire.kalium.logic.feature.connection.BlockUserResult import com.wire.kalium.logic.feature.connection.BlockUserUseCase import com.wire.kalium.logic.feature.connection.UnblockUserResult import com.wire.kalium.logic.feature.connection.UnblockUserUseCase +import com.wire.kalium.logic.feature.conversation.ArchiveStatusUpdateResult import com.wire.kalium.logic.feature.conversation.ClearConversationContentUseCase import com.wire.kalium.logic.feature.conversation.ConversationUpdateStatusResult import com.wire.kalium.logic.feature.conversation.LeaveConversationUseCase @@ -59,9 +61,9 @@ import io.mockk.impl.annotations.MockK import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.runTest import org.amshove.kluent.internal.assertEquals +import org.junit.Assert.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -145,8 +147,6 @@ class ConversationListViewModelTest { userTypeMapper = UserTypeMapper(), updateConversationArchivedStatus = updateConversationArchivedStatus ) - - coEvery { observeConversationListDetailsUseCase(any()) } returns flowOf(listOf()) } @Test @@ -253,6 +253,21 @@ class ConversationListViewModelTest { assertEquals(false, conversationListViewModel.conversationListState.shouldShowCallingPermissionDialog) } + @Test + fun `given a valid conversation state, when archiving it correctly, then the right success message is shown`() = runTest { + val isArchiving = true + val archivingTimestamp = 123456789L + conversationListViewModel.conversationListState = + conversationListViewModel.conversationListState.copy(shouldShowCallingPermissionDialog = true) + coEvery { updateConversationArchivedStatus(any(), any(), any()) } returns ArchiveStatusUpdateResult.Success + + conversationListViewModel.moveConversationToArchive(conversationId, isArchiving, archivingTimestamp) + + coVerify(exactly = 1) { + conversationListViewModel.homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationSuccess) + } + } + companion object { private val conversationId = ConversationId("some_id", "some_domain") private val userId: UserId = UserId("someUser", "some_domain") diff --git a/kalium b/kalium index e51ad570493..580236d3359 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit e51ad570493017e0d4ce4d5396f743a2212d51d5 +Subproject commit 580236d3359fc035f4638a4228a92a0c51ad563b From de86f9d4b638d0ca106dfbe2d1f47c22f1f24541 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Tue, 26 Sep 2023 10:52:42 +0200 Subject: [PATCH 08/10] removed unused import --- .../ui/home/conversationslist/ConversationListViewModelTest.kt | 1 - kalium | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt index 0c88c270775..7689484838a 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt @@ -63,7 +63,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.test.runTest import org.amshove.kluent.internal.assertEquals -import org.junit.Assert.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith diff --git a/kalium b/kalium index 580236d3359..36674860900 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 580236d3359fc035f4638a4228a92a0c51ad563b +Subproject commit 36674860900b0ff9228dd252fee8b721803be842 From bc8fe4bbaa4ac405cc43278a763f5a634949db1b Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Tue, 26 Sep 2023 12:44:25 +0200 Subject: [PATCH 09/10] fix: fixed tests --- .../ConversationListViewModelTest.kt | 31 ++++++++++++++++--- kalium | 2 +- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt index 7689484838a..a0c0a33dd2e 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt @@ -20,6 +20,7 @@ package com.wire.android.ui.home.conversationslist +import app.cash.turbine.test import com.wire.android.config.CoroutineTestExtension import com.wire.android.config.TestDispatcherProvider import com.wire.android.config.mockUri @@ -60,9 +61,18 @@ import io.mockk.coVerify import io.mockk.impl.annotations.MockK import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.async +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest +import okhttp3.internal.wait import org.amshove.kluent.internal.assertEquals +import org.amshove.kluent.shouldBeEqualTo +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -256,14 +266,25 @@ class ConversationListViewModelTest { fun `given a valid conversation state, when archiving it correctly, then the right success message is shown`() = runTest { val isArchiving = true val archivingTimestamp = 123456789L - conversationListViewModel.conversationListState = - conversationListViewModel.conversationListState.copy(shouldShowCallingPermissionDialog = true) + coEvery { updateConversationArchivedStatus(any(), any(), any()) } returns ArchiveStatusUpdateResult.Success - conversationListViewModel.moveConversationToArchive(conversationId, isArchiving, archivingTimestamp) + conversationListViewModel.homeSnackBarState.test { + conversationListViewModel.moveConversationToArchive(conversationId, isArchiving, archivingTimestamp) + expectMostRecentItem() shouldBeEqualTo HomeSnackbarState.ArchivingConversationSuccess + } + } + + @Test + fun `given a valid conversation state, when archiving it with an error, then the right failure message is shown`() = runTest { + val isArchiving = true + val archivingTimestamp = 123456789L + + coEvery { updateConversationArchivedStatus(any(), any(), any()) } returns ArchiveStatusUpdateResult.Failure - coVerify(exactly = 1) { - conversationListViewModel.homeSnackBarState.emit(HomeSnackbarState.ArchivingConversationSuccess) + conversationListViewModel.homeSnackBarState.test { + conversationListViewModel.moveConversationToArchive(conversationId, isArchiving, archivingTimestamp) + expectMostRecentItem() shouldBeEqualTo HomeSnackbarState.ArchivingConversationError } } diff --git a/kalium b/kalium index 36674860900..45b6707e7a0 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 36674860900b0ff9228dd252fee8b721803be842 +Subproject commit 45b6707e7a0f29bd9b1647a7780fe04425404015 From 250e1f480f8c1e530b13767f931cd13cf70da734 Mon Sep 17 00:00:00 2001 From: Gonzalo Gran Crespo Date: Tue, 26 Sep 2023 13:02:48 +0200 Subject: [PATCH 10/10] detekt issues addressed --- .../conversationslist/ConversationListViewModelTest.kt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt index a0c0a33dd2e..7b5abe7d804 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModelTest.kt @@ -61,18 +61,10 @@ import io.mockk.coVerify import io.mockk.impl.annotations.MockK import io.mockk.verify import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.async -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest -import okhttp3.internal.wait import org.amshove.kluent.internal.assertEquals import org.amshove.kluent.shouldBeEqualTo -import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith