Add a back button to the account provider confirmation screen

The screen where the user enters the server address only supported the
system back gesture. Add a top app bar with a back button, consistent with
the screen to choose the account provider and FlowStepPage, so the user can
navigate back from it, especially when adding another account.

Part of #7768

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benoit Marty
2026-10-14 11:35:13 +02:00
parent 9b3a9a0a2d
commit f72af72d80
4 changed files with 71 additions and 2 deletions
@@ -56,6 +56,7 @@ class ConfirmAccountProviderNode(
ConfirmAccountProviderView(
state = state,
modifier = modifier,
onBackClick = ::navigateUp,
onOAuthDetails = callback::navigateToOAuth,
onNeedLoginPassword = callback::navigateToLoginPassword,
onLearnMoreClick = { openLearnMorePage(context) },
@@ -34,7 +34,7 @@ open class ConfirmAccountProviderStatePreviewParam : PreviewParameterProvider<Co
)
}
private fun aConfirmAccountProviderState(
internal fun aConfirmAccountProviderState(
accountProviderInput: String = "matrix.org",
accountProviderSuggestion: String? = null,
isAccountCreation: Boolean = false,
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -50,12 +51,14 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.BigIcon
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.form.textFieldState
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.TextField
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.libraries.permissions.api.localnetwork.LocalNetworkPermissionDialogView
import io.element.android.libraries.testtags.TestTags
@@ -71,6 +74,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable
fun ConfirmAccountProviderView(
state: ConfirmAccountProviderState,
onBackClick: () -> Unit,
onOAuthDetails: (OAuthDetails) -> Unit,
onNeedLoginPassword: () -> Unit,
onLearnMoreClick: () -> Unit,
@@ -118,9 +122,15 @@ fun ConfirmAccountProviderView(
// Let the header and content scroll so the supporting text is not clipped by the footer when the
// keyboard is visible and vertical space is reduced.
isScrollable = true,
topBar = {
TopAppBar(
title = {},
navigationIcon = { BackButton(onClick = onBackClick) },
colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
)
},
header = {
IconTitleSubtitleMolecule(
modifier = Modifier.padding(top = 60.dp),
iconStyle = BigIcon.Style.Default(CompoundIcons.UserProfileSolid()),
title = stringResource(
id = if (state.isAccountCreation) {
@@ -272,6 +282,7 @@ internal fun ConfirmAccountProviderViewPreview(
) = ElementPreview {
ConfirmAccountProviderView(
state = state,
onBackClick = {},
onOAuthDetails = {},
onNeedLoginPassword = {},
onLearnMoreClick = {},
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
@file:OptIn(ExperimentalTestApi::class)
package io.element.android.features.login.impl.screens.confirmaccountprovider
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.v2.runAndroidComposeUiTest
import io.element.android.libraries.matrix.api.auth.OAuthDetails
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.pressBack
import io.element.android.tests.testutils.robolectric.RobolectricTest
import org.junit.Test
class ConfirmAccountProviderViewTest : RobolectricTest() {
@Test
fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest {
val eventSink = EventsRecorder<ConfirmAccountProviderEvent>(expectEvents = false)
ensureCalledOnce {
setConfirmAccountProviderView(
state = aConfirmAccountProviderState(
eventSink = eventSink,
),
onBackClick = it,
)
pressBack()
}
}
private fun AndroidComposeUiTest<ComponentActivity>.setConfirmAccountProviderView(
state: ConfirmAccountProviderState,
onBackClick: () -> Unit = EnsureNeverCalled(),
onOAuthDetails: (OAuthDetails) -> Unit = EnsureNeverCalledWithParam(),
onNeedLoginPassword: () -> Unit = EnsureNeverCalled(),
onLearnMoreClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
ConfirmAccountProviderView(
state = state,
onBackClick = onBackClick,
onOAuthDetails = onOAuthDetails,
onNeedLoginPassword = onNeedLoginPassword,
onLearnMoreClick = onLearnMoreClick,
)
}
}
}