Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add confirmation dialog archiving [WPB-4434] #2300

Merged
merged 5 commits into from
Oct 5, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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.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 @@
}

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 @@
}

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 @@
fun leaveGroup(leaveGroupState: GroupDialogState) {
viewModelScope.launch {
requestInProgress = true
val response = withContext(dispatcher.io()) {
leaveConversation(
leaveGroupState.conversationId
)
}
val response = leaveConversation(leaveGroupState.conversationId)

Check warning on line 364 in app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt#L364

Added line #L364 was not covered by tests
when (response) {
is RemoveMemberFromConversationUseCase.Result.Failure ->
homeSnackBarState.emit(HomeSnackbarState.LeaveConversationError)
Expand All @@ -382,7 +377,7 @@
fun deleteGroup(groupDialogState: GroupDialogState) {
viewModelScope.launch {
requestInProgress = true
when (withContext(dispatcher.io()) { deleteTeamConversation(groupDialogState.conversationId) }) {
when (deleteTeamConversation(groupDialogState.conversationId)) {

Check warning on line 380 in app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt#L380

Added line #L380 was not covered by tests
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 @@
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()) =

Check warning on line 413 in app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt#L413

Added line #L413 was not covered by tests
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)

Check warning on line 436 in app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationListViewModel.kt#L436

Added line #L436 was not covered by tests
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.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 @@
},
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 @@
onClearConversationContent = viewModel::clearConversationContent
)

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

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

Check warning on line 298 in app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/kotlin/com/wire/android/ui/home/conversationslist/ConversationRouter.kt#L298

Added line #L298 was not covered by tests
requestInProgress: Boolean
) {

Expand Down Expand Up @@ -326,6 +327,7 @@
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 @@
blockUserDialogState,
unblockUserDialogState,
clearContentDialogState,
requestInProgress
archiveConversationDialogState,
requestInProgress,
)
}

Expand All @@ -354,6 +357,7 @@
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