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: Delete group option on Leaving it WPB-14938 #3809

Merged
merged 10 commits into from
Jan 23, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavArgs
import com.wire.android.ui.home.conversationslist.model.BlockingState
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.kalium.logic.data.conversation.Conversation
import com.wire.kalium.logic.data.conversation.ConversationFolder
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
Expand All @@ -46,7 +47,7 @@ fun ConversationSheetContent(
clearConversationContent: (DialogState) -> Unit,
blockUser: (BlockUserDialogState) -> Unit,
unblockUser: (UnblockUserDialogState) -> Unit,
leaveGroup: (GroupDialogState) -> Unit,
leaveGroup: (LeaveGroupDialogState) -> Unit,
deleteGroup: (GroupDialogState) -> Unit,
deleteGroupLocally: (GroupDialogState) -> Unit,
isBottomSheetVisible: () -> Boolean = { true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import com.wire.android.ui.home.conversationslist.common.GroupConversationAvatar
import com.wire.android.ui.home.conversationslist.model.BlockingState
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.android.ui.home.conversationslist.model.getMutedStatusTextResource
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.ui.theme.wireTypography
Expand All @@ -68,7 +69,7 @@ internal fun ConversationMainSheetContent(
clearConversationContent: (DialogState) -> Unit,
blockUserClick: (BlockUserDialogState) -> Unit,
unblockUserClick: (UnblockUserDialogState) -> Unit,
leaveGroup: (GroupDialogState) -> Unit,
leaveGroup: (LeaveGroupDialogState) -> Unit,
deleteGroup: (GroupDialogState) -> Unit,
deleteGroupLocally: (GroupDialogState) -> Unit,
navigateToNotification: () -> Unit
Expand Down Expand Up @@ -294,7 +295,7 @@ internal fun ConversationMainSheetContent(
title = stringResource(R.string.label_leave_group),
onItemClick = {
leaveGroup(
GroupDialogState(
LeaveGroupDialogState(
conversationSheetContent.conversationId,
conversationSheetContent.title
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavBackA
import com.wire.android.ui.home.conversations.folder.RemoveConversationFromFolderVM
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.android.ui.legalhold.dialog.subject.LegalHoldSubjectConversationDialog
import com.wire.android.ui.theme.WireTheme
import com.wire.android.ui.theme.wireColorScheme
Expand Down Expand Up @@ -305,7 +306,7 @@ private fun GroupConversationDetailsContent(
onEditGuestAccess: () -> Unit,
onEditSelfDeletingMessages: () -> Unit,
onEditGroupName: () -> Unit,
onLeaveGroup: (GroupDialogState) -> Unit,
onLeaveGroup: (LeaveGroupDialogState) -> Unit,
onDeleteGroup: (GroupDialogState) -> Unit,
groupParticipantsState: GroupConversationParticipantsState,
isLoading: Boolean,
Expand Down Expand Up @@ -343,7 +344,7 @@ private fun GroupConversationDetailsContent(
val getBottomSheetVisibility: () -> Boolean = remember(sheetState) { { sheetState.isVisible } }

val deleteGroupDialogState = rememberVisibilityState<GroupDialogState>()
val leaveGroupDialogState = rememberVisibilityState<GroupDialogState>()
val leaveGroupDialogState = rememberVisibilityState<LeaveGroupDialogState>()
val clearConversationDialogState = rememberVisibilityState<DialogState>()
val archiveConversationDialogState = rememberVisibilityState<DialogState>()
val legalHoldSubjectDialogState = rememberVisibilityState<Unit>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.work.WorkManager
import com.wire.android.R
import com.wire.android.appLogger
import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetContent
Expand All @@ -33,11 +34,14 @@ import com.wire.android.ui.home.conversations.details.participants.GroupConversa
import com.wire.android.ui.home.conversations.details.participants.usecase.ObserveParticipantsForConversationUseCase
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.android.ui.home.conversationslist.showLegalHoldIndicator
import com.wire.android.ui.navArgs
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.android.util.ui.UIText
import com.wire.android.util.uiText
import com.wire.android.workmanager.worker.ConversationDeletionLocallyStatus
import com.wire.android.workmanager.worker.enqueueConversationDeletionLocally
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.conversation.Conversation
import com.wire.kalium.logic.data.conversation.ConversationDetails
Expand All @@ -62,8 +66,8 @@ import com.wire.kalium.logic.feature.team.DeleteTeamConversationUseCase
import com.wire.kalium.logic.feature.team.GetUpdatedSelfTeamUseCase
import com.wire.kalium.logic.feature.team.Result
import com.wire.kalium.logic.feature.user.GetDefaultProtocolUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.logic.feature.user.IsMLSEnabledUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import com.wire.kalium.logic.functional.getOrNull
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -102,6 +106,7 @@ class GroupConversationDetailsViewModel @Inject constructor(
override val savedStateHandle: SavedStateHandle,
private val isMLSEnabled: IsMLSEnabledUseCase,
private val getDefaultProtocol: GetDefaultProtocolUseCase,
private val workManager: WorkManager,
refreshUsersWithoutMetadata: RefreshUsersWithoutMetadataUseCase,
) : GroupConversationParticipantsViewModel(
savedStateHandle, observeConversationMembers, refreshUsersWithoutMetadata
Expand Down Expand Up @@ -190,7 +195,7 @@ class GroupConversationDetailsViewModel @Inject constructor(
}

fun leaveGroup(
leaveGroupState: GroupDialogState,
leaveGroupState: LeaveGroupDialogState,
onSuccess: () -> Unit,
onFailure: (UIText) -> Unit
) {
Expand All @@ -204,7 +209,13 @@ class GroupConversationDetailsViewModel @Inject constructor(
}
when (response) {
is RemoveMemberFromConversationUseCase.Result.Failure -> onFailure(response.cause.uiText())
RemoveMemberFromConversationUseCase.Result.Success -> onSuccess()
RemoveMemberFromConversationUseCase.Result.Success -> {
if (leaveGroupState.shouldDelete) {
deleteGroupLocally(leaveGroupState, onSuccess, onFailure)
} else {
onSuccess()
}
}
}
requestInProgress = false
}
Expand All @@ -226,6 +237,29 @@ class GroupConversationDetailsViewModel @Inject constructor(
}
}

fun deleteGroupLocally(
groupDialogState: GroupDialogState,
onSuccess: () -> Unit,
onFailure: (UIText) -> Unit
) {
viewModelScope.launch {
workManager.enqueueConversationDeletionLocally(groupDialogState.conversationId)
.collect { status ->
when (status) {
ConversationDeletionLocallyStatus.SUCCEEDED -> onSuccess()

ConversationDeletionLocallyStatus.FAILED ->
onFailure(UIText.StringResource(R.string.delete_group_conversation_error))

ConversationDeletionLocallyStatus.RUNNING,
ConversationDeletionLocallyStatus.IDLE -> {
// nop
}
}
}
}
}

fun onServicesUpdate(enableServices: Boolean) {
updateState(groupOptionsState.value.copy(loadingServicesOption = true, isServicesAllowed = enableServices))
when (enableServices) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,31 @@

package com.wire.android.ui.home.conversations.details.menu

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
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.WireLabelledCheckbox
import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.ui.common.visbility.VisibilityState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState

@Composable
internal fun LeaveConversationGroupDialog(
dialogState: VisibilityState<GroupDialogState>,
dialogState: VisibilityState<LeaveGroupDialogState>,
isLoading: Boolean,
onLeaveGroup: (GroupDialogState) -> Unit,
onLeaveGroup: (LeaveGroupDialogState) -> Unit,
) {
VisibilityState(dialogState) {
VisibilityState(dialogState) { state ->
WireDialog(
title = stringResource(id = R.string.leave_group_conversation_dialog_title, it.conversationName),
title = stringResource(id = R.string.leave_group_conversation_dialog_title, state.conversationName),
text = stringResource(id = R.string.leave_group_conversation_dialog_description),
buttonsHorizontalAlignment = true,
onDismiss = dialogState::dismiss,
Expand All @@ -47,7 +52,7 @@ internal fun LeaveConversationGroupDialog(
state = WireButtonState.Default
),
optionButton1Properties = WireDialogButtonProperties(
onClick = { onLeaveGroup(it) },
onClick = { onLeaveGroup(state) },
text = stringResource(id = R.string.label_leave),
type = WireDialogButtonType.Primary,
state =
Expand All @@ -57,6 +62,14 @@ internal fun LeaveConversationGroupDialog(
WireButtonState.Error,
loading = isLoading
)
)
) {
WireLabelledCheckbox(
label = stringResource(R.string.leave_group_conversation_dialog_delete_fully_check),
checked = state.shouldDelete,
onCheckClicked = remember { { dialogState.show(state.copy(shouldDelete = it)) } },
horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import com.wire.android.ui.home.conversationslist.model.ConversationItem
import com.wire.android.ui.home.conversationslist.model.ConversationsSource
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.android.workmanager.worker.ConversationDeletionLocallyStatus
import com.wire.android.workmanager.worker.enqueueConversationDeletionLocally
Expand Down Expand Up @@ -115,7 +116,7 @@ interface ConversationListViewModel {
fun deleteGroup(groupDialogState: GroupDialogState) {}
fun deleteGroupLocally(groupDialogState: GroupDialogState) {}
fun observeIsDeletingConversationLocally(conversationId: ConversationId): Flow<Boolean>
fun leaveGroup(leaveGroupState: GroupDialogState) {}
fun leaveGroup(leaveGroupState: LeaveGroupDialogState) {}
fun clearConversationContent(dialogState: DialogState) {}
fun muteConversation(conversationId: ConversationId?, mutedConversationStatus: MutedConversationStatus) {}
fun moveConversationToFolder() {}
Expand Down Expand Up @@ -359,7 +360,7 @@ class ConversationListViewModelImpl @AssistedInject constructor(
}
}

override fun leaveGroup(leaveGroupState: GroupDialogState) {
override fun leaveGroup(leaveGroupState: LeaveGroupDialogState) {
viewModelScope.launch {
_requestInProgress = true
val response = leaveConversation(leaveGroupState.conversationId)
Expand All @@ -368,7 +369,11 @@ class ConversationListViewModelImpl @AssistedInject constructor(
_infoMessage.emit(HomeSnackBarMessage.LeaveConversationError)

RemoveMemberFromConversationUseCase.Result.Success -> {
_infoMessage.emit(HomeSnackBarMessage.LeftConversationSuccess)
if (leaveGroupState.shouldDelete) {
deleteGroupLocally(leaveGroupState)
} else {
_infoMessage.emit(HomeSnackBarMessage.LeftConversationSuccess)
}
}
}
_requestInProgress = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ import com.wire.android.ui.common.visbility.VisibilityState
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.home.conversationslist.model.LeaveGroupDialogState

@Suppress("LongParameterList")
class ConversationsDialogsState(
val leaveGroupDialogState: VisibilityState<GroupDialogState>,
val leaveGroupDialogState: VisibilityState<LeaveGroupDialogState>,
val deleteGroupDialogState: VisibilityState<GroupDialogState>,
val deleteGroupLocallyDialogState: VisibilityState<GroupDialogState>,
val blockUserDialogState: VisibilityState<BlockUserDialogState>,
Expand All @@ -47,7 +48,7 @@ class ConversationsDialogsState(
@Composable
fun rememberConversationsDialogsState(requestInProgress: Boolean): ConversationsDialogsState {

val leaveGroupDialogState = rememberVisibilityState<GroupDialogState>()
val leaveGroupDialogState = rememberVisibilityState<LeaveGroupDialogState>()
val deleteGroupDialogState = rememberVisibilityState<GroupDialogState>()
val deleteGroupLocallyDialogState = rememberVisibilityState<GroupDialogState>()
val blockUserDialogState = rememberVisibilityState<BlockUserDialogState>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ package com.wire.android.ui.home.conversationslist.model
import com.wire.android.ui.common.bottomsheet.conversation.ConversationTypeDetail
import com.wire.kalium.logic.data.id.ConversationId

data class GroupDialogState(
val conversationId: ConversationId,
val conversationName: String
open class GroupDialogState(
open val conversationId: ConversationId,
open val conversationName: String
)

data class DialogState(
Expand All @@ -33,3 +33,9 @@ data class DialogState(
val isArchived: Boolean,
val isMember: Boolean
)

data class LeaveGroupDialogState(
override val conversationId: ConversationId,
override val conversationName: String,
val shouldDelete: Boolean = false
) : GroupDialogState(conversationId, conversationName)
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@
<string name="leave_group_conversation_menu_item">Leave Group…</string>
<string name="leave_group_conversation_dialog_title">Leave “%s”?</string>
<string name="leave_group_conversation_dialog_description">You will then no longer be able to send or read messages in this group on any device.</string>
<string name="leave_group_conversation_dialog_delete_fully_check">Delete the group and its content for me on all my devices</string>
<string name="delete_group_conversation_menu_item">Delete Group…</string>
<string name="delete_group_conversation_dialog_title">Remove “%s”?</string>
<string name="delete_group_conversation_dialog_description">The group will be removed from your conversations list on all devices. You will no longer be able to access the group and its content.</string>
Expand Down
2 changes: 1 addition & 1 deletion kalium
Loading