diff --git a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt index 02445d535f5..8291470d512 100644 --- a/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt +++ b/app/src/main/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContent.kt @@ -152,4 +152,6 @@ data class ConversationSheetContent( fun canAddToFavourite(): Boolean = (conversationTypeDetail is ConversationTypeDetail.Private && conversationTypeDetail.blockingState != BlockingState.BLOCKED) || conversationTypeDetail is ConversationTypeDetail.Group + + fun isAbandonedOneOnOneConversation(participantsCount: Int): Boolean = title.isEmpty() && participantsCount == 1 } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt index fa1596bbdff..100800fe8e5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt @@ -18,6 +18,7 @@ package com.wire.android.ui.home.conversations.details +import SwipeableSnackbar import androidx.annotation.StringRes import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.LocalOverscrollConfiguration @@ -34,6 +35,7 @@ import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -111,8 +113,6 @@ import com.wire.android.ui.theme.wireTypography import com.wire.android.util.ui.UIText import com.wire.kalium.logic.data.conversation.Conversation import kotlinx.coroutines.launch -import SwipeableSnackbar -import androidx.compose.material3.SnackbarHost @RootNavGraph @WireDestination( @@ -394,7 +394,11 @@ private fun GroupConversationDetailsContent( openFullListPressed = openFullListPressed, onAddParticipantsPressed = onAddParticipantsPressed, onProfilePressed = onProfilePressed, - lazyListState = lazyListStates[pageIndex] + lazyListState = lazyListStates[pageIndex], + isAbandonedOneOnOneConversation = conversationSheetState.conversationSheetContent?.isAbandonedOneOnOneConversation( + groupParticipantsState.data.allCount + ) ?: false + ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsTopBarCollapsing.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsTopBarCollapsing.kt index d6f098ce04d..29c18ac86eb 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsTopBarCollapsing.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsTopBarCollapsing.kt @@ -99,7 +99,7 @@ fun GroupConversationDetailsTopBarCollapsing( Text( text = title.ifBlank { if (isLoading) "" - else UIText.StringResource(R.string.group_unavailable_label).asString() + else UIText.StringResource(R.string.member_name_deleted_label).asString() }, overflow = TextOverflow.Ellipsis, maxLines = 1, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipants.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipants.kt index d657a5a2f1e..6ecc81a210d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipants.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/GroupConversationParticipants.kt @@ -61,7 +61,8 @@ fun GroupConversationParticipants( onProfilePressed: (UIParticipant) -> Unit, onAddParticipantsPressed: () -> Unit, groupParticipantsState: GroupConversationParticipantsState, - lazyListState: LazyListState = rememberLazyListState() + lazyListState: LazyListState = rememberLazyListState(), + isAbandonedOneOnOneConversation: Boolean = false ) { val context = LocalContext.current Column { @@ -86,7 +87,7 @@ fun GroupConversationParticipants( groupParticipantsState.data.allCount.toString() ) ) - if (groupParticipantsState.data.isSelfAnAdmin) { + if (groupParticipantsState.data.isSelfAnAdmin && !isAbandonedOneOnOneConversation) { WirePrimaryButton( text = stringResource(R.string.conversation_details_group_participants_add), fillMaxWidth = true, diff --git a/app/src/test/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContentTest.kt b/app/src/test/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContentTest.kt new file mode 100644 index 00000000000..5b86e7dd5eb --- /dev/null +++ b/app/src/test/kotlin/com/wire/android/ui/common/bottomsheet/conversation/ConversationSheetContentTest.kt @@ -0,0 +1,91 @@ +/* + * 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.conversation + +import com.wire.android.ui.home.conversations.details.GroupConversationDetailsViewModelTest.Companion.testGroup +import com.wire.kalium.logic.data.conversation.Conversation +import com.wire.kalium.logic.data.id.TeamId +import kotlinx.coroutines.test.runTest +import org.amshove.kluent.internal.assertEquals +import org.junit.jupiter.api.Test + +class ConversationSheetContentTest { + + @Test + fun givenTitleIsEmptyAndTheGroupSizeIsOne_whenCallingIsTheGroupAbandoned_returnsTrue() = runTest { + val details = testGroup.copy(conversation = testGroup.conversation.copy(teamId = TeamId("team_id"))) + + val givenConversationSheetContent = ConversationSheetContent( + title = "", + conversationId = details.conversation.id, + mutingConversationState = details.conversation.mutedStatus, + conversationTypeDetail = ConversationTypeDetail.Group(details.conversation.id, details.isSelfUserCreator), + selfRole = Conversation.Member.Role.Member, + isTeamConversation = details.conversation.isTeamGroup(), + isArchived = false, + protocol = Conversation.ProtocolInfo.Proteus, + mlsVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED, + proteusVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED + ) + val givenParticipantsCount = 1 + + assertEquals(true, givenConversationSheetContent.isAbandonedOneOnOneConversation(givenParticipantsCount)) + } + + @Test + fun givenTitleIsEmptyAndTheGroupSizeIsGtOne_whenCallingIsTheGroupAbandoned_returnsFalse() = runTest { + val details = testGroup.copy(conversation = testGroup.conversation.copy(teamId = TeamId("team_id"))) + + val givenConversationSheetContent = ConversationSheetContent( + title = "", + conversationId = details.conversation.id, + mutingConversationState = details.conversation.mutedStatus, + conversationTypeDetail = ConversationTypeDetail.Group(details.conversation.id, details.isSelfUserCreator), + selfRole = Conversation.Member.Role.Member, + isTeamConversation = details.conversation.isTeamGroup(), + isArchived = false, + protocol = Conversation.ProtocolInfo.Proteus, + mlsVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED, + proteusVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED + ) + val givenParticipantsCount = 3 + + assertEquals(false, givenConversationSheetContent.isAbandonedOneOnOneConversation(givenParticipantsCount)) + } + + @Test + fun givenTitleIsNotEmptyAndTheGroupSizeIsOne_whenCallingIsTheGroupAbandoned_returnsFalse() = runTest { + val details = testGroup.copy(conversation = testGroup.conversation.copy(teamId = TeamId("team_id"))) + + val givenConversationSheetContent = ConversationSheetContent( + title = "notEmpty", + conversationId = details.conversation.id, + mutingConversationState = details.conversation.mutedStatus, + conversationTypeDetail = ConversationTypeDetail.Group(details.conversation.id, details.isSelfUserCreator), + selfRole = Conversation.Member.Role.Member, + isTeamConversation = details.conversation.isTeamGroup(), + isArchived = false, + protocol = Conversation.ProtocolInfo.Proteus, + mlsVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED, + proteusVerificationStatus = Conversation.VerificationStatus.NOT_VERIFIED + ) + val givenParticipantsCount = 3 + + assertEquals(false, givenConversationSheetContent.isAbandonedOneOnOneConversation(givenParticipantsCount)) + } +}