Link new device using QrCode.

This commit is contained in:
Benoit Marty 2025-12-04 10:52:26 +01:00 committed by Benoit Marty
parent 5ebb615751
commit a073117d62
94 changed files with 4431 additions and 36 deletions

View file

@ -163,6 +163,10 @@ class PreferencesFlowNode(
backstack.push(NavTarget.Labs)
}
override fun navigateToLinkNewDevice() {
callback.navigateToLinkNewDevice()
}
override fun navigateToUserProfile(matrixUser: MatrixUser) {
backstack.push(NavTarget.UserProfile(matrixUser))
}

View file

@ -45,6 +45,7 @@ class PreferencesRootNode(
fun navigateToLockScreenSettings()
fun navigateToAdvancedSettings()
fun navigateToLabs()
fun navigateToLinkNewDevice()
fun navigateToUserProfile(matrixUser: MatrixUser)
fun navigateToBlockedUsers()
fun startSignOutFlow()
@ -84,6 +85,7 @@ class PreferencesRootNode(
onOpenDeveloperSettings = callback::navigateToDeveloperSettings,
onOpenAdvancedSettings = callback::navigateToAdvancedSettings,
onOpenLabs = callback::navigateToLabs,
onLinkNewDeviceClick = callback::navigateToLinkNewDevice,
onManageAccountClick = { onManageAccountClick(activity, it, isDark) },
onOpenNotificationSettings = callback::navigateToNotificationSettings,
onOpenLockScreenSettings = callback::navigateToLockScreenSettings,

View file

@ -69,6 +69,9 @@ class PreferencesRootPresenter(
val isMultiAccountEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.MultiAccount)
}.collectAsState(initial = false)
val showLinkNewDevice by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.QrCodeLogin)
}.collectAsState(initial = false)
val otherSessions by remember {
sessionStore.sessionsFlow().map { list ->
@ -146,6 +149,7 @@ class PreferencesRootPresenter(
devicesManagementUrl = devicesManagementUrl.value,
showAnalyticsSettings = hasAnalyticsProviders,
canReportBug = canReportBug,
showLinkNewDevice = showLinkNewDevice,
showDeveloperSettings = showDeveloperSettings,
canDeactivateAccount = canDeactivateAccount,
showBlockedUsersItem = showBlockedUsersItem,

View file

@ -25,6 +25,7 @@ data class PreferencesRootState(
val accountManagementUrl: String?,
val devicesManagementUrl: String?,
val canReportBug: Boolean,
val showLinkNewDevice: Boolean,
val showAnalyticsSettings: Boolean,
val showDeveloperSettings: Boolean,
val canDeactivateAccount: Boolean,

View file

@ -31,6 +31,7 @@ fun aPreferencesRootState(
accountManagementUrl = "aUrl",
devicesManagementUrl = "anOtherUrl",
showAnalyticsSettings = true,
showLinkNewDevice = true,
canReportBug = true,
showDeveloperSettings = true,
showBlockedUsersItem = true,

View file

@ -54,6 +54,7 @@ fun PreferencesRootView(
onAddAccountClick: () -> Unit,
onSecureBackupClick: () -> Unit,
onManageAccountClick: (url: String) -> Unit,
onLinkNewDeviceClick: () -> Unit,
onOpenAnalytics: () -> Unit,
onOpenRageShake: () -> Unit,
onOpenLockScreenSettings: () -> Unit,
@ -101,6 +102,7 @@ fun PreferencesRootView(
ManageAccountSection(
state = state,
onManageAccountClick = onManageAccountClick,
onLinkNewDeviceClick = onLinkNewDeviceClick,
onOpenBlockedUsers = onOpenBlockedUsers
)
@ -193,8 +195,16 @@ private fun ColumnScope.ManageAppSection(
private fun ColumnScope.ManageAccountSection(
state: PreferencesRootState,
onManageAccountClick: (url: String) -> Unit,
onLinkNewDeviceClick: () -> Unit,
onOpenBlockedUsers: () -> Unit,
) {
if (state.showLinkNewDevice) {
ListItem(
headlineContent = { Text(stringResource(id = CommonStrings.common_link_new_device)) },
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Devices())),
onClick = onLinkNewDeviceClick,
)
}
state.accountManagementUrl?.let { url ->
ListItem(
headlineContent = { Text(stringResource(id = CommonStrings.action_manage_account)) },
@ -353,6 +363,7 @@ private fun ContentToPreview(matrixUser: MatrixUser) {
onOpenAbout = {},
onSecureBackupClick = {},
onManageAccountClick = {},
onLinkNewDeviceClick = {},
onOpenNotificationSettings = {},
onOpenLockScreenSettings = {},
onOpenUserProfile = {},

View file

@ -50,6 +50,7 @@ class DefaultPreferencesEntryPointTest {
}
val callback = object : PreferencesEntryPoint.Callback {
override fun navigateToAddAccount() = lambdaError()
override fun navigateToLinkNewDevice() = lambdaError()
override fun navigateToBugReport() = lambdaError()
override fun navigateToSecureBackup() = lambdaError()
override fun navigateToRoomNotificationSettings(roomId: RoomId) = lambdaError()

View file

@ -87,6 +87,7 @@ class PreferencesRootPresenterTest {
assertThat(loadedState.accountManagementUrl).isNull()
assertThat(loadedState.devicesManagementUrl).isNull()
assertThat(loadedState.showAnalyticsSettings).isFalse()
assertThat(loadedState.showLinkNewDevice).isFalse()
assertThat(loadedState.showDeveloperSettings).isTrue()
assertThat(loadedState.canDeactivateAccount).isTrue()
assertThat(loadedState.canReportBug).isTrue()
@ -258,6 +259,22 @@ class PreferencesRootPresenterTest {
}
}
@Test
fun `present - link new device`() = runTest {
createPresenter(
matrixClient = FakeMatrixClient(
sessionId = A_SESSION_ID,
canDeactivateAccountResult = { true },
),
featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.QrCodeLogin.key to true)
),
).test {
val state = awaitFirstItem()
assertThat(state.showLinkNewDevice).isTrue()
}
}
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
skipItems(1)
return awaitItem()