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 and remove conversation favorite [WPB-11639] #3653

Merged
merged 8 commits into from
Nov 25, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,14 @@ class ConversationModule {
@Provides
fun provideGetFavoriteFolderUseCase(conversationScope: ConversationScope) =
conversationScope.getFavoriteFolder

@ViewModelScoped
@Provides
fun provideAddConversationToFavoritesUseCase(conversationScope: ConversationScope) =
conversationScope.addConversationToFavorites

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

Expand Down Expand Up @@ -101,6 +102,7 @@ fun ConversationDetailsWithEvents.toConversationItem(
proteusVerificationStatus = conversationDetails.conversation.proteusVerificationStatus,
hasNewActivitiesToShow = hasNewActivitiesToShow,
searchQuery = searchQuery,
isFavorite = conversationDetails.isFavorite
)
}

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/kotlin/com/wire/android/model/SnackBarMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ interface SnackBarMessage {
val uiText: UIText
val actionLabel: UIText? get() = null
}

data class DefaultSnackBarMessage(
override val uiText: UIText,
override val actionLabel: UIText? = null
) : SnackBarMessage

fun UIText.asSnackBarMessage(actionLabel: UIText? = null): SnackBarMessage = DefaultSnackBarMessage(this, actionLabel)
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import com.wire.kalium.logic.data.user.UserId
fun ConversationSheetContent(
conversationSheetState: ConversationSheetState,
onMutingConversationStatusChange: () -> Unit,
addConversationToFavourites: () -> Unit,
changeFavoriteState: (GroupDialogState, addToFavorite: Boolean) -> Unit,
moveConversationToFolder: () -> Unit,
updateConversationArchiveStatus: (DialogState) -> Unit,
clearConversationContent: (DialogState) -> Unit,
Expand All @@ -54,9 +54,8 @@ fun ConversationSheetContent(
ConversationOptionNavigation.Home -> {
ConversationMainSheetContent(
conversationSheetContent = conversationSheetState.conversationSheetContent!!,
changeFavoriteState = changeFavoriteState,
// TODO(profile): enable when implemented
//
// addConversationToFavourites = addConversationToFavourites,
// moveConversationToFolder = moveConversationToFolder,
updateConversationArchiveStatus = updateConversationArchiveStatus,
clearConversationContent = clearConversationContent,
Expand Down Expand Up @@ -125,6 +124,7 @@ data class ConversationSheetContent(
val mlsVerificationStatus: Conversation.VerificationStatus,
val proteusVerificationStatus: Conversation.VerificationStatus,
val isUnderLegalHold: Boolean,
val isFavorite: Boolean?
) {

private val isSelfUserMember: Boolean get() = selfRole != null
Expand All @@ -147,9 +147,9 @@ data class ConversationSheetContent(
fun canUnblockUser(): Boolean =
conversationTypeDetail is ConversationTypeDetail.Private && conversationTypeDetail.blockingState == BlockingState.BLOCKED

fun canAddToFavourite(): Boolean =
(conversationTypeDetail is ConversationTypeDetail.Private && conversationTypeDetail.blockingState != BlockingState.BLOCKED)
|| conversationTypeDetail is ConversationTypeDetail.Group
fun canAddToFavourite(): Boolean = isFavorite != null &&
((conversationTypeDetail is ConversationTypeDetail.Private && conversationTypeDetail.blockingState != BlockingState.BLOCKED)
|| conversationTypeDetail is ConversationTypeDetail.Group)

fun isAbandonedOneOnOneConversation(participantsCount: Int): Boolean = title.isEmpty() && participantsCount == 1
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ fun rememberConversationSheetState(
protocol = Conversation.ProtocolInfo.Proteus,
mlsVerificationStatus = Conversation.VerificationStatus.VERIFIED,
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = isFavorite
)
}
}
Expand All @@ -102,7 +103,8 @@ fun rememberConversationSheetState(
protocol = Conversation.ProtocolInfo.Proteus,
mlsVerificationStatus = Conversation.VerificationStatus.VERIFIED,
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = isFavorite
)
}
}
Expand All @@ -122,7 +124,8 @@ fun rememberConversationSheetState(
protocol = Conversation.ProtocolInfo.Proteus,
mlsVerificationStatus = Conversation.VerificationStatus.VERIFIED,
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = showLegalHoldIndicator
isUnderLegalHold = showLegalHoldIndicator,
isFavorite = null
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@ import com.wire.android.ui.theme.wireTypography
import com.wire.kalium.logic.data.conversation.MutedConversationStatus
import com.wire.kalium.logic.data.user.ConnectionState

// items cannot be simplified
@Suppress("CyclomaticComplexMethod")
@Composable
internal fun ConversationMainSheetContent(
conversationSheetContent: ConversationSheetContent,
// TODO(profile): enable when implemented
// addConversationToFavourites: () -> Unit,
// moveConversationToFolder: () -> Unit,
changeFavoriteState: (dialogState: GroupDialogState, addToFavorite: Boolean) -> Unit,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: move the // TODO(profile): enable when implemented line below this one so that it's right next to commented line // moveConversationToFolder: () -> Unit,

// TODO(profile): enable when implemented
// moveConversationToFolder: () -> Unit,
updateConversationArchiveStatus: (DialogState) -> Unit,
clearConversationContent: (DialogState) -> Unit,
blockUserClick: (BlockUserDialogState) -> Unit,
Expand Down Expand Up @@ -108,21 +110,38 @@ internal fun ConversationMainSheetContent(
)
}
}

if (conversationSheetContent.canAddToFavourite() && !conversationSheetContent.isArchived) {
conversationSheetContent.isFavorite?.let { isFavorite ->
add {
MenuBottomSheetItem(
title = stringResource(
if (isFavorite) {
R.string.label_remove_from_favourites
} else {
R.string.label_add_to_favourites
}
),
leading = {
MenuItemIcon(
id = R.drawable.ic_favourite,
contentDescription = null
)
},
onItemClick = {
changeFavoriteState(
GroupDialogState(
conversationSheetContent.conversationId,
conversationSheetContent.title
),
!isFavorite
)
}
)
}
}
}
// TODO(profile): enable when implemented
//
// if (conversationSheetContent.canAddToFavourite())
// add {
// MenuBottomSheetItem(
// title = stringResource(R.string.label_add_to_favourites),
// icon = {
// MenuItemIcon(
// id = R.drawable.ic_favourite,
// contentDescription = stringResource(R.string.content_description_add_to_favourite),
// )
// },
// onItemClick = addConversationToFavourites
// )
// }
// add {
// MenuBottomSheetItem(
// icon = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Wire
* Copyright (C) 2024 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.bottomsheet.folder

import com.wire.android.di.ScopedArgs
import kotlinx.serialization.Serializable

@Serializable
object ChangeConversationFavoriteStateArgs : ScopedArgs {
override val key = "ConnectionActionButtonArgsKey"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Wire
* Copyright (C) 2024 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.bottomsheet.folder

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wire.android.R
import com.wire.android.di.ViewModelScopedPreview
import com.wire.android.model.SnackBarMessage
import com.wire.android.model.asSnackBarMessage
import com.wire.android.ui.home.conversationslist.model.GroupDialogState
import com.wire.android.util.ui.UIText
import com.wire.kalium.logic.feature.conversation.folder.AddConversationToFavoritesUseCase
import com.wire.kalium.logic.feature.conversation.folder.RemoveConversationFromFavoritesUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

@ViewModelScopedPreview
interface ChangeConversationFavoriteVM {
val infoMessage: SharedFlow<SnackBarMessage>
get() = MutableSharedFlow()

fun changeFavoriteState(dialogState: GroupDialogState, addToFavorite: Boolean) {}
}

@HiltViewModel
class ChangeConversationFavoriteVMImpl @Inject constructor(
private val addConversationToFavorites: AddConversationToFavoritesUseCase,
private val removeConversationFromFavorites: RemoveConversationFromFavoritesUseCase,
) : ChangeConversationFavoriteVM, ViewModel() {

private val _infoMessage = MutableSharedFlow<SnackBarMessage>()
override val infoMessage = _infoMessage.asSharedFlow()

override fun changeFavoriteState(dialogState: GroupDialogState, addToFavorite: Boolean) {
viewModelScope.launch {
val messageResource = if (addToFavorite) {
when (addConversationToFavorites(dialogState.conversationId)) {
is AddConversationToFavoritesUseCase.Result.Failure -> R.string.error_adding_to_favorite
AddConversationToFavoritesUseCase.Result.Success -> R.string.success_adding_to_favorite
}
} else {
when (removeConversationFromFavorites(dialogState.conversationId)) {
is RemoveConversationFromFavoritesUseCase.Result.Failure -> R.string.error_removing_from_favorite
RemoveConversationFromFavoritesUseCase.Result.Success -> R.string.success_removing_from_favorite
}
}
_infoMessage.emit(UIText.StringResource(messageResource, dialogState.conversationName).asSnackBarMessage())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import com.ramcosta.composedestinations.result.ResultBackNavigator
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.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.navigation.WireDestination
Expand All @@ -78,6 +79,9 @@ import com.wire.android.ui.common.bottomsheet.WireModalSheetLayout
import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetContent
import com.wire.android.ui.common.bottomsheet.conversation.ConversationTypeDetail
import com.wire.android.ui.common.bottomsheet.conversation.rememberConversationSheetState
import com.wire.android.ui.common.bottomsheet.folder.ChangeConversationFavoriteStateArgs
import com.wire.android.ui.common.bottomsheet.folder.ChangeConversationFavoriteVM
import com.wire.android.ui.common.bottomsheet.folder.ChangeConversationFavoriteVMImpl
import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
import com.wire.android.ui.common.bottomsheet.show
import com.wire.android.ui.common.button.WirePrimaryButton
Expand Down Expand Up @@ -285,7 +289,11 @@ private fun GroupConversationDetailsContent(
isLoading: Boolean,
isAbandonedOneOnOneConversation: Boolean,
onSearchConversationMessagesClick: () -> Unit,
onConversationMediaClick: () -> Unit
onConversationMediaClick: () -> Unit,
changeConversationFavoriteStateViewModel: ChangeConversationFavoriteVM =
hiltViewModelScoped<ChangeConversationFavoriteVMImpl, ChangeConversationFavoriteVM, ChangeConversationFavoriteStateArgs>(
ChangeConversationFavoriteStateArgs
),
) {
val scope = rememberCoroutineScope()
val resources = LocalContext.current.resources
Expand Down Expand Up @@ -461,7 +469,7 @@ private fun GroupConversationDetailsContent(
)
}
},
addConversationToFavourites = bottomSheetEventsHandler::onAddConversationToFavourites,
changeFavoriteState = changeConversationFavoriteStateViewModel::changeFavoriteState,
moveConversationToFolder = bottomSheetEventsHandler::onMoveConversationToFolder,
updateConversationArchiveStatus = {
// Only show the confirmation dialog if the conversation is not archived
Expand Down Expand Up @@ -597,7 +605,8 @@ fun PreviewGroupConversationDetails() {
),
mlsVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isUnderLegalHold = false,
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED
proteusVerificationStatus = Conversation.VerificationStatus.VERIFIED,
isFavorite = false
),
bottomSheetEventsHandler = GroupConversationDetailsBottomSheetEventsHandler.PREVIEW,
onBackPressed = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class GroupConversationDetailsViewModel @Inject constructor(
mlsVerificationStatus = groupDetails.conversation.mlsVerificationStatus,
proteusVerificationStatus = groupDetails.conversation.proteusVerificationStatus,
isUnderLegalHold = groupDetails.conversation.legalHoldStatus.showLegalHoldIndicator(),
isFavorite = groupDetails.isFavorite
)

updateState(
Expand Down Expand Up @@ -374,10 +375,6 @@ class GroupConversationDetailsViewModel @Inject constructor(
}
}

@Suppress("EmptyFunctionBlock")
override fun onAddConversationToFavourites(conversationId: ConversationId?) {
}

@Suppress("EmptyFunctionBlock")
override fun onMoveConversationToFolder(conversationId: ConversationId?) {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ 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 updateConversationArchiveStatus(
dialogState: DialogState,
Expand All @@ -47,7 +46,6 @@ interface GroupConversationDetailsBottomSheetEventsHandler {
) {
}

override fun onAddConversationToFavourites(conversationId: ConversationId?) {}
override fun onMoveConversationToFolder(conversationId: ConversationId?) {}
override fun updateConversationArchiveStatus(
dialogState: DialogState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ interface ConversationListViewModel {
fun leaveGroup(leaveGroupState: GroupDialogState) {}
fun clearConversationContent(dialogState: DialogState) {}
fun muteConversation(conversationId: ConversationId?, mutedConversationStatus: MutedConversationStatus) {}
fun addConversationToFavourites() {}
fun moveConversationToFolder() {}
fun searchQueryChanged(searchQuery: String) {}
}
Expand Down Expand Up @@ -367,11 +366,6 @@ class ConversationListViewModelImpl @AssistedInject constructor(
}
}

// TODO: needs to be implemented
@Suppress("EmptyFunctionBlock")
override fun addConversationToFavourites() {
}

// TODO: needs to be implemented
@Suppress("EmptyFunctionBlock")
override fun moveConversationToFolder() {
Expand Down
Loading
Loading