From 466331c55cc8046eeee985fbba5a723e07a48c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Mon, 16 Dec 2024 19:01:32 +0100 Subject: [PATCH 1/5] feat: Add option to manage team [#WPB-14873] --- .../userprofile/self/SelfUserProfileScreen.kt | 27 ++++++++++++++++++- .../userprofile/self/SelfUserProfileState.kt | 1 + .../self/SelfUserProfileViewModel.kt | 2 ++ app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt index e09da4b1532..d6d9504be26 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.scrollable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.defaultMinSize @@ -43,6 +44,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -208,6 +210,7 @@ private fun SelfUserProfileContent( isUserInCall: () -> Boolean ) { val snackbarHostState = LocalSnackbarHostState.current + val uriHandler = LocalUriHandler.current state.errorMessageCode?.let { errorCode -> val errorMessage = mapErrorCodeToString(errorCode) @@ -345,7 +348,13 @@ private fun SelfUserProfileContent( Divider(color = MaterialTheme.wireColorScheme.outline) - Box(modifier = Modifier.padding(dimensions().spacing16x)) { + Column( + modifier = Modifier.padding(dimensions().spacing16x), + verticalArrangement = Arrangement.spacedBy(dimensions().spacing8x) + ) { + if (isTeamAdminOrOwner) { + ManageTeamButton(uriHandler::openUri) + } NewTeamButton(onAddAccountClick, isUserInCall, context) } } @@ -440,6 +449,22 @@ private fun CurrentSelfUserStatus( } } +@Composable +private fun ManageTeamButton( + onManageTeamClick: (String) -> Unit +) { + val teamManagementLink = stringResource(R.string.url_team_management_login) + WireSecondaryButton( + modifier = Modifier + .testTag("Manage team"), + text = stringResource(R.string.user_profile_account_management), + onClickDescription = stringResource(R.string.content_description_self_profile_manage_team_btn), + onClick = { + onManageTeamClick(teamManagementLink) + } + ) +} + @Composable private fun NewTeamButton( onAddAccountClick: () -> Unit, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt index c5ffb5c647a..37e276bfff3 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt @@ -34,6 +34,7 @@ data class SelfUserProfileState( val fullName: String = "", val userName: String = "", val teamName: String? = "", // maybe teamId is better here + val isTeamAdminOrOwner: Boolean = false, val otherAccounts: List = emptyList(), val statusDialogData: StatusDialogData? = null, // null means no dialog to display val isAvatarLoading: Boolean = false, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt index 7ea1e925b6b..237cbff948e 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt @@ -48,6 +48,7 @@ import com.wire.kalium.logic.data.user.SelfUser import com.wire.kalium.logic.data.user.UserAssetId import com.wire.kalium.logic.data.user.UserAvailabilityStatus import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.data.user.type.UserType import com.wire.kalium.logic.feature.auth.LogoutUseCase import com.wire.kalium.logic.feature.call.usecase.EndCallUseCase import com.wire.kalium.logic.feature.call.usecase.ObserveEstablishedCallsUseCase @@ -176,6 +177,7 @@ class SelfUserProfileViewModel @Inject constructor( fullName = name.orEmpty(), userName = handle.orEmpty(), teamName = selfTeam?.name, + isTeamAdminOrOwner = userType == UserType.OWNER || userType == UserType.ADMIN, otherAccounts = otherAccounts, avatarAsset = userProfileState.avatarAsset, isAvatarLoading = false, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4811da7ef86..f12f3cbc10a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -242,6 +242,7 @@ Team name, %s change availability status Create a new team or personal account or log in + Manage team Go back to your profile overview Close new team creation and login view Go back to new team creation and login view @@ -612,6 +613,7 @@ Away None New Team or Add Account + Manage Team Details Devices Group From 53bd397d71c8fd4ec919d25f88998d7626f92e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Tue, 17 Dec 2024 11:52:43 +0100 Subject: [PATCH 2/5] Self review --- .../wire/android/ui/userprofile/self/SelfUserProfileScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt index d6d9504be26..b18fa1f8457 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt @@ -455,8 +455,6 @@ private fun ManageTeamButton( ) { val teamManagementLink = stringResource(R.string.url_team_management_login) WireSecondaryButton( - modifier = Modifier - .testTag("Manage team"), text = stringResource(R.string.user_profile_account_management), onClickDescription = stringResource(R.string.content_description_self_profile_manage_team_btn), onClick = { From 736646852102f33e59cf45b2404cebff2c02f026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Tue, 17 Dec 2024 13:29:21 +0100 Subject: [PATCH 3/5] Code review --- .../ui/userprofile/self/SelfUserProfileScreen.kt | 11 ++++------- .../ui/userprofile/self/SelfUserProfileState.kt | 2 +- .../ui/userprofile/self/SelfUserProfileViewModel.kt | 6 ++++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt index b18fa1f8457..60d081bf260 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileScreen.kt @@ -352,8 +352,8 @@ private fun SelfUserProfileContent( modifier = Modifier.padding(dimensions().spacing16x), verticalArrangement = Arrangement.spacedBy(dimensions().spacing8x) ) { - if (isTeamAdminOrOwner) { - ManageTeamButton(uriHandler::openUri) + if (teamUrl != null) { + ManageTeamButton { uriHandler.openUri(teamUrl) } } NewTeamButton(onAddAccountClick, isUserInCall, context) } @@ -451,15 +451,12 @@ private fun CurrentSelfUserStatus( @Composable private fun ManageTeamButton( - onManageTeamClick: (String) -> Unit + onManageTeamClick: () -> Unit ) { - val teamManagementLink = stringResource(R.string.url_team_management_login) WireSecondaryButton( text = stringResource(R.string.user_profile_account_management), onClickDescription = stringResource(R.string.content_description_self_profile_manage_team_btn), - onClick = { - onManageTeamClick(teamManagementLink) - } + onClick = onManageTeamClick ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt index 37e276bfff3..5c2a742f02d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileState.kt @@ -34,7 +34,7 @@ data class SelfUserProfileState( val fullName: String = "", val userName: String = "", val teamName: String? = "", // maybe teamId is better here - val isTeamAdminOrOwner: Boolean = false, + val teamUrl: String? = null, val otherAccounts: List = emptyList(), val statusDialogData: StatusDialogData? = null, // null means no dialog to display val isAvatarLoading: Boolean = false, diff --git a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt index 237cbff948e..2820cc43ae5 100644 --- a/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModel.kt @@ -55,6 +55,7 @@ import com.wire.kalium.logic.feature.call.usecase.ObserveEstablishedCallsUseCase import com.wire.kalium.logic.feature.legalhold.LegalHoldStateForSelfUser import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldStateForSelfUserUseCase import com.wire.kalium.logic.feature.personaltoteamaccount.CanMigrateFromPersonalToTeamUseCase +import com.wire.kalium.logic.feature.server.GetTeamUrlUseCase import com.wire.kalium.logic.feature.team.GetUpdatedSelfTeamUseCase import com.wire.kalium.logic.feature.user.GetSelfUserUseCase import com.wire.kalium.logic.feature.user.IsReadOnlyAccountUseCase @@ -99,7 +100,8 @@ class SelfUserProfileViewModel @Inject constructor( private val notificationManager: WireNotificationManager, private val globalDataStore: GlobalDataStore, private val qualifiedIdMapper: QualifiedIdMapper, - private val anonymousAnalyticsManager: AnonymousAnalyticsManager + private val anonymousAnalyticsManager: AnonymousAnalyticsManager, + private val getTeamUrl: GetTeamUrlUseCase ) : ViewModel() { var userProfileState by mutableStateOf(SelfUserProfileState(userId = selfUserId, isAvatarLoading = true)) @@ -177,7 +179,7 @@ class SelfUserProfileViewModel @Inject constructor( fullName = name.orEmpty(), userName = handle.orEmpty(), teamName = selfTeam?.name, - isTeamAdminOrOwner = userType == UserType.OWNER || userType == UserType.ADMIN, + teamUrl = getTeamUrl().takeIf { userType == UserType.OWNER || userType == UserType.ADMIN }, otherAccounts = otherAccounts, avatarAsset = userProfileState.avatarAsset, isAvatarLoading = false, From a5fc2ddcba57034082c2b6cc235796a4c015d86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Tue, 17 Dec 2024 23:24:24 +0100 Subject: [PATCH 4/5] Update kalium to have access to team url use case --- .../kotlin/com/wire/android/di/accountScoped/UserModule.kt | 6 ++++++ kalium | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/wire/android/di/accountScoped/UserModule.kt b/app/src/main/kotlin/com/wire/android/di/accountScoped/UserModule.kt index e4ed7d01bfa..2c8c7ac115c 100644 --- a/app/src/main/kotlin/com/wire/android/di/accountScoped/UserModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/accountScoped/UserModule.kt @@ -37,6 +37,7 @@ import com.wire.kalium.logic.feature.personaltoteamaccount.CanMigrateFromPersona import com.wire.kalium.logic.feature.publicuser.GetAllContactsUseCase import com.wire.kalium.logic.feature.publicuser.GetKnownUserUseCase import com.wire.kalium.logic.feature.publicuser.RefreshUsersWithoutMetadataUseCase +import com.wire.kalium.logic.feature.server.GetTeamUrlUseCase import com.wire.kalium.logic.feature.user.DeleteAccountUseCase import com.wire.kalium.logic.feature.user.GetSelfUserUseCase import com.wire.kalium.logic.feature.user.GetUserInfoUseCase @@ -191,6 +192,11 @@ class UserModule { fun provideGetSelfUseCase(userScope: UserScope): GetSelfUserUseCase = userScope.getSelfUser + @ViewModelScoped + @Provides + fun provideGetTeamUrlUseCase(userScope: UserScope): GetTeamUrlUseCase = + userScope.getTeamUrl + @ViewModelScoped @Provides fun provideGetAvatarAssetUseCase(userScope: UserScope): GetAvatarAssetUseCase = diff --git a/kalium b/kalium index 1ca6dfc988e..91b8319e99d 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 1ca6dfc988eeccf550858620ae1dadf8e49555da +Subproject commit 91b8319e99d83e486751967c8adf4f027d57a82e From df6a47b4802e3f4bab00ed099b1846c255e9924d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zag=C3=B3rski?= Date: Wed, 18 Dec 2024 10:41:05 +0100 Subject: [PATCH 5/5] Fix tests --- .../self/SelfUserProfileViewModelArrangement.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModelArrangement.kt b/app/src/test/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModelArrangement.kt index 47b10e19c10..b278b335428 100644 --- a/app/src/test/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModelArrangement.kt +++ b/app/src/test/kotlin/com/wire/android/ui/userprofile/self/SelfUserProfileViewModelArrangement.kt @@ -35,6 +35,7 @@ import com.wire.kalium.logic.feature.call.usecase.ObserveEstablishedCallsUseCase import com.wire.kalium.logic.feature.legalhold.LegalHoldStateForSelfUser import com.wire.kalium.logic.feature.legalhold.ObserveLegalHoldStateForSelfUserUseCase import com.wire.kalium.logic.feature.personaltoteamaccount.CanMigrateFromPersonalToTeamUseCase +import com.wire.kalium.logic.feature.server.GetTeamUrlUseCase import com.wire.kalium.logic.feature.team.GetUpdatedSelfTeamUseCase import com.wire.kalium.logic.feature.user.GetSelfUserUseCase import com.wire.kalium.logic.feature.user.IsReadOnlyAccountUseCase @@ -101,6 +102,9 @@ class SelfUserProfileViewModelArrangement { @MockK lateinit var canMigrateFromPersonalToTeam: CanMigrateFromPersonalToTeamUseCase + @MockK + lateinit var getTeamUrl: GetTeamUrlUseCase + private val viewModel by lazy { SelfUserProfileViewModel( selfUserId = TestUser.SELF_USER.id, @@ -121,7 +125,8 @@ class SelfUserProfileViewModelArrangement { globalDataStore = globalDataStore, qualifiedIdMapper = qualifiedIdMapper, anonymousAnalyticsManager = anonymousAnalyticsManager, - canMigrateFromPersonalToTeam = canMigrateFromPersonalToTeam + canMigrateFromPersonalToTeam = canMigrateFromPersonalToTeam, + getTeamUrl = getTeamUrl ) } @@ -136,6 +141,7 @@ class SelfUserProfileViewModelArrangement { coEvery { observeEstablishedCalls.invoke() } returns flowOf(emptyList()) coEvery { observeEstablishedCalls.invoke() } returns flowOf(emptyList()) coEvery { canMigrateFromPersonalToTeam.invoke() } returns true + coEvery { getTeamUrl.invoke() } returns "" } fun withLegalHoldStatus(result: LegalHoldStateForSelfUser) = apply {