Skip to content

Commit

Permalink
feat: move to folder [WPB-14627] (#3787)
Browse files Browse the repository at this point in the history
  • Loading branch information
Garzas authored Jan 14, 2025
1 parent 2f1c38d commit 6ab51e6
Show file tree
Hide file tree
Showing 27 changed files with 545 additions and 64 deletions.
4 changes: 4 additions & 0 deletions app/src/main/kotlin/com/wire/android/di/ViewModelScoped.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ interface ScopedArgs {
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class ViewModelScopedPreview

interface AssistedViewModelFactory<VM : ViewModel, R : ScopedArgs> {
fun create(args: R): VM
}
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,9 @@ class ConversationModule {
@Provides
fun provideObserveUserFoldersUseCase(conversationScope: ConversationScope) =
conversationScope.observeUserFolders

@ViewModelScoped
@Provides
fun provideMoveConversationToFolderUseCase(conversationScope: ConversationScope) =
conversationScope.moveConversationToFolder
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ fun ConversationDetailsWithEvents.toConversationItem(
proteusVerificationStatus = conversationDetails.conversation.proteusVerificationStatus,
hasNewActivitiesToShow = hasNewActivitiesToShow,
searchQuery = searchQuery,
isFavorite = conversationDetails.isFavorite
isFavorite = conversationDetails.isFavorite,
folder = conversationDetails.folder
)
}

Expand Down Expand Up @@ -103,7 +104,8 @@ fun ConversationDetailsWithEvents.toConversationItem(
proteusVerificationStatus = conversationDetails.conversation.proteusVerificationStatus,
hasNewActivitiesToShow = hasNewActivitiesToShow,
searchQuery = searchQuery,
isFavorite = conversationDetails.isFavorite
isFavorite = conversationDetails.isFavorite,
folder = conversationDetails.folder
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ fun SelectableMenuBottomSheetItem(
.wrapContentHeight()
.wrapContentWidth()
.defaultMinSize(minHeight = dimensions().spacing48x)
.let { if (isSelectedItem(state)) it.background(MaterialTheme.wireColorScheme.secondaryButtonSelected) else it }
.background(
if (isSelectedItem(state)) {
MaterialTheme.wireColorScheme.secondaryButtonSelected
} else {
MaterialTheme.wireColorScheme.surface
}
)
.clickable(onItemClick)
.semantics { if (isSelectedItem(state)) selected = true }
.padding(vertical = dimensions().spacing12x, horizontal = dimensions().spacing16x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import com.wire.android.R
import com.wire.android.model.ImageAsset.UserAvatarAsset
import com.wire.android.ui.common.dialogs.BlockUserDialogState
import com.wire.android.ui.common.dialogs.UnblockUserDialogState
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.kalium.logic.data.conversation.Conversation
import com.wire.kalium.logic.data.conversation.ConversationFolder
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.user.UserId
Expand All @@ -38,7 +40,7 @@ fun ConversationSheetContent(
conversationSheetState: ConversationSheetState,
onMutingConversationStatusChange: () -> Unit,
changeFavoriteState: (GroupDialogState, addToFavorite: Boolean) -> Unit,
moveConversationToFolder: () -> Unit,
moveConversationToFolder: ((ConversationFoldersNavArgs) -> Unit)?,
updateConversationArchiveStatus: (DialogState) -> Unit,
clearConversationContent: (DialogState) -> Unit,
blockUser: (BlockUserDialogState) -> Unit,
Expand All @@ -56,8 +58,7 @@ fun ConversationSheetContent(
ConversationMainSheetContent(
conversationSheetContent = conversationSheetState.conversationSheetContent!!,
changeFavoriteState = changeFavoriteState,
// TODO(profile): enable when implemented
// moveConversationToFolder = moveConversationToFolder,
moveConversationToFolder = moveConversationToFolder,
updateConversationArchiveStatus = updateConversationArchiveStatus,
clearConversationContent = clearConversationContent,
blockUserClick = blockUser,
Expand Down Expand Up @@ -128,6 +129,7 @@ data class ConversationSheetContent(
val proteusVerificationStatus: Conversation.VerificationStatus,
val isUnderLegalHold: Boolean,
val isFavorite: Boolean?,
val folder: ConversationFolder?,
val isDeletingConversationLocallyRunning: Boolean
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ fun rememberConversationSheetState(
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = isFavorite,
folder = folder,
isDeletingConversationLocallyRunning = isConversationDeletionLocallyRunning
)
}
Expand Down Expand Up @@ -108,6 +109,7 @@ fun rememberConversationSheetState(
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = isFavorite,
folder = folder,
isDeletingConversationLocallyRunning = false
)
}
Expand All @@ -130,6 +132,7 @@ fun rememberConversationSheetState(
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = null,
folder = null,
isDeletingConversationLocallyRunning = false
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.wire.android.ui.common.conversationColor
import com.wire.android.ui.common.dialogs.BlockUserDialogState
import com.wire.android.ui.common.dialogs.UnblockUserDialogState
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavArgs
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
Expand All @@ -59,8 +60,7 @@ import com.wire.kalium.logic.data.user.ConnectionState
internal fun ConversationMainSheetContent(
conversationSheetContent: ConversationSheetContent,
changeFavoriteState: (dialogState: GroupDialogState, addToFavorite: Boolean) -> Unit,
// TODO(profile): enable when implemented
// moveConversationToFolder: () -> Unit,
moveConversationToFolder: ((ConversationFoldersNavArgs) -> Unit)?,
updateConversationArchiveStatus: (DialogState) -> Unit,
clearConversationContent: (DialogState) -> Unit,
blockUserClick: (BlockUserDialogState) -> Unit,
Expand Down Expand Up @@ -142,19 +142,28 @@ internal fun ConversationMainSheetContent(
}
}
}
// TODO(profile): enable when implemented
// add {
// MenuBottomSheetItem(
// icon = {
// MenuItemIcon(
// id = R.drawable.ic_folder,
// contentDescription = stringResource(R.string.content_description_move_to_folder),
// )
// },
// title = stringResource(R.string.label_move_to_folder),
// onItemClick = moveConversationToFolder
// )
// }
if (moveConversationToFolder != null) {
add {
MenuBottomSheetItem(
leading = {
MenuItemIcon(
id = R.drawable.ic_folder,
contentDescription = null,
)
},
title = stringResource(R.string.label_move_to_folder),
onItemClick = {
moveConversationToFolder(
ConversationFoldersNavArgs(
conversationId = conversationSheetContent.conversationId,
conversationName = conversationSheetContent.title,
currentFolderId = conversationSheetContent.folder?.id
)
)
}
)
}
}
add {
MenuBottomSheetItem(
leading = {
Expand Down
22 changes: 18 additions & 4 deletions app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import com.ramcosta.composedestinations.result.NavResult
import com.ramcosta.composedestinations.result.ResultRecipient
import com.wire.android.R
import com.wire.android.appLogger
import com.wire.android.di.hiltViewModelScoped
import com.wire.android.navigation.HomeDestination
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
Expand All @@ -79,13 +78,15 @@ import com.wire.android.ui.common.dimensions
import com.wire.android.ui.common.snackbar.LocalSnackbarHostState
import com.wire.android.ui.common.topappbar.search.SearchTopBar
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.destinations.ConversationFoldersScreenDestination
import com.wire.android.ui.destinations.ConversationScreenDestination
import com.wire.android.ui.destinations.NewConversationSearchPeopleScreenDestination
import com.wire.android.ui.destinations.OtherUserProfileScreenDestination
import com.wire.android.ui.destinations.SelfUserProfileScreenDestination
import com.wire.android.ui.home.conversations.PermissionPermanentlyDeniedDialogState
import com.wire.android.ui.home.conversations.details.GroupConversationActionType
import com.wire.android.ui.home.conversations.details.GroupConversationDetailsNavBackArgs
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavBackArgs
import com.wire.android.ui.home.conversations.folder.ConversationFoldersStateArgs
import com.wire.android.ui.home.conversations.folder.ConversationFoldersVM
import com.wire.android.ui.home.conversations.folder.ConversationFoldersVMImpl
Expand All @@ -108,16 +109,19 @@ fun HomeScreen(
navigator: Navigator,
groupDetailsScreenResultRecipient: ResultRecipient<ConversationScreenDestination, GroupConversationDetailsNavBackArgs>,
otherUserProfileScreenResultRecipient: ResultRecipient<OtherUserProfileScreenDestination, String>,
conversationFoldersScreenResultRecipient:
ResultRecipient<ConversationFoldersScreenDestination, ConversationFoldersNavBackArgs>,
homeViewModel: HomeViewModel = hiltViewModel(),
appSyncViewModel: AppSyncViewModel = hiltViewModel(),
homeDrawerViewModel: HomeDrawerViewModel = hiltViewModel(),
analyticsUsageViewModel: AnalyticsUsageViewModel = hiltViewModel(),
foldersViewModel: ConversationFoldersVM =
hiltViewModelScoped<ConversationFoldersVMImpl, ConversationFoldersVM, ConversationFoldersStateArgs>(
ConversationFoldersStateArgs
hiltViewModel<ConversationFoldersVMImpl, ConversationFoldersVMImpl.Factory>(
creationCallback = { it.create(ConversationFoldersStateArgs(null)) }
)
) {
homeViewModel.checkRequirements { it.navigate(navigator::navigate) }
val context = LocalContext.current

val homeScreenState = rememberHomeScreenState(navigator)
val notificationsPermissionDeniedDialogState = rememberVisibilityState<PermissionPermanentlyDeniedDialogState>()
Expand All @@ -137,7 +141,6 @@ fun HomeScreen(
)

val lifecycleOwner = LocalLifecycleOwner.current
val context = LocalContext.current
val snackbarHostState = LocalSnackbarHostState.current
val coroutineScope = rememberCoroutineScope()

Expand Down Expand Up @@ -237,6 +240,17 @@ fun HomeScreen(
}
}

conversationFoldersScreenResultRecipient.onNavResult { result ->
when (result) {
NavResult.Canceled -> {}
is NavResult.Value -> {
coroutineScope.launch {
snackbarHostState.showSnackbar(result.value.message)
}
}
}
}

PermissionPermanentlyDeniedDialog(
dialogState = notificationsPermissionDeniedDialogState,
hideDialog = notificationsPermissionDeniedDialogState::dismiss
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
import com.wire.android.ui.common.topappbar.WireTopAppBarTitle
import com.wire.android.ui.common.visbility.rememberVisibilityState
import com.wire.android.ui.destinations.AddMembersSearchScreenDestination
import com.wire.android.ui.destinations.ConversationFoldersScreenDestination
import com.wire.android.ui.destinations.ConversationMediaScreenDestination
import com.wire.android.ui.destinations.EditConversationNameScreenDestination
import com.wire.android.ui.destinations.EditGuestAccessScreenDestination
Expand All @@ -111,6 +112,8 @@ import com.wire.android.ui.home.conversations.details.options.GroupConversationO
import com.wire.android.ui.home.conversations.details.participants.GroupConversationParticipants
import com.wire.android.ui.home.conversations.details.participants.GroupConversationParticipantsState
import com.wire.android.ui.home.conversations.details.participants.model.UIParticipant
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavArgs
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavBackArgs
import com.wire.android.ui.home.conversationslist.model.DialogState
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.ui.legalhold.dialog.subject.LegalHoldSubjectConversationDialog
Expand Down Expand Up @@ -138,6 +141,8 @@ fun GroupConversationDetailsScreen(
navigator: Navigator,
resultNavigator: ResultBackNavigator<GroupConversationDetailsNavBackArgs>,
groupConversationDetailResultRecipient: ResultRecipient<EditConversationNameScreenDestination, Boolean>,
conversationFoldersScreenResultRecipient:
ResultRecipient<ConversationFoldersScreenDestination, ConversationFoldersNavBackArgs>,
viewModel: GroupConversationDetailsViewModel = hiltViewModel()
) {
val scope = rememberCoroutineScope()
Expand Down Expand Up @@ -246,8 +251,10 @@ fun GroupConversationDetailsScreen(
onConversationMediaClick = onConversationMediaClick,
isAbandonedOneOnOneConversation = viewModel.conversationSheetContent?.isAbandonedOneOnOneConversation(
viewModel.groupParticipantsState.data.allCount
) ?: false

) ?: false,
onMoveToFolder = {
navigator.navigate(NavigationCommand(ConversationFoldersScreenDestination(it)))
}
)

val tryAgainSnackBarMessage = stringResource(id = R.string.error_unknown_message)
Expand All @@ -270,6 +277,17 @@ fun GroupConversationDetailsScreen(
}
}
}

conversationFoldersScreenResultRecipient.onNavResult { result ->
when (result) {
NavResult.Canceled -> {}
is NavResult.Value -> {
scope.launch {
snackbarHostState.showSnackbar(result.value.message)
}
}
}
}
}

@OptIn(ExperimentalFoundationApi::class)
Expand All @@ -290,6 +308,7 @@ private fun GroupConversationDetailsContent(
isAbandonedOneOnOneConversation: Boolean,
onSearchConversationMessagesClick: () -> Unit,
onConversationMediaClick: () -> Unit,
onMoveToFolder: (ConversationFoldersNavArgs) -> Unit = {},
initialPageIndex: GroupConversationDetailsTabItem = GroupConversationDetailsTabItem.OPTIONS,
changeConversationFavoriteStateViewModel: ChangeConversationFavoriteVM =
hiltViewModelScoped<ChangeConversationFavoriteVMImpl, ChangeConversationFavoriteVM, ChangeConversationFavoriteStateArgs>(
Expand Down Expand Up @@ -473,7 +492,7 @@ private fun GroupConversationDetailsContent(
}
},
changeFavoriteState = changeConversationFavoriteStateViewModel::changeFavoriteState,
moveConversationToFolder = bottomSheetEventsHandler::onMoveConversationToFolder,
moveConversationToFolder = onMoveToFolder,
updateConversationArchiveStatus = {
// Only show the confirmation dialog if the conversation is not archived
if (!it.isArchived) {
Expand Down Expand Up @@ -611,6 +630,7 @@ fun PreviewGroupConversationDetails() {
isUnderLegalHold = false,
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isFavorite = false,
folder = null,
isDeletingConversationLocallyRunning = false
),
bottomSheetEventsHandler = GroupConversationDetailsBottomSheetEventsHandler.PREVIEW,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.feature.user.IsMLSEnabledUseCase
import com.wire.kalium.logic.functional.getOrNull
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -122,16 +123,17 @@ class GroupConversationDetailsViewModel @Inject constructor(
observeConversationDetails()
}

private suspend fun groupDetailsFlow(): Flow<ConversationDetails.Group> = observeConversationDetails(conversationId)
.filterIsInstance<ObserveConversationDetailsUseCase.Result.Success>()
.map { it.conversationDetails }
.filterIsInstance<ConversationDetails.Group>()
.distinctUntilChanged()
.flowOn(dispatcher.io())

private fun observeConversationDetails() {
viewModelScope.launch {
val groupDetailsFlow =
observeConversationDetails(conversationId)
.filterIsInstance<ObserveConversationDetailsUseCase.Result.Success>()
.map { it.conversationDetails }
.filterIsInstance<ConversationDetails.Group>()
.distinctUntilChanged()
.flowOn(dispatcher.io())
.shareIn(this, SharingStarted.WhileSubscribed(), 1)
val groupDetailsFlow = groupDetailsFlow()
.shareIn(this, SharingStarted.WhileSubscribed(), 1)

val selfTeam = getSelfTeam().getOrNull()
val selfUser = observerSelfUser().first()
Expand All @@ -141,7 +143,6 @@ class GroupConversationDetailsViewModel @Inject constructor(
groupDetailsFlow,
observeSelfDeletionTimerSettingsForConversation(conversationId, considerSelfUserSettings = false),
) { groupDetails, selfDeletionTimer ->

val isSelfInOwnerTeam = selfTeam?.id != null && selfTeam.id == groupDetails.conversation.teamId?.value
val isSelfExternalMember = selfUser.userType == UserType.EXTERNAL
val isSelfAnAdmin = groupDetails.selfRole == Conversation.Member.Role.Admin
Expand All @@ -163,6 +164,7 @@ class GroupConversationDetailsViewModel @Inject constructor(
proteusVerificationStatus = groupDetails.conversation.proteusVerificationStatus,
isUnderLegalHold = groupDetails.conversation.legalHoldStatus.showLegalHoldIndicator(),
isFavorite = groupDetails.isFavorite,
folder = groupDetails.folder,
isDeletingConversationLocallyRunning = false
)

Expand Down
Loading

0 comments on commit 6ab51e6

Please sign in to comment.