Skip to content

Commit

Permalink
feat: add confirmation dialog archiving [WPB-4434] (#2300)
Browse files Browse the repository at this point in the history
  • Loading branch information
gongracr authored Oct 5, 2023
1 parent 3522b4a commit 013245e
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.common.dialogs

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.wire.android.R
import com.wire.android.ui.common.VisibilityState
import com.wire.android.ui.common.WireDialog
import com.wire.android.ui.common.WireDialogButtonProperties
import com.wire.android.ui.common.WireDialogButtonType
import com.wire.android.ui.common.visbility.VisibilityState
import com.wire.android.ui.home.conversationslist.model.DialogState

@Composable
fun ArchiveConversationDialog(onArchiveButtonClicked: (DialogState) -> Unit, dialogState: VisibilityState<DialogState>) {
VisibilityState(dialogState) {
WireDialog(
title = stringResource(R.string.dialog_archive_conversation_title),
text = stringResource(R.string.dialog_archive_conversation_description),
onDismiss = dialogState::dismiss,
optionButton1Properties = WireDialogButtonProperties(
onClick = { onArchiveButtonClicked(it) },
text = stringResource(R.string.dialog_archive_conversation_option),
type = WireDialogButtonType.Primary,
),
dismissButtonProperties = WireDialogButtonProperties(
onClick = dialogState::dismiss,
text = stringResource(R.string.label_cancel),
type = WireDialogButtonType.Secondary,
),
buttonsHorizontalAlignment = true
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
Expand All @@ -68,6 +67,7 @@ import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetCont
import com.wire.android.ui.common.bottomsheet.conversation.rememberConversationSheetState
import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
import com.wire.android.ui.common.calculateCurrentTab
import com.wire.android.ui.common.dialogs.ArchiveConversationDialog
import com.wire.android.ui.common.scaffold.WireScaffold
import com.wire.android.ui.common.topBarElevation
import com.wire.android.ui.common.topappbar.NavigationIconType
Expand Down Expand Up @@ -221,7 +221,6 @@ fun GroupConversationDetailsScreen(
}

@OptIn(
ExperimentalComposeUiApi::class,
ExperimentalMaterial3Api::class,
ExperimentalFoundationApi::class
)
Expand Down Expand Up @@ -268,6 +267,7 @@ private fun GroupConversationDetailsContent(
val deleteGroupDialogState = rememberVisibilityState<GroupDialogState>()
val leaveGroupDialogState = rememberVisibilityState<GroupDialogState>()
val clearConversationDialogState = rememberVisibilityState<DialogState>()
val archiveConversationDialogState = rememberVisibilityState<DialogState>()

LaunchedEffect(conversationSheetState.conversationSheetContent) {
// on each closing BottomSheet we revert BSContent to Home.
Expand All @@ -282,6 +282,7 @@ private fun GroupConversationDetailsContent(
deleteGroupDialogState.dismiss()
leaveGroupDialogState.dismiss()
clearConversationDialogState.dismiss()
archiveConversationDialogState.dismiss()
}
WireScaffold(
topBar = {
Expand Down Expand Up @@ -361,10 +362,12 @@ private fun GroupConversationDetailsContent(
addConversationToFavourites = bottomSheetEventsHandler::onAddConversationToFavourites,
moveConversationToFolder = bottomSheetEventsHandler::onMoveConversationToFolder,
updateConversationArchiveStatus = {
conversationSheetContent?.let {
// Only show the confirmation dialog if the conversation is not archived
if (!it.isArchived) {
archiveConversationDialogState.show(it)
} else {
bottomSheetEventsHandler.updateConversationArchiveStatus(
conversationId = it.conversationId,
shouldArchive = !it.isArchived,
dialogState = it,
onMessage = closeBottomSheetAndShowSnackbarMessage
)
}
Expand Down Expand Up @@ -394,7 +397,14 @@ private fun GroupConversationDetailsContent(
dialogState = clearConversationDialogState,
isLoading = isLoading,
onClearConversationContent = {
bottomSheetEventsHandler.onClearConversationContent(it, closeBottomSheetAndShowSnackbarMessage)
bottomSheetEventsHandler.onClearConversationContent(dialogState = it, onMessage = closeBottomSheetAndShowSnackbarMessage)
}
)

ArchiveConversationDialog(
dialogState = archiveConversationDialogState,
onArchiveButtonClicked = {
bottomSheetEventsHandler.updateConversationArchiveStatus(dialogState = it, onMessage = closeBottomSheetAndShowSnackbarMessage)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,15 +380,14 @@ class GroupConversationDetailsViewModel @Inject constructor(
}

override fun updateConversationArchiveStatus(
conversationId: ConversationId,
shouldArchive: Boolean,
dialogState: DialogState,
timestamp: Long,
onMessage: (UIText) -> Unit
) {
viewModelScope.launch {
val shouldArchive = dialogState.isArchived.not()
requestInProgress = true
val result =
withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, shouldArchive, timestamp) }
val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, shouldArchive, timestamp) }
requestInProgress = false
when (result) {
ArchiveStatusUpdateResult.Failure -> onMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ interface GroupConversationDetailsBottomSheetEventsHandler {
fun onAddConversationToFavourites(conversationId: ConversationId? = null)
fun onMoveConversationToFolder(conversationId: ConversationId? = null)
fun updateConversationArchiveStatus(
conversationId: ConversationId,
shouldArchive: Boolean,
dialogState: DialogState,
timestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds(),
onMessage: (UIText) -> Unit
)
Expand All @@ -53,8 +52,7 @@ interface GroupConversationDetailsBottomSheetEventsHandler {
override fun onAddConversationToFavourites(conversationId: ConversationId?) {}
override fun onMoveConversationToFolder(conversationId: ConversationId?) {}
override fun updateConversationArchiveStatus(
conversationId: ConversationId,
shouldArchive: Boolean,
dialogState: DialogState,
timestamp: Long,
onMessage: (UIText) -> Unit
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Date
import javax.inject.Inject

Expand Down Expand Up @@ -323,7 +322,7 @@ class ConversationListViewModel @Inject constructor(
}

fun blockUser(blockUserState: BlockUserDialogState) {
viewModelScope.launch(dispatcher.io()) {
viewModelScope.launch {
requestInProgress = true
val state = when (val result = blockUserUseCase(blockUserState.userId)) {
BlockUserResult.Success -> {
Expand All @@ -342,7 +341,7 @@ class ConversationListViewModel @Inject constructor(
}

fun unblockUser(userId: UserId) {
viewModelScope.launch(dispatcher.io()) {
viewModelScope.launch {
requestInProgress = true
when (val result = unblockUserUseCase(userId)) {
UnblockUserResult.Success -> {
Expand All @@ -362,11 +361,7 @@ class ConversationListViewModel @Inject constructor(
fun leaveGroup(leaveGroupState: GroupDialogState) {
viewModelScope.launch {
requestInProgress = true
val response = withContext(dispatcher.io()) {
leaveConversation(
leaveGroupState.conversationId
)
}
val response = leaveConversation(leaveGroupState.conversationId)
when (response) {
is RemoveMemberFromConversationUseCase.Result.Failure ->
homeSnackBarState.emit(HomeSnackbarState.LeaveConversationError)
Expand All @@ -382,7 +377,7 @@ class ConversationListViewModel @Inject constructor(
fun deleteGroup(groupDialogState: GroupDialogState) {
viewModelScope.launch {
requestInProgress = true
when (withContext(dispatcher.io()) { deleteTeamConversation(groupDialogState.conversationId) }) {
when (deleteTeamConversation(groupDialogState.conversationId)) {
is Result.Failure.GenericFailure -> homeSnackBarState.emit(HomeSnackbarState.DeleteConversationGroupError)
Result.Failure.NoTeamFailure -> homeSnackBarState.emit(HomeSnackbarState.DeleteConversationGroupError)
Result.Success -> homeSnackBarState.emit(
Expand Down Expand Up @@ -415,32 +410,30 @@ class ConversationListViewModel @Inject constructor(
fun moveConversationToFolder(id: String = "") {
}

fun moveConversationToArchive(
conversationId: ConversationId,
isArchiving: Boolean,
timestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds()
) {
viewModelScope.launch {
requestInProgress = true
val result = withContext(dispatcher.io()) { updateConversationArchivedStatus(conversationId, isArchiving, timestamp) }
requestInProgress = false
when (result) {
is ArchiveStatusUpdateResult.Failure -> {
homeSnackBarState.emit(HomeSnackbarState.UpdateArchivingStatusError(isArchiving))
}
fun moveConversationToArchive(dialogState: DialogState, timestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds()) =
with(dialogState) {
viewModelScope.launch {
val isArchiving = !isArchived
requestInProgress = true
val result = updateConversationArchivedStatus(conversationId, isArchiving, timestamp)
requestInProgress = false
when (result) {
is ArchiveStatusUpdateResult.Failure -> {
homeSnackBarState.emit(HomeSnackbarState.UpdateArchivingStatusError(isArchiving))
}

is ArchiveStatusUpdateResult.Success -> {
homeSnackBarState.emit(HomeSnackbarState.UpdateArchivingStatusSuccess(isArchiving))
is ArchiveStatusUpdateResult.Success -> {
homeSnackBarState.emit(HomeSnackbarState.UpdateArchivingStatusSuccess(isArchiving))
}
}
}
}
}

fun clearConversationContent(dialogState: DialogState) {
viewModelScope.launch {
requestInProgress = true
with(dialogState) {
val result = withContext(dispatcher.io()) { clearConversationContentUseCase(conversationId) }
val result = clearConversationContentUseCase(conversationId)
requestInProgress = false
clearContentSnackbarResult(result, conversationTypeDetail)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.common.bottomsheet.conversation.ConversationOptionNavigation
import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetContent
import com.wire.android.ui.common.bottomsheet.conversation.rememberConversationSheetState
import com.wire.android.ui.common.dialogs.ArchiveConversationDialog
import com.wire.android.ui.common.dialogs.BlockUserDialogContent
import com.wire.android.ui.common.dialogs.BlockUserDialogState
import com.wire.android.ui.common.dialogs.UnblockUserDialogContent
Expand Down Expand Up @@ -155,13 +156,7 @@ fun ConversationRouterHomeBridge(
},
addConversationToFavourites = viewModel::addConversationToFavourites,
moveConversationToFolder = viewModel::moveConversationToFolder,
updateConversationArchiveStatus = {
viewModel.moveConversationToArchive(
conversationId = it.conversationId,
isArchiving = !it.isArchived
)
onCloseBottomSheet()
},
updateConversationArchiveStatus = archiveConversationDialogState::show,
clearConversationContent = clearContentDialogState::show,
blockUser = blockUserDialogState::show,
unblockUser = unblockUserDialogState::show,
Expand Down Expand Up @@ -281,6 +276,11 @@ fun ConversationRouterHomeBridge(
onClearConversationContent = viewModel::clearConversationContent
)

ArchiveConversationDialog(
dialogState = archiveConversationDialogState,
onArchiveButtonClicked = viewModel::moveConversationToArchive
)

BackHandler(conversationItemType == ConversationItemType.SEARCH) {
closeSearch()
}
Expand All @@ -295,6 +295,7 @@ class ConversationRouterState(
val blockUserDialogState: VisibilityState<BlockUserDialogState>,
val unblockUserDialogState: VisibilityState<UnblockUserDialogState>,
val clearContentDialogState: VisibilityState<DialogState>,
val archiveConversationDialogState: VisibilityState<DialogState>,
requestInProgress: Boolean
) {

Expand Down Expand Up @@ -326,6 +327,7 @@ fun rememberConversationRouterState(
val blockUserDialogState = rememberVisibilityState<BlockUserDialogState>()
val unblockUserDialogState = rememberVisibilityState<UnblockUserDialogState>()
val clearContentDialogState = rememberVisibilityState<DialogState>()
val archiveConversationDialogState = rememberVisibilityState<DialogState>()

LaunchedEffect(Unit) {
homeSnackBarState.collect { onSnackBarStateChanged(it) }
Expand All @@ -343,7 +345,8 @@ fun rememberConversationRouterState(
blockUserDialogState,
unblockUserDialogState,
clearContentDialogState,
requestInProgress
archiveConversationDialogState,
requestInProgress,
)
}

Expand All @@ -354,6 +357,7 @@ fun rememberConversationRouterState(
blockUserDialogState.dismiss()
unblockUserDialogState.dismiss()
clearContentDialogState.dismiss()
archiveConversationDialogState.dismiss()
}

conversationRouterState.requestInProgress = requestInProgress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ fun OtherProfileScreenContent(
val unblockUserDialogState = rememberVisibilityState<UnblockUserDialogState>()
val removeMemberDialogState = rememberVisibilityState<RemoveConversationMemberState>()
val clearConversationDialogState = rememberVisibilityState<DialogState>()
val archivingConversationDialogState = rememberVisibilityState<DialogState>()
val getBottomSheetVisibility: () -> Boolean = remember(sheetState) { { sheetState.isVisible } }
val bottomSheetState = remember { OtherUserBottomSheetState() }
bottomSheetState.setContents(state.conversationSheetContent, state.groupState)
Expand Down Expand Up @@ -234,6 +235,7 @@ fun OtherProfileScreenContent(
unblockUserDialogState.dismiss()
removeMemberDialogState.dismiss()
clearConversationDialogState.dismiss()
archivingConversationDialogState.dismiss()
}

CollapsingTopBarScaffold(
Expand Down Expand Up @@ -283,6 +285,7 @@ fun OtherProfileScreenContent(
blockUser = blockUserDialogState::show,
unblockUser = unblockUserDialogState::show,
clearContent = clearConversationDialogState::show,
archivingStatusState = archivingConversationDialogState::show,
closeBottomSheet = closeBottomSheet,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ fun OtherUserProfileBottomSheetContent(
bottomSheetState: OtherUserBottomSheetState,
eventsHandler: OtherUserProfileBottomSheetEventsHandler,
clearContent: (DialogState) -> Unit,
archivingStatusState: (DialogState) -> Unit,
blockUser: (BlockUserDialogState) -> Unit,
unblockUser: (UnblockUserDialogState) -> Unit,
closeBottomSheet: () -> Unit,
Expand All @@ -54,10 +55,11 @@ fun OtherUserProfileBottomSheetContent(
addConversationToFavourites = eventsHandler::onAddConversationToFavourites,
moveConversationToFolder = eventsHandler::onMoveConversationToFolder,
updateConversationArchiveStatus = {
eventsHandler.onMoveConversationToArchive(
conversationId = it.conversationId,
isArchivingConversation = !it.isArchived
)
if (!it.isArchived) {
archivingStatusState(it)
} else {
eventsHandler.onMoveConversationToArchive(it.conversationId, isArchivingConversation = false)
}
},
clearConversationContent = clearContent,
blockUser = blockUser,
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -726,10 +726,14 @@
<string name="error_unblocking_user">User could not be unblocked</string>
<string name="delete_group_conversation_error">There was an error while deleting conversation</string>
<string name="error_limit_number_assets_imported_exceeded">You can only send up to 20 files at once</string>
<!-- Archiving -->
<string name="success_archiving_conversation">Conversation was archived</string>
<string name="success_unarchiving_conversation">Conversation was unarchived</string>
<string name="error_archiving_conversation">Conversation could not be archived</string>
<string name="error_unarchiving_conversation">Conversation could not be unarchived</string>
<string name="dialog_archive_conversation_title">Archive conversation?</string>
<string name="dialog_archive_conversation_description">The conversation will be moved to the archive section. You can still participate in the conversation and receive new activity, but the group will be muted. You can un-archive the conversation any time.</string>
<string name="dialog_archive_conversation_option">Archive</string>
<!-- Animation label -->
<string name="animation_label_message_compose_input_state_transition" translatable="false">MessageComposeInputState transition</string>
<string name="animation_label_typing_indicator_horizontal_transition" translatable="false">HorizontalBouncingWritingPen transition</string>
Expand Down
Loading

0 comments on commit 013245e

Please sign in to comment.