Secure backup and sign out: add TopBar with Back button.

This commit is contained in:
Benoit Marty 2023-10-30 11:03:29 +01:00 committed by Benoit Marty
parent ddd9ca40fc
commit 4898d8012c
11 changed files with 86 additions and 7 deletions

View file

@ -58,6 +58,7 @@ class LogoutNode @AssistedInject constructor(
state = state, state = state,
onChangeRecoveryKeyClicked = ::onChangeRecoveryKeyClicked, onChangeRecoveryKeyClicked = ::onChangeRecoveryKeyClicked,
onSuccessLogout = { onSuccessLogout(activity, it) }, onSuccessLogout = { onSuccessLogout(activity, it) },
onBackClicked = ::navigateUp,
modifier = modifier, modifier = modifier,
) )
} }

View file

@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -32,6 +33,7 @@ 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.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@ -39,16 +41,19 @@ import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator import io.element.android.libraries.designsystem.theme.components.LinearProgressIndicator
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.theme.progressIndicatorTrackColor import io.element.android.libraries.designsystem.theme.progressIndicatorTrackColor
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.matrix.api.encryption.BackupUploadState import io.element.android.libraries.matrix.api.encryption.BackupUploadState
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun LogoutView( fun LogoutView(
state: LogoutState, state: LogoutState,
onChangeRecoveryKeyClicked: () -> Unit, onChangeRecoveryKeyClicked: () -> Unit,
onBackClicked: () -> Unit,
onSuccessLogout: (logoutUrlResult: String?) -> Unit, onSuccessLogout: (logoutUrlResult: String?) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
@ -56,6 +61,12 @@ fun LogoutView(
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = {
TopAppBar(
navigationIcon = { BackButton(onClick = onBackClicked) },
title = {},
)
},
header = { header = {
HeaderContent(state = state) HeaderContent(state = state)
}, },
@ -134,7 +145,7 @@ private fun HeaderContent(
else -> null else -> null
} }
val paddingTop = 60.dp val paddingTop = 0.dp
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = modifier.padding(top = paddingTop), modifier = modifier.padding(top = paddingTop),
iconResourceId = CommonDrawables.ic_key, iconResourceId = CommonDrawables.ic_key,
@ -219,6 +230,7 @@ internal fun LogoutViewPreview(
LogoutView( LogoutView(
state, state,
onChangeRecoveryKeyClicked = {}, onChangeRecoveryKeyClicked = {},
onSuccessLogout = {} onSuccessLogout = {},
onBackClicked = {},
) )
} }

View file

@ -40,6 +40,7 @@ class SecureBackupDisableNode @AssistedInject constructor(
state = state, state = state,
modifier = modifier, modifier = modifier,
onDone = ::navigateUp, onDone = ::navigateUp,
onBackClicked = ::navigateUp,
) )
} }
} }

View file

@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -33,6 +34,7 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
@ -40,13 +42,16 @@ 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.Button
import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.theme.ElementTheme import io.element.android.libraries.theme.ElementTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SecureBackupDisableView( fun SecureBackupDisableView(
state: SecureBackupDisableState, state: SecureBackupDisableState,
onDone: () -> Unit, onDone: () -> Unit,
onBackClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LaunchedEffect(state.disableAction) { LaunchedEffect(state.disableAction) {
@ -56,6 +61,12 @@ fun SecureBackupDisableView(
} }
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = {
TopAppBar(
navigationIcon = { BackButton(onClick = onBackClicked) },
title = {},
)
},
header = { header = {
HeaderContent() HeaderContent()
}, },
@ -95,7 +106,7 @@ private fun HeaderContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = modifier.padding(top = 60.dp), modifier = modifier.padding(top = 0.dp),
iconResourceId = CommonDrawables.ic_key_off, iconResourceId = CommonDrawables.ic_key_off,
title = stringResource(id = R.string.screen_key_backup_disable_title), title = stringResource(id = R.string.screen_key_backup_disable_title),
subTitle = stringResource(id = R.string.screen_key_backup_disable_description), subTitle = stringResource(id = R.string.screen_key_backup_disable_description),
@ -158,5 +169,6 @@ internal fun SecureBackupDisableViewPreview(
SecureBackupDisableView( SecureBackupDisableView(
state = state, state = state,
onDone = {}, onDone = {},
onBackClicked = {},
) )
} }

View file

@ -40,6 +40,7 @@ class SecureBackupEnableNode @AssistedInject constructor(
state = state, state = state,
modifier = modifier, modifier = modifier,
onDone = ::navigateUp, onDone = ::navigateUp,
onBackClicked = ::navigateUp,
) )
} }
} }

View file

@ -18,6 +18,7 @@ package io.element.android.features.securebackup.impl.enable
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -29,16 +30,20 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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.Button
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SecureBackupEnableView( fun SecureBackupEnableView(
state: SecureBackupEnableState, state: SecureBackupEnableState,
onDone: () -> Unit, onDone: () -> Unit,
onBackClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
LaunchedEffect(state.enableAction) { LaunchedEffect(state.enableAction) {
@ -48,6 +53,12 @@ fun SecureBackupEnableView(
} }
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = {
TopAppBar(
navigationIcon = { BackButton(onClick = onBackClicked) },
title = {},
)
},
header = { header = {
HeaderContent() HeaderContent()
}, },
@ -68,7 +79,7 @@ private fun HeaderContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = modifier.padding(top = 60.dp), modifier = modifier.padding(top = 0.dp),
iconResourceId = CommonDrawables.ic_key, iconResourceId = CommonDrawables.ic_key,
title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable), title = stringResource(id = R.string.screen_chat_backup_key_backup_action_enable),
subTitle = null, subTitle = null,
@ -99,5 +110,6 @@ internal fun SecureBackupEnableViewPreview(
SecureBackupEnableView( SecureBackupEnableView(
state = state, state = state,
onDone = {}, onDone = {},
onBackClicked = {},
) )
} }

View file

@ -50,7 +50,8 @@ class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
onDone = { onDone = {
coroutineScope.postSuccessSnackbar() coroutineScope.postSuccessSnackbar()
navigateUp() navigateUp()
} },
onBackClicked = ::navigateUp,
) )
} }

View file

@ -18,6 +18,7 @@ package io.element.android.features.securebackup.impl.enter
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -30,17 +31,21 @@ import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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.Button
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SecureBackupEnterRecoveryKeyView( fun SecureBackupEnterRecoveryKeyView(
state: SecureBackupEnterRecoveryKeyState, state: SecureBackupEnterRecoveryKeyState,
onDone: () -> Unit, onDone: () -> Unit,
onBackClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
when (state.submitAction) { when (state.submitAction) {
@ -59,6 +64,12 @@ fun SecureBackupEnterRecoveryKeyView(
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = {
TopAppBar(
navigationIcon = { BackButton(onClick = onBackClicked) },
title = {},
)
},
header = { header = {
HeaderContent() HeaderContent()
}, },
@ -87,7 +98,7 @@ private fun HeaderContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = modifier.padding(top = 60.dp), modifier = modifier.padding(top = 0.dp),
iconResourceId = CommonDrawables.ic_key, iconResourceId = CommonDrawables.ic_key,
title = stringResource(id = R.string.screen_recovery_key_confirm_title), title = stringResource(id = R.string.screen_recovery_key_confirm_title),
subTitle = stringResource(id = R.string.screen_recovery_key_confirm_description), subTitle = stringResource(id = R.string.screen_recovery_key_confirm_description),
@ -135,5 +146,6 @@ internal fun SecureBackupEnterRecoveryKeyViewPreview(
SecureBackupEnterRecoveryKeyView( SecureBackupEnterRecoveryKeyView(
state = state, state = state,
onDone = {}, onDone = {},
onBackClicked = {},
) )
} }

View file

@ -60,6 +60,7 @@ class SecureBackupSetupNode @AssistedInject constructor(
coroutineScope.postSuccessSnackbar() coroutineScope.postSuccessSnackbar()
navigateUp() navigateUp()
}, },
onBackClicked = ::navigateUp,
modifier = modifier, modifier = modifier,
) )
} }

View file

@ -16,8 +16,10 @@
package io.element.android.features.securebackup.impl.setup package io.element.android.features.securebackup.impl.setup
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -32,24 +34,42 @@ import io.element.android.libraries.androidutils.system.startSharePlainTextInten
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight 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.Button
import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.IconSource
import io.element.android.libraries.designsystem.theme.components.OutlinedButton import io.element.android.libraries.designsystem.theme.components.OutlinedButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun SecureBackupSetupView( fun SecureBackupSetupView(
state: SecureBackupSetupState, state: SecureBackupSetupState,
onDone: () -> Unit, onDone: () -> Unit,
onBackClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val context = LocalContext.current val context = LocalContext.current
val canGoBack = state.canGoBack()
BackHandler(enabled = canGoBack) {
onBackClicked()
}
HeaderFooterPage( HeaderFooterPage(
modifier = modifier, modifier = modifier,
topBar = {
TopAppBar(
navigationIcon = {
if (canGoBack) {
BackButton(onClick = onBackClicked)
}
},
title = {},
)
},
header = { header = {
HeaderContent(state = state) HeaderContent(state = state)
}, },
@ -109,6 +129,10 @@ fun SecureBackupSetupView(
} }
} }
private fun SecureBackupSetupState.canGoBack(): Boolean {
return recoveryKeyViewState.formattedRecoveryKey == null
}
@Composable @Composable
private fun HeaderContent( private fun HeaderContent(
state: SecureBackupSetupState, state: SecureBackupSetupState,
@ -136,7 +160,7 @@ private fun HeaderContent(
stringResource(id = R.string.screen_recovery_key_save_description) stringResource(id = R.string.screen_recovery_key_save_description)
} }
IconTitleSubtitleMolecule( IconTitleSubtitleMolecule(
modifier = modifier.padding(top = 60.dp), modifier = modifier.padding(top = 0.dp),
iconResourceId = CommonDrawables.ic_key, iconResourceId = CommonDrawables.ic_key,
title = title, title = title,
subTitle = subTitle, subTitle = subTitle,
@ -204,5 +228,6 @@ internal fun SecureBackupSetupViewPreview(
SecureBackupSetupView( SecureBackupSetupView(
state = state, state = state,
onDone = {}, onDone = {},
onBackClicked = {},
) )
} }

View file

@ -33,5 +33,6 @@ internal fun SecureBackupSetupViewChangePreview(
recoveryKeyViewState = state.recoveryKeyViewState.copy(recoveryKeyUserStory = RecoveryKeyUserStory.Change), recoveryKeyViewState = state.recoveryKeyViewState.copy(recoveryKeyUserStory = RecoveryKeyUserStory.Change),
), ),
onDone = {}, onDone = {},
onBackClicked = {},
) )
} }