Remove Lost your recovery key? button and the temporary screen it opened.
This commit is contained in:
parent
76a3ef9353
commit
8408c7db2d
7 changed files with 1 additions and 181 deletions
|
|
@ -32,9 +32,6 @@ interface SecureBackupEntryPoint : FeatureEntryPoint {
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object EnterRecoveryKey : InitialTarget
|
data object EnterRecoveryKey : InitialTarget
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data object CreateNewRecoveryKey : InitialTarget
|
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object ResetIdentity : InitialTarget
|
data object ResetIdentity : InitialTarget
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
|
import io.element.android.features.securebackup.api.SecureBackupEntryPoint
|
||||||
import io.element.android.features.securebackup.impl.createkey.CreateNewRecoveryKeyNode
|
|
||||||
import io.element.android.features.securebackup.impl.disable.SecureBackupDisableNode
|
import io.element.android.features.securebackup.impl.disable.SecureBackupDisableNode
|
||||||
import io.element.android.features.securebackup.impl.enable.SecureBackupEnableNode
|
import io.element.android.features.securebackup.impl.enable.SecureBackupEnableNode
|
||||||
import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode
|
import io.element.android.features.securebackup.impl.enter.SecureBackupEnterRecoveryKeyNode
|
||||||
|
|
@ -52,7 +51,6 @@ class SecureBackupFlowNode @AssistedInject constructor(
|
||||||
initialElement = when (plugins.filterIsInstance<SecureBackupEntryPoint.Params>().first().initialElement) {
|
initialElement = when (plugins.filterIsInstance<SecureBackupEntryPoint.Params>().first().initialElement) {
|
||||||
SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root
|
SecureBackupEntryPoint.InitialTarget.Root -> NavTarget.Root
|
||||||
SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey
|
SecureBackupEntryPoint.InitialTarget.EnterRecoveryKey -> NavTarget.EnterRecoveryKey
|
||||||
SecureBackupEntryPoint.InitialTarget.CreateNewRecoveryKey -> NavTarget.CreateNewRecoveryKey
|
|
||||||
is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity
|
is SecureBackupEntryPoint.InitialTarget.ResetIdentity -> NavTarget.ResetIdentity
|
||||||
},
|
},
|
||||||
savedStateMap = buildContext.savedStateMap,
|
savedStateMap = buildContext.savedStateMap,
|
||||||
|
|
@ -79,9 +77,6 @@ class SecureBackupFlowNode @AssistedInject constructor(
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object EnterRecoveryKey : NavTarget
|
data object EnterRecoveryKey : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
|
||||||
data object CreateNewRecoveryKey : NavTarget
|
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object ResetIdentity : NavTarget
|
data object ResetIdentity : NavTarget
|
||||||
}
|
}
|
||||||
|
|
@ -141,16 +136,9 @@ class SecureBackupFlowNode @AssistedInject constructor(
|
||||||
backstack.pop()
|
backstack.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateNewRecoveryKey() {
|
|
||||||
backstack.push(NavTarget.CreateNewRecoveryKey)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
createNode<SecureBackupEnterRecoveryKeyNode>(buildContext, plugins = listOf(callback))
|
createNode<SecureBackupEnterRecoveryKeyNode>(buildContext, plugins = listOf(callback))
|
||||||
}
|
}
|
||||||
NavTarget.CreateNewRecoveryKey -> {
|
|
||||||
createNode<CreateNewRecoveryKeyNode>(buildContext)
|
|
||||||
}
|
|
||||||
is NavTarget.ResetIdentity -> {
|
is NavTarget.ResetIdentity -> {
|
||||||
val callback = object : ResetIdentityFlowNode.Callback {
|
val callback = object : ResetIdentityFlowNode.Callback {
|
||||||
override fun onDone() {
|
override fun onDone() {
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.securebackup.impl.createkey
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
|
||||||
import com.bumble.appyx.core.node.Node
|
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
|
||||||
import dagger.assisted.Assisted
|
|
||||||
import dagger.assisted.AssistedInject
|
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
|
||||||
import io.element.android.libraries.di.SessionScope
|
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
|
||||||
class CreateNewRecoveryKeyNode @AssistedInject constructor(
|
|
||||||
@Assisted buildContext: BuildContext,
|
|
||||||
@Assisted plugins: List<Plugin>,
|
|
||||||
private val buildMeta: BuildMeta,
|
|
||||||
) : Node(buildContext, plugins = plugins) {
|
|
||||||
@Composable
|
|
||||||
override fun View(modifier: Modifier) {
|
|
||||||
CreateNewRecoveryKeyView(
|
|
||||||
desktopApplicationName = buildMeta.desktopApplicationName,
|
|
||||||
modifier = modifier,
|
|
||||||
onBackClick = ::navigateUp,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2024 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.features.securebackup.impl.createkey
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
|
||||||
import io.element.android.features.securebackup.impl.R
|
|
||||||
import io.element.android.libraries.designsystem.atomic.organisms.NumberedListOrganism
|
|
||||||
import io.element.android.libraries.designsystem.components.BigIcon
|
|
||||||
import io.element.android.libraries.designsystem.components.PageTitle
|
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
|
||||||
import io.element.android.libraries.designsystem.utils.annotatedTextWithBold
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun CreateNewRecoveryKeyView(
|
|
||||||
desktopApplicationName: String,
|
|
||||||
onBackClick: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
Scaffold(
|
|
||||||
modifier = modifier,
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(title = {}, navigationIcon = { BackButton(onClick = onBackClick) })
|
|
||||||
}
|
|
||||||
) { padding ->
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(padding)
|
|
||||||
) {
|
|
||||||
PageTitle(
|
|
||||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 40.dp),
|
|
||||||
title = stringResource(R.string.screen_create_new_recovery_key_title),
|
|
||||||
iconStyle = BigIcon.Style.Default(CompoundIcons.Computer())
|
|
||||||
)
|
|
||||||
Content(desktopApplicationName = desktopApplicationName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun Content(desktopApplicationName: String) {
|
|
||||||
val listItems = buildList {
|
|
||||||
add(AnnotatedString(stringResource(R.string.screen_create_new_recovery_key_list_item_1, desktopApplicationName)))
|
|
||||||
add(AnnotatedString(stringResource(R.string.screen_create_new_recovery_key_list_item_2)))
|
|
||||||
add(
|
|
||||||
annotatedTextWithBold(
|
|
||||||
text = stringResource(
|
|
||||||
id = R.string.screen_create_new_recovery_key_list_item_3,
|
|
||||||
stringResource(R.string.screen_create_new_recovery_key_list_item_3_reset_all)
|
|
||||||
),
|
|
||||||
boldText = stringResource(R.string.screen_create_new_recovery_key_list_item_3_reset_all)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
add(AnnotatedString(stringResource(R.string.screen_create_new_recovery_key_list_item_4)))
|
|
||||||
add(AnnotatedString(stringResource(R.string.screen_create_new_recovery_key_list_item_5)))
|
|
||||||
}
|
|
||||||
NumberedListOrganism(modifier = Modifier.padding(horizontal = 16.dp), items = listItems.toImmutableList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreviewsDayNight
|
|
||||||
@Composable
|
|
||||||
internal fun CreateNewRecoveryKeyViewPreview() {
|
|
||||||
ElementPreview {
|
|
||||||
CreateNewRecoveryKeyView(
|
|
||||||
desktopApplicationName = "Element",
|
|
||||||
onBackClick = {},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -35,7 +35,6 @@ class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
fun onEnterRecoveryKeySuccess()
|
fun onEnterRecoveryKeySuccess()
|
||||||
fun onCreateNewRecoveryKey()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callback = plugins<Callback>().first()
|
private val callback = plugins<Callback>().first()
|
||||||
|
|
@ -48,7 +47,6 @@ class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onSuccess = callback::onEnterRecoveryKeySuccess,
|
onSuccess = callback::onEnterRecoveryKeySuccess,
|
||||||
onBackClick = ::navigateUp,
|
onBackClick = ::navigateUp,
|
||||||
onCreateNewRecoveryKey = callback::onCreateNewRecoveryKey
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ import io.element.android.libraries.designsystem.components.async.AsyncActionVie
|
||||||
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.TextButton
|
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -41,7 +40,6 @@ fun SecureBackupEnterRecoveryKeyView(
|
||||||
state: SecureBackupEnterRecoveryKeyState,
|
state: SecureBackupEnterRecoveryKeyState,
|
||||||
onSuccess: () -> Unit,
|
onSuccess: () -> Unit,
|
||||||
onBackClick: () -> Unit,
|
onBackClick: () -> Unit,
|
||||||
onCreateNewRecoveryKey: () -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
AsyncActionView(
|
AsyncActionView(
|
||||||
|
|
@ -60,7 +58,7 @@ fun SecureBackupEnterRecoveryKeyView(
|
||||||
iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()),
|
iconStyle = BigIcon.Style.Default(CompoundIcons.KeySolid()),
|
||||||
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),
|
||||||
buttons = { Buttons(state = state, onCreateRecoveryKey = onCreateNewRecoveryKey) }
|
buttons = { Buttons(state = state) }
|
||||||
) {
|
) {
|
||||||
Content(state = state)
|
Content(state = state)
|
||||||
}
|
}
|
||||||
|
|
@ -86,7 +84,6 @@ private fun Content(
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.Buttons(
|
private fun ColumnScope.Buttons(
|
||||||
state: SecureBackupEnterRecoveryKeyState,
|
state: SecureBackupEnterRecoveryKeyState,
|
||||||
onCreateRecoveryKey: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
text = stringResource(id = CommonStrings.action_continue),
|
text = stringResource(id = CommonStrings.action_continue),
|
||||||
|
|
@ -97,12 +94,6 @@ private fun ColumnScope.Buttons(
|
||||||
state.eventSink.invoke(SecureBackupEnterRecoveryKeyEvents.Submit)
|
state.eventSink.invoke(SecureBackupEnterRecoveryKeyEvents.Submit)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
TextButton(
|
|
||||||
text = stringResource(id = R.string.screen_recovery_key_confirm_lost_recovery_key),
|
|
||||||
enabled = !state.submitAction.isLoading(),
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = onCreateRecoveryKey,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
|
|
@ -114,6 +105,5 @@ internal fun SecureBackupEnterRecoveryKeyViewPreview(
|
||||||
state = state,
|
state = state,
|
||||||
onSuccess = {},
|
onSuccess = {},
|
||||||
onBackClick = {},
|
onBackClick = {},
|
||||||
onCreateNewRecoveryKey = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,18 +101,6 @@ class SecureBackupEnterRecoveryKeyViewTest {
|
||||||
recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.Submit)
|
recorder.assertSingle(SecureBackupEnterRecoveryKeyEvents.Submit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
@Config(qualifiers = "h1024dp")
|
|
||||||
fun `tapping on Lost your recovery key - calls onCreateNewRecoveryKey`() {
|
|
||||||
ensureCalledOnce { callback ->
|
|
||||||
rule.setSecureBackupEnterRecoveryKeyView(
|
|
||||||
aSecureBackupEnterRecoveryKeyState(),
|
|
||||||
onCreateNewRecoveryKey = callback,
|
|
||||||
)
|
|
||||||
rule.clickOn(R.string.screen_recovery_key_confirm_lost_recovery_key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when submit action succeeds - calls onDone`() {
|
fun `when submit action succeeds - calls onDone`() {
|
||||||
ensureCalledOnce { callback ->
|
ensureCalledOnce { callback ->
|
||||||
|
|
@ -127,14 +115,12 @@ class SecureBackupEnterRecoveryKeyViewTest {
|
||||||
state: SecureBackupEnterRecoveryKeyState,
|
state: SecureBackupEnterRecoveryKeyState,
|
||||||
onDone: () -> Unit = EnsureNeverCalled(),
|
onDone: () -> Unit = EnsureNeverCalled(),
|
||||||
onBackClick: () -> Unit = EnsureNeverCalled(),
|
onBackClick: () -> Unit = EnsureNeverCalled(),
|
||||||
onCreateNewRecoveryKey: () -> Unit = EnsureNeverCalled(),
|
|
||||||
) {
|
) {
|
||||||
setContent {
|
setContent {
|
||||||
SecureBackupEnterRecoveryKeyView(
|
SecureBackupEnterRecoveryKeyView(
|
||||||
state = state,
|
state = state,
|
||||||
onSuccess = onDone,
|
onSuccess = onDone,
|
||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
onCreateNewRecoveryKey = onCreateNewRecoveryKey
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue