From 76db8314d8f4d20fda25559cf6776ff919ae664b Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Fri, 2 Aug 2024 16:38:59 +0200 Subject: [PATCH 1/6] fix: handling no metadata connection request --- .../main/kotlin/com/wire/android/mapper/ContactMapper.kt | 4 ++-- .../android/ui/home/newconversation/model/Contact.kt | 6 +----- .../wire/android/ui/userprofile/common/UsernameMapper.kt | 9 +++++++-- .../userprofile/other/OtherUserProfileScreenViewModel.kt | 4 ++-- .../ui/userprofile/other/OtherUserProfileState.kt | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/mapper/ContactMapper.kt b/app/src/main/kotlin/com/wire/android/mapper/ContactMapper.kt index 91f41a6fcc2..8d16c5e3557 100644 --- a/app/src/main/kotlin/com/wire/android/mapper/ContactMapper.kt +++ b/app/src/main/kotlin/com/wire/android/mapper/ContactMapper.kt @@ -22,7 +22,7 @@ import com.wire.android.model.ImageAsset import com.wire.android.model.UserAvatarData import com.wire.android.ui.home.conversationslist.model.Membership import com.wire.android.ui.home.newconversation.model.Contact -import com.wire.android.ui.userprofile.common.UsernameMapper.mapUserLabel +import com.wire.android.ui.userprofile.common.UsernameMapper import com.wire.android.util.EMPTY import com.wire.android.util.ui.WireSessionImageLoader import com.wire.kalium.logic.data.publicuser.model.UserSearchDetails @@ -44,7 +44,7 @@ class ContactMapper id = id.value, domain = id.domain, name = name.orEmpty(), - label = mapUserLabel(otherUser), + label = UsernameMapper.fromOtherUser(otherUser), avatarData = UserAvatarData( asset = previewPicture?.let { ImageAsset.UserAvatarAsset(wireSessionImageLoader, it) }, connectionState = connectionStatus diff --git a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/model/Contact.kt b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/model/Contact.kt index b5458e5282e..9ffd8f20a0b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/model/Contact.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/model/Contact.kt @@ -30,8 +30,4 @@ data class Contact( val label: String = "", val connectionState: ConnectionState, val membership: Membership -) { - fun isMetadataEmpty(): Boolean { - return name.isEmpty() - } -} +) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/common/UsernameMapper.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/common/UsernameMapper.kt index 8e86756c488..b46925b1c1f 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/common/UsernameMapper.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/common/UsernameMapper.kt @@ -18,15 +18,20 @@ package com.wire.android.ui.userprofile.common +import com.wire.android.util.ifNotEmpty import com.wire.kalium.logic.data.user.OtherUser import com.wire.kalium.logic.data.user.type.UserType object UsernameMapper { - fun mapUserLabel(otherUser: OtherUser): String = with(otherUser) { + /** + * Returns the username for the given [OtherUser]. + * The username is the handle if it exists, otherwise it is the handle@domain for federated users. + */ + fun fromOtherUser(otherUser: OtherUser): String = with(otherUser) { val userId = otherUser.id return when (otherUser.userType) { - UserType.FEDERATED -> if (handle != null) "$handle@${userId.domain}" else "" + UserType.FEDERATED -> handle?.ifNotEmpty { "$handle@${userId.domain}" }.orEmpty() else -> handle.orEmpty() } } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt index c6e9ab036a8..56208e3d92e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt @@ -37,7 +37,7 @@ import com.wire.android.ui.home.conversationslist.model.BlockState import com.wire.android.ui.home.conversationslist.model.DialogState import com.wire.android.ui.home.conversationslist.showLegalHoldIndicator import com.wire.android.ui.navArgs -import com.wire.android.ui.userprofile.common.UsernameMapper.mapUserLabel +import com.wire.android.ui.userprofile.common.UsernameMapper.fromOtherUser import com.wire.android.ui.userprofile.group.RemoveConversationMemberState import com.wire.android.ui.userprofile.other.OtherUserProfileInfoMessageType.BlockingUserOperationError import com.wire.android.ui.userprofile.other.OtherUserProfileInfoMessageType.BlockingUserOperationSuccess @@ -384,7 +384,7 @@ class OtherUserProfileScreenViewModel @Inject constructor( isAvatarLoading = false, userAvatarAsset = userAvatarAsset, fullName = otherUser.name.orEmpty(), - userName = mapUserLabel(otherUser), + userName = fromOtherUser(otherUser), teamName = userResult.team?.name.orEmpty(), email = otherUser.email.orEmpty(), phone = otherUser.phone.orEmpty(), diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt index 709c6018370..f82e89308ef 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt @@ -74,7 +74,7 @@ data class OtherUserProfileState( } fun isMetadataEmpty(): Boolean { - return fullName.isEmpty() || userName.isEmpty() + return fullName.isEmpty() && userName.isEmpty() } fun shouldShowSearchButton(): Boolean = (groupState == null From 35d8b73ef5864e36eebedfc9beb09fd5f95a2594 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Mon, 5 Aug 2024 11:23:44 +0200 Subject: [PATCH 2/6] fix: handling no metadata connection request, for temp users --- .../kotlin/com/wire/android/mapper/UIParticipantMapper.kt | 1 + .../details/participants/model/UIParticipant.kt | 1 + .../android/ui/userprofile/other/OtherUserProfileScreen.kt | 5 ++--- .../ui/userprofile/other/OtherUserProfileScreenViewModel.kt | 1 + .../android/ui/userprofile/other/OtherUserProfileState.kt | 6 +++++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/mapper/UIParticipantMapper.kt b/app/src/main/kotlin/com/wire/android/mapper/UIParticipantMapper.kt index 85736024d46..87541dd46ab 100644 --- a/app/src/main/kotlin/com/wire/android/mapper/UIParticipantMapper.kt +++ b/app/src/main/kotlin/com/wire/android/mapper/UIParticipantMapper.kt @@ -58,6 +58,7 @@ class UIParticipantMapper @Inject constructor( isMLSVerified = isMLSVerified, supportedProtocolList = supportedProtocols.orEmpty().toList(), isUnderLegalHold = isUnderLegalHold, + expiresAt = user.expiresAt ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/model/UIParticipant.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/model/UIParticipant.kt index b68c5aa926e..274a9b17aa3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/model/UIParticipant.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/participants/model/UIParticipant.kt @@ -44,4 +44,5 @@ data class UIParticipant( val isMLSVerified: Boolean = false, val supportedProtocolList: List = listOf(), val isUnderLegalHold: Boolean = false, + val expiresAt: Instant? = null ) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index 638ef43e6a9..f7ffa5983c8 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -201,7 +201,6 @@ fun OtherUserProfileScreen( } } -@OptIn(ExperimentalFoundationApi::class) @SuppressLint("UnusedCrossfadeTargetStateParameter", "LongParameterList") @Composable fun OtherProfileScreenContent( @@ -441,7 +440,6 @@ private fun TopBarCollapsing( } } -@OptIn(ExperimentalFoundationApi::class) @Composable private fun TopBarFooter( state: OtherUserProfileState, @@ -558,7 +556,7 @@ private fun ContentFooter( ) { Box(modifier = Modifier.padding(all = dimensions().spacing16x)) { // TODO show open conversation button for service bots after AR-2135 - if (!state.isMetadataEmpty() && state.membership != Membership.Service) { + if (!state.isMetadataEmpty() && state.membership != Membership.Service && !state.isTemporaryUser()) { ConnectionActionButton( state.userId, state.userName, @@ -578,6 +576,7 @@ enum class OtherUserProfileTabItem(@StringRes val titleResId: Int) : TabItem { GROUP(R.string.user_profile_group_tab), DETAILS(R.string.user_profile_details_tab), DEVICES(R.string.user_profile_devices_tab); + override val title: UIText = UIText.StringResource(titleResId) } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt index 56208e3d92e..5663e553319 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenViewModel.kt @@ -395,6 +395,7 @@ class OtherUserProfileScreenViewModel @Inject constructor( blockingState = otherUser.BlockState, isProteusVerified = otherUser.isProteusVerified, isUnderLegalHold = otherUser.isUnderLegalHold, + expiresAt = otherUser.expiresAt, conversationSheetContent = conversation?.let { ConversationSheetContent( title = otherUser.name.orEmpty(), diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt index f82e89308ef..ff8d68eabff 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileState.kt @@ -29,6 +29,7 @@ import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.user.BotService import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId +import kotlinx.datetime.Instant data class OtherUserProfileState( val userId: UserId, @@ -51,7 +52,8 @@ data class OtherUserProfileState( val isProteusVerified: Boolean = false, val isMLSVerified: Boolean = false, val isUnderLegalHold: Boolean = false, - val isConversationStarted: Boolean = false + val isConversationStarted: Boolean = false, + val expiresAt: Instant? = null ) { fun updateMuteStatus(status: MutedConversationStatus): OtherUserProfileState { return conversationSheetContent?.let { @@ -77,6 +79,8 @@ data class OtherUserProfileState( return fullName.isEmpty() && userName.isEmpty() } + fun isTemporaryUser() = expiresAt != null + fun shouldShowSearchButton(): Boolean = (groupState == null && connectionState in listOf( ConnectionState.ACCEPTED, From 1125f7d9bc4606eb47852ecdeb6b5293798116a0 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Mon, 5 Aug 2024 11:35:07 +0200 Subject: [PATCH 3/6] fix: handling no metadata connection request, for temp users --- .../other/OtherUserProfileGroup.kt | 2 +- .../other/OtherUserProfileScreen.kt | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt index 48444d16d13..ec311425034 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroup.kt @@ -93,7 +93,7 @@ fun OtherUserProfileGroup( value = AnnotatedString(state.groupState!!.role.name.asString()), isSelfAdmin = state.groupState.isSelfAdmin, openChangeRoleBottomSheet = openChangeRoleBottomSheet, - isRoleEditable = state.membership.allowsRoleEdition() && !state.isMetadataEmpty() + isRoleEditable = state.membership.allowsRoleEdition() && !state.isMetadataEmpty() && !state.isTemporaryUser() ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index f7ffa5983c8..a81d0bb413e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -112,6 +112,7 @@ import com.wire.kalium.logic.data.user.ConnectionState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.launch +import kotlinx.datetime.Instant @RootNavGraph @WireDestination( @@ -649,3 +650,28 @@ fun PreviewOtherProfileScreenContentNotConnected() { ) } } + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +@PreviewMultipleThemes +fun PreviewOtherProfileScreenTempUser() { + WireTheme { + OtherProfileScreenContent( + scope = rememberCoroutineScope(), + state = OtherUserProfileState.PREVIEW.copy( + userName = "", + connectionState = ConnectionState.CANCELLED, + isUnderLegalHold = true, + expiresAt = Instant.DISTANT_FUTURE + ), + navigationIconType = NavigationIconType.Back, + requestInProgress = false, + sheetState = rememberWireModalSheetState(), + openBottomSheet = {}, + closeBottomSheet = {}, + eventsHandler = OtherUserProfileEventsHandler.PREVIEW, + bottomSheetEventsHandler = OtherUserProfileBottomSheetEventsHandler.PREVIEW, + onSearchConversationMessagesClick = {}, + ) + } +} From f8fe07e7c43c2b2a82f8206835d868b8af8f30c7 Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Mon, 5 Aug 2024 12:11:39 +0200 Subject: [PATCH 4/6] fix: handling no metadata connection request, tests --- .../other/OtherUserProfileGroupTest.kt | 94 +++++++++++++++++++ .../other/OtherUserProfileScreenTest.kt | 77 +++++++++++++++ .../ui/userprofile/other/OtherUserStubs.kt | 51 ++++++++++ .../ui/connection/ConnectionActionButton.kt | 16 +++- .../other/OtherUserProfileScreen.kt | 5 +- 5 files changed, 238 insertions(+), 5 deletions(-) create mode 100644 app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt create mode 100644 app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt create mode 100644 app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt new file mode 100644 index 00000000000..590a8159dd3 --- /dev/null +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt @@ -0,0 +1,94 @@ +/* + * 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.userprofile.other + +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithContentDescription +import com.wire.android.ui.WireTestTheme +import com.wire.android.ui.home.conversationslist.model.Membership +import com.wire.android.ui.userprofile.other.OtherUserStubs.provideState +import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant +import org.junit.Rule +import org.junit.Test + +class OtherUserProfileGroupTest { + @get:Rule + val composeTestRule by lazy { createComposeRule() } + + @Test + fun givenARoleSelectionComponentIsShow_ShouldNotAllowModificationForTempUsers() = runTest { + composeTestRule.setContent { + WireTestTheme { + OtherUserProfileGroup( + provideState(withExpireAt = Instant.DISTANT_FUTURE.toEpochMilliseconds()), + onRemoveFromConversation = {}, + openChangeRoleBottomSheet = {}, + ) + } + } + + composeTestRule.onNodeWithContentDescription("Edit").assertDoesNotExist() + } + + @Test + fun givenARoleSelectionComponentIsShow_ShouldNotAllowModificationForUsersWithoutMetadata() = runTest { + composeTestRule.setContent { + WireTestTheme { + OtherUserProfileGroup( + provideState(withUserName = "", withFullName = ""), + onRemoveFromConversation = {}, + openChangeRoleBottomSheet = {}, + ) + } + } + + composeTestRule.onNodeWithContentDescription("Edit").assertDoesNotExist() + } + + @Test + fun givenARoleSelectionComponentIsShow_ShouldNotAllowModificationForFederatedUsers() = runTest { + composeTestRule.setContent { + WireTestTheme { + OtherUserProfileGroup( + provideState(withMembership = Membership.Federated), + onRemoveFromConversation = {}, + openChangeRoleBottomSheet = {}, + ) + } + } + + composeTestRule.onNodeWithContentDescription("Edit").assertDoesNotExist() + } + + @Test + fun givenARoleSelectionComponentIsShow_ShouldNotAllowModificationForServices() = runTest { + composeTestRule.setContent { + WireTestTheme { + OtherUserProfileGroup( + provideState(withMembership = Membership.Service), + onRemoveFromConversation = {}, + openChangeRoleBottomSheet = {}, + ) + } + } + + composeTestRule.onNodeWithContentDescription("Edit").assertDoesNotExist() + } + +} diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt new file mode 100644 index 00000000000..65cc7da16f6 --- /dev/null +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt @@ -0,0 +1,77 @@ +/* + * 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.userprofile.other + +import androidx.compose.material3.MaterialTheme +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithTag +import com.wire.android.ui.WireTestTheme +import com.wire.android.ui.home.conversationslist.model.Membership +import com.wire.android.ui.theme.wireDimensions +import com.wire.android.ui.userprofile.other.OtherUserStubs.provideState +import kotlinx.coroutines.test.runTest +import kotlinx.datetime.Instant +import org.junit.Rule +import org.junit.Test + +class OtherUserProfileScreenTest { + @get:Rule + val composeTestRule by lazy { createComposeRule() } + + @Test + fun givenOtherUserProfileFooter_ShouldNotShowConnectButtonForTempUsers() = runTest { + composeTestRule.setContent { + WireTestTheme { + ContentFooter( + state = provideState(withExpireAt = Instant.DISTANT_FUTURE.toEpochMilliseconds()), + maxBarElevation = MaterialTheme.wireDimensions.topBarShadowElevation + ) + } + } + + composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + } + + @Test + fun givenOtherUserProfileFooter_ShouldNotShowConnectButtonForUsersWithoutMetadata() = runTest { + composeTestRule.setContent { + WireTestTheme { + ContentFooter( + state = provideState(withUserName = "", withFullName = ""), + maxBarElevation = MaterialTheme.wireDimensions.topBarShadowElevation + ) + } + } + + composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + } + + @Test + fun givenOtherUserProfileFooter_ShouldNotShowConnectButtonForServices() = runTest { + composeTestRule.setContent { + WireTestTheme { + ContentFooter( + state = provideState(withMembership = Membership.Service), + maxBarElevation = MaterialTheme.wireDimensions.topBarShadowElevation + ) + } + } + + composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + } +} diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt new file mode 100644 index 00000000000..2ac82752fe4 --- /dev/null +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt @@ -0,0 +1,51 @@ +/* + * 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.userprofile.other + +import com.wire.android.ui.home.conversationslist.model.Membership +import com.wire.kalium.logic.data.conversation.Conversation.Member +import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.data.user.UserId +import kotlinx.datetime.Instant + +object OtherUserStubs { + private val baseState = OtherUserProfileState( + userId = UserId("some_user", "domain.com"), + fullName = "name", + userName = "username", + teamName = "team", + email = "email", + groupState = OtherUserProfileGroupState( + "group name", Member.Role.Member, true, ConversationId("some_user", "domain.com") + ) + ) + + fun provideState( + withFullName: String = "name", + withUserName: String = "username", + withExpireAt: Long? = null, + withMembership: Membership = Membership.Standard + ): OtherUserProfileState { + return baseState.copy( + fullName = withFullName, + userName = withUserName, + expiresAt = withExpireAt?.let { Instant.fromEpochMilliseconds(it) }, + membership = withMembership + ) + } +} diff --git a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt index 08a521a0277..7b8e647d4d3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt @@ -27,6 +27,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import com.wire.android.R @@ -98,6 +99,7 @@ fun ConnectionActionButton( loading = viewModel.actionableState().isPerformingAction, onClick = viewModel::onCancelConnectionRequest, clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true), + modifier = Modifier.testTag("connection_buttons"), ) ConnectionState.ACCEPTED -> WirePrimaryButton( @@ -108,6 +110,7 @@ fun ConnectionActionButton( unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName)) } }, + modifier = Modifier.testTag("connection_buttons"), ) ConnectionState.IGNORED -> WirePrimaryButton( @@ -121,7 +124,8 @@ fun ConnectionActionButton( contentDescription = stringResource(R.string.content_description_right_arrow), modifier = Modifier.padding(dimensions().spacing8x) ) - } + }, + modifier = Modifier.testTag("connection_buttons"), ) ConnectionState.PENDING -> Column { @@ -136,7 +140,8 @@ fun ConnectionActionButton( contentDescription = stringResource(R.string.content_description_right_arrow), modifier = Modifier.padding(dimensions().spacing8x) ) - } + }, + modifier = Modifier.testTag("connection_buttons"), ) Spacer(modifier = Modifier.height(dimensions().spacing8x)) WirePrimaryButton( @@ -155,7 +160,8 @@ fun ConnectionActionButton( contentDescription = stringResource(R.string.content_description_right_arrow), modifier = Modifier.padding(dimensions().spacing8x) ) - } + }, + modifier = Modifier.testTag("connection_buttons"), ) } @@ -172,6 +178,7 @@ fun ConnectionActionButton( ) }, clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true), + modifier = Modifier.testTag("connection_buttons"), ) } @@ -188,7 +195,8 @@ fun ConnectionActionButton( contentDescription = stringResource(R.string.content_description_right_arrow), modifier = Modifier.padding(dimensions().spacing8x) ) - } + }, + modifier = Modifier.testTag("connection_buttons"), ) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt index a81d0bb413e..eff96924201 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreen.kt @@ -109,6 +109,7 @@ import com.wire.android.util.ui.PreviewMultipleThemes import com.wire.android.util.ui.UIText import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.user.ConnectionState +import io.github.esentsov.PackagePrivate import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.launch @@ -539,8 +540,10 @@ private fun Content( } } +@SuppressLint("ComposeModifierMissing") +@PackagePrivate @Composable -private fun ContentFooter( +fun ContentFooter( state: OtherUserProfileState, maxBarElevation: Dp, onIgnoreConnectionRequest: (String) -> Unit = {}, From 4d5226a080f6f60a2be64d78da1449bf4a75180c Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Mon, 5 Aug 2024 12:12:54 +0200 Subject: [PATCH 5/6] fix: handling no metadata connection request, tests --- .../ui/userprofile/other/OtherUserProfileGroupTest.kt | 1 - .../com/wire/android/ui/userprofile/other/OtherUserStubs.kt | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt index 590a8159dd3..ab880b62b11 100644 --- a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileGroupTest.kt @@ -90,5 +90,4 @@ class OtherUserProfileGroupTest { composeTestRule.onNodeWithContentDescription("Edit").assertDoesNotExist() } - } diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt index 2ac82752fe4..48ea501f4f3 100644 --- a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserStubs.kt @@ -31,7 +31,10 @@ object OtherUserStubs { teamName = "team", email = "email", groupState = OtherUserProfileGroupState( - "group name", Member.Role.Member, true, ConversationId("some_user", "domain.com") + groupName = "group name", + role = Member.Role.Member, + isSelfAdmin = true, + conversationId = ConversationId("some_user", "domain.com") ) ) From 44e4499a4c3b30016b6b09ec14664d92663453bc Mon Sep 17 00:00:00 2001 From: yamilmedina Date: Mon, 5 Aug 2024 12:20:24 +0200 Subject: [PATCH 6/6] fix: handling no metadata connection request, tests, const --- .../other/OtherUserProfileScreenTest.kt | 7 ++++--- .../ui/connection/ConnectionActionButton.kt | 16 +++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt index 65cc7da16f6..ed39ea6a534 100644 --- a/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt +++ b/app/src/androidTest/kotlin/com/wire/android/ui/userprofile/other/OtherUserProfileScreenTest.kt @@ -21,6 +21,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import com.wire.android.ui.WireTestTheme +import com.wire.android.ui.connection.CONNECTION_ACTION_BUTTONS_TEST_TAG import com.wire.android.ui.home.conversationslist.model.Membership import com.wire.android.ui.theme.wireDimensions import com.wire.android.ui.userprofile.other.OtherUserStubs.provideState @@ -44,7 +45,7 @@ class OtherUserProfileScreenTest { } } - composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + composeTestRule.onNodeWithTag(CONNECTION_ACTION_BUTTONS_TEST_TAG).assertDoesNotExist() } @Test @@ -58,7 +59,7 @@ class OtherUserProfileScreenTest { } } - composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + composeTestRule.onNodeWithTag(CONNECTION_ACTION_BUTTONS_TEST_TAG).assertDoesNotExist() } @Test @@ -72,6 +73,6 @@ class OtherUserProfileScreenTest { } } - composeTestRule.onNodeWithTag("connection_buttons").assertDoesNotExist() + composeTestRule.onNodeWithTag(CONNECTION_ACTION_BUTTONS_TEST_TAG).assertDoesNotExist() } } diff --git a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt index 7b8e647d4d3..3892f3b2899 100644 --- a/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt +++ b/app/src/main/kotlin/com/wire/android/ui/connection/ConnectionActionButton.kt @@ -57,6 +57,8 @@ import com.wire.kalium.logic.data.id.ConversationId import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId +const val CONNECTION_ACTION_BUTTONS_TEST_TAG = "connection_buttons" + @Composable fun ConnectionActionButton( userId: UserId, @@ -99,7 +101,7 @@ fun ConnectionActionButton( loading = viewModel.actionableState().isPerformingAction, onClick = viewModel::onCancelConnectionRequest, clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true), - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) ConnectionState.ACCEPTED -> WirePrimaryButton( @@ -110,7 +112,7 @@ fun ConnectionActionButton( unableStartConversationDialogState.show(UnableStartConversationDialogState(fullName)) } }, - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) ConnectionState.IGNORED -> WirePrimaryButton( @@ -125,7 +127,7 @@ fun ConnectionActionButton( modifier = Modifier.padding(dimensions().spacing8x) ) }, - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) ConnectionState.PENDING -> Column { @@ -141,7 +143,7 @@ fun ConnectionActionButton( modifier = Modifier.padding(dimensions().spacing8x) ) }, - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) Spacer(modifier = Modifier.height(dimensions().spacing8x)) WirePrimaryButton( @@ -161,7 +163,7 @@ fun ConnectionActionButton( modifier = Modifier.padding(dimensions().spacing8x) ) }, - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) } @@ -178,7 +180,7 @@ fun ConnectionActionButton( ) }, clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true), - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) } @@ -196,7 +198,7 @@ fun ConnectionActionButton( modifier = Modifier.padding(dimensions().spacing8x) ) }, - modifier = Modifier.testTag("connection_buttons"), + modifier = Modifier.testTag(CONNECTION_ACTION_BUTTONS_TEST_TAG), ) } }