Let SecureBackupSetupView use UserStoryFlowPage.
This commit is contained in:
parent
64ca96d502
commit
4bd47c4436
1 changed files with 88 additions and 127 deletions
|
|
@ -16,10 +16,9 @@
|
||||||
|
|
||||||
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.ColumnScope
|
||||||
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
|
||||||
|
|
@ -28,24 +27,18 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.features.securebackup.impl.R
|
import io.element.android.features.securebackup.impl.R
|
||||||
import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyView
|
import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyView
|
||||||
import io.element.android.features.securebackup.impl.setup.views.RecoveryKeyViewState
|
|
||||||
import io.element.android.libraries.androidutils.system.copyToClipboard
|
import io.element.android.libraries.androidutils.system.copyToClipboard
|
||||||
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
|
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
|
||||||
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
|
import io.element.android.libraries.designsystem.atomic.pages.UserStoryFlowPage
|
||||||
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.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,
|
||||||
|
|
@ -53,68 +46,16 @@ fun SecureBackupSetupView(
|
||||||
onBackClicked: () -> Unit,
|
onBackClicked: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
UserStoryFlowPage(
|
||||||
val canGoBack = state.canGoBack()
|
|
||||||
BackHandler(enabled = canGoBack) {
|
|
||||||
onBackClicked()
|
|
||||||
}
|
|
||||||
HeaderFooterPage(
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
topBar = {
|
canGoBack = state.canGoBack(),
|
||||||
TopAppBar(
|
onBackClicked = onBackClicked,
|
||||||
navigationIcon = {
|
title = title(state),
|
||||||
if (canGoBack) {
|
subTitle = subtitle(state),
|
||||||
BackButton(onClick = onBackClicked)
|
iconResourceId = CommonDrawables.ic_key,
|
||||||
}
|
content = { Content(state) },
|
||||||
},
|
buttons = { Buttons(state, onDone = onDone) },
|
||||||
title = {},
|
)
|
||||||
)
|
|
||||||
},
|
|
||||||
header = {
|
|
||||||
HeaderContent(state = state)
|
|
||||||
},
|
|
||||||
footer = {
|
|
||||||
val chooserTitle = stringResource(id = R.string.screen_recovery_key_save_action)
|
|
||||||
BottomMenu(
|
|
||||||
state = state,
|
|
||||||
onSaveClicked = { key ->
|
|
||||||
context.startSharePlainTextIntent(
|
|
||||||
activityResultLauncher = null,
|
|
||||||
chooserTitle = chooserTitle,
|
|
||||||
text = key,
|
|
||||||
)
|
|
||||||
state.eventSink.invoke(SecureBackupSetupEvents.RecoveryKeyHasBeenSaved)
|
|
||||||
},
|
|
||||||
onDone = {
|
|
||||||
if (state.setupState is SetupState.CreatedAndSaved) {
|
|
||||||
onDone()
|
|
||||||
} else {
|
|
||||||
state.eventSink.invoke(SecureBackupSetupEvents.Done)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
val formattedRecoveryKey = state.recoveryKeyViewState.formattedRecoveryKey
|
|
||||||
val clickLambda = if (formattedRecoveryKey != null) {
|
|
||||||
{
|
|
||||||
context.copyToClipboard(
|
|
||||||
formattedRecoveryKey,
|
|
||||||
context.getString(R.string.screen_recovery_key_copied_to_clipboard)
|
|
||||||
)
|
|
||||||
state.eventSink.invoke(SecureBackupSetupEvents.RecoveryKeyHasBeenSaved)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!state.recoveryKeyViewState.inProgress) {
|
|
||||||
{
|
|
||||||
state.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Content(state = state.recoveryKeyViewState, onClick = clickLambda)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.showSaveConfirmationDialog) {
|
if (state.showSaveConfirmationDialog) {
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
|
|
@ -134,12 +75,8 @@ private fun SecureBackupSetupState.canGoBack(): Boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun HeaderContent(
|
private fun title(state: SecureBackupSetupState): String {
|
||||||
state: SecureBackupSetupState,
|
return when (state.setupState) {
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
val setupState = state.setupState
|
|
||||||
val title = when (setupState) {
|
|
||||||
SetupState.Init,
|
SetupState.Init,
|
||||||
SetupState.Creating -> if (state.isChangeRecoveryKeyUserStory)
|
SetupState.Creating -> if (state.isChangeRecoveryKeyUserStory)
|
||||||
stringResource(id = R.string.screen_recovery_key_change_title)
|
stringResource(id = R.string.screen_recovery_key_change_title)
|
||||||
|
|
@ -149,7 +86,11 @@ private fun HeaderContent(
|
||||||
is SetupState.CreatedAndSaved ->
|
is SetupState.CreatedAndSaved ->
|
||||||
stringResource(id = R.string.screen_recovery_key_save_title)
|
stringResource(id = R.string.screen_recovery_key_save_title)
|
||||||
}
|
}
|
||||||
val subTitle = when (setupState) {
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun subtitle(state: SecureBackupSetupState): String {
|
||||||
|
return when (state.setupState) {
|
||||||
SetupState.Init,
|
SetupState.Init,
|
||||||
SetupState.Creating -> if (state.isChangeRecoveryKeyUserStory)
|
SetupState.Creating -> if (state.isChangeRecoveryKeyUserStory)
|
||||||
stringResource(id = R.string.screen_recovery_key_change_description)
|
stringResource(id = R.string.screen_recovery_key_change_description)
|
||||||
|
|
@ -159,67 +100,87 @@ private fun HeaderContent(
|
||||||
is SetupState.CreatedAndSaved ->
|
is SetupState.CreatedAndSaved ->
|
||||||
stringResource(id = R.string.screen_recovery_key_save_description)
|
stringResource(id = R.string.screen_recovery_key_save_description)
|
||||||
}
|
}
|
||||||
IconTitleSubtitleMolecule(
|
|
||||||
modifier = modifier.padding(top = 0.dp),
|
|
||||||
iconResourceId = CommonDrawables.ic_key,
|
|
||||||
title = title,
|
|
||||||
subTitle = subTitle,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun BottomMenu(
|
|
||||||
state: SecureBackupSetupState,
|
|
||||||
onSaveClicked: (String) -> Unit,
|
|
||||||
onDone: () -> Unit,
|
|
||||||
) {
|
|
||||||
val setupState = state.setupState
|
|
||||||
ButtonColumnMolecule(
|
|
||||||
modifier = Modifier.padding(bottom = 20.dp)
|
|
||||||
) {
|
|
||||||
when (setupState) {
|
|
||||||
SetupState.Init,
|
|
||||||
SetupState.Creating -> {
|
|
||||||
Button(
|
|
||||||
text = stringResource(id = CommonStrings.action_done),
|
|
||||||
enabled = false,
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = onDone
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is SetupState.Created,
|
|
||||||
is SetupState.CreatedAndSaved -> {
|
|
||||||
OutlinedButton(
|
|
||||||
text = stringResource(id = R.string.screen_recovery_key_save_action),
|
|
||||||
leadingIcon = IconSource.Resource(CommonDrawables.ic_compound_download),
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = { onSaveClicked(setupState.recoveryKey()!!) },
|
|
||||||
)
|
|
||||||
Button(
|
|
||||||
text = stringResource(id = CommonStrings.action_done),
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = onDone,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Content(
|
private fun Content(
|
||||||
state: RecoveryKeyViewState,
|
state: SecureBackupSetupState,
|
||||||
onClick: (() -> Unit)?,
|
|
||||||
) {
|
) {
|
||||||
val modifier = Modifier.padding(top = 52.dp)
|
val context = LocalContext.current
|
||||||
|
val formattedRecoveryKey = state.recoveryKeyViewState.formattedRecoveryKey
|
||||||
|
val clickLambda = if (formattedRecoveryKey != null) {
|
||||||
|
{
|
||||||
|
context.copyToClipboard(
|
||||||
|
formattedRecoveryKey,
|
||||||
|
context.getString(R.string.screen_recovery_key_copied_to_clipboard)
|
||||||
|
)
|
||||||
|
state.eventSink.invoke(SecureBackupSetupEvents.RecoveryKeyHasBeenSaved)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!state.recoveryKeyViewState.inProgress) {
|
||||||
|
{
|
||||||
|
state.eventSink.invoke(SecureBackupSetupEvents.CreateRecoveryKey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
RecoveryKeyView(
|
RecoveryKeyView(
|
||||||
modifier = modifier,
|
modifier = Modifier.padding(top = 52.dp),
|
||||||
state = state,
|
state = state.recoveryKeyViewState,
|
||||||
onClick = onClick,
|
onClick = clickLambda,
|
||||||
onChange = null,
|
onChange = null,
|
||||||
onSubmit = null,
|
onSubmit = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ColumnScope.Buttons(
|
||||||
|
state: SecureBackupSetupState,
|
||||||
|
onDone: () -> Unit,
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val chooserTitle = stringResource(id = R.string.screen_recovery_key_save_action)
|
||||||
|
when (state.setupState) {
|
||||||
|
SetupState.Init,
|
||||||
|
SetupState.Creating -> {
|
||||||
|
Button(
|
||||||
|
text = stringResource(id = CommonStrings.action_done),
|
||||||
|
enabled = false,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
onClick = onDone
|
||||||
|
)
|
||||||
|
}
|
||||||
|
is SetupState.Created,
|
||||||
|
is SetupState.CreatedAndSaved -> {
|
||||||
|
OutlinedButton(
|
||||||
|
text = stringResource(id = R.string.screen_recovery_key_save_action),
|
||||||
|
leadingIcon = IconSource.Resource(CommonDrawables.ic_compound_download),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
onClick = {
|
||||||
|
context.startSharePlainTextIntent(
|
||||||
|
activityResultLauncher = null,
|
||||||
|
chooserTitle = chooserTitle,
|
||||||
|
text = state.setupState.recoveryKey()!!,
|
||||||
|
)
|
||||||
|
state.eventSink.invoke(SecureBackupSetupEvents.RecoveryKeyHasBeenSaved)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
text = stringResource(id = CommonStrings.action_done),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
onClick = {
|
||||||
|
if (state.setupState is SetupState.CreatedAndSaved) {
|
||||||
|
onDone()
|
||||||
|
} else {
|
||||||
|
state.eventSink.invoke(SecureBackupSetupEvents.Done)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
@Composable
|
@Composable
|
||||||
internal fun SecureBackupSetupViewPreview(
|
internal fun SecureBackupSetupViewPreview(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue