[#1286] Remove Seed Copy Button

* [#1286] New wallet screen: Copy seed only in debug

* [#1286] Seed screen: Copy seed only in debug

* Changelog update
This commit is contained in:
Honza Rychnovský 2024-03-13 15:49:10 +01:00 committed by GitHub
parent fd7703e005
commit d309da9287
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 164 additions and 134 deletions

View File

@ -22,6 +22,9 @@ directly impact users rather than highlighting other key architectural updates.*
### Fixed
- Button sizing has been updated to align with the design guidelines and preserve stretching if necessary
### Removed
- The seed copy feature from the New wallet recovery and Seed recovery screens has been removed for security reasons
## [0.2.0 (560)] - 2024-02-27
### Added

View File

@ -38,8 +38,9 @@ private fun ComposablePreview() {
@Composable
fun ChipGrid(
wordList: ImmutableList<String>,
onGridClick: () -> Unit,
modifier: Modifier = Modifier,
onGridClick: () -> Unit
allowCopy: Boolean = false,
) {
val interactionSource = remember { MutableInteractionSource() }
@ -51,13 +52,20 @@ fun ChipGrid(
modifier =
Modifier
.wrapContentWidth()
.clickable(
interactionSource = interactionSource,
// Disable ripple
indication = null,
onClick = onGridClick
)
.testTag(CommonTag.CHIP_LAYOUT)
.then(
if (allowCopy) {
Modifier
.clickable(
interactionSource = interactionSource,
// Disable ripple
indication = null,
onClick = onGridClick
)
} else {
Modifier
}
)
) {
wordList.chunked(CHIP_GRID_COLUMN_SIZE).forEachIndexed { chunkIndex, chunk ->
// TODO [#1043]: Correctly align numbers and words on Recovery screen

View File

@ -3,23 +3,18 @@ package co.electriccoin.zcash.ui.screen.newwalletrecovery.view
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import java.util.concurrent.atomic.AtomicInteger
class NewWalletRecoveryTestSetup(
private val composeTestRule: ComposeContentTestRule,
private val versionInfo: VersionInfo,
) {
private val onSeedCopyCount = AtomicInteger(0)
private val onBirthdayCopyCount = AtomicInteger(0)
private val onCompleteCallbackCount = AtomicInteger(0)
fun getOnSeedCopyCount(): Int {
composeTestRule.waitForIdle()
return onSeedCopyCount.get()
}
fun getOnBirthdayCopyCount(): Int {
composeTestRule.waitForIdle()
return onBirthdayCopyCount.get()
@ -36,9 +31,10 @@ class NewWalletRecoveryTestSetup(
ZcashTheme {
NewWalletRecovery(
PersistableWalletFixture.new(),
onSeedCopy = { onSeedCopyCount.incrementAndGet() },
onSeedCopy = { /* Not tested - debug mode feature only */ },
onBirthdayCopy = { onBirthdayCopyCount.incrementAndGet() },
onComplete = { onCompleteCallbackCount.incrementAndGet() },
versionInfo = versionInfo,
)
}
}

View File

@ -11,6 +11,7 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
import co.electriccoin.zcash.ui.design.component.CommonTag
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import co.electriccoin.zcash.ui.test.getStringResource
import org.junit.Rule
import kotlin.test.Test
@ -21,7 +22,10 @@ class NewWalletRecoveryViewTest : UiTestPrerequisites() {
val composeTestRule = createComposeRule()
private fun newTestSetup(): NewWalletRecoveryTestSetup {
return NewWalletRecoveryTestSetup(composeTestRule).apply {
return NewWalletRecoveryTestSetup(
composeTestRule,
VersionInfoFixture.new()
).apply {
setDefaultContent()
}
}
@ -31,14 +35,9 @@ class NewWalletRecoveryViewTest : UiTestPrerequisites() {
fun default_ui_state_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
composeTestRule.onNodeWithText(getStringResource(R.string.new_wallet_recovery_copy)).also {
it.assertExists()
}
composeTestRule.onNodeWithContentDescription(
label = getStringResource(R.string.zcash_logo_content_description)
).also {
@ -69,40 +68,10 @@ class NewWalletRecoveryViewTest : UiTestPrerequisites() {
it.assertExists()
}
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
}
@Test
@MediumTest
fun copy_seed_to_clipboard_from_app_bar_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
composeTestRule.onNodeWithText(getStringResource(R.string.new_wallet_recovery_copy)).also { menuButton ->
menuButton.performClick()
}
assertEquals(1, testSetup.getOnSeedCopyCount())
}
@Test
@MediumTest
fun copy_seed_to_clipboard_content_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
composeTestRule.onNodeWithTag(CommonTag.CHIP_LAYOUT).also {
it.performScrollTo()
it.performClick()
}
assertEquals(1, testSetup.getOnSeedCopyCount())
}
@Test
@MediumTest
fun copy_birthday_to_clipboard_content_test() {
@ -123,7 +92,6 @@ class NewWalletRecoveryViewTest : UiTestPrerequisites() {
fun click_finish_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
@ -135,7 +103,6 @@ class NewWalletRecoveryViewTest : UiTestPrerequisites() {
it.performClick()
}
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(1, testSetup.getOnCompleteCount())
}

View File

@ -9,6 +9,7 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.common.compose.LocalScreenSecurity
import co.electriccoin.zcash.ui.common.compose.ScreenSecurity
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -45,7 +46,8 @@ class NewWalletRecoveryViewsSecuredScreenTest : UiTestPrerequisites() {
PersistableWalletFixture.new(),
onSeedCopy = {},
onBirthdayCopy = {},
onComplete = {}
onComplete = {},
versionInfo = VersionInfoFixture.new()
)
}
}

View File

@ -3,25 +3,20 @@ package co.electriccoin.zcash.ui.screen.seedrecovery.view
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import cash.z.ecc.sdk.fixture.PersistableWalletFixture
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import java.util.concurrent.atomic.AtomicInteger
class SeedRecoveryTestSetup(
private val composeTestRule: ComposeContentTestRule,
private val versionInfo: VersionInfo,
) {
private val onSeedCopyCount = AtomicInteger(0)
private val onBirthdayCopyCount = AtomicInteger(0)
private val onCompleteCallbackCount = AtomicInteger(0)
private val onBackCount = AtomicInteger(0)
fun getOnSeedCopyCount(): Int {
composeTestRule.waitForIdle()
return onSeedCopyCount.get()
}
fun getOnBirthdayCopyCount(): Int {
composeTestRule.waitForIdle()
return onBirthdayCopyCount.get()
@ -44,9 +39,10 @@ class SeedRecoveryTestSetup(
SeedRecovery(
PersistableWalletFixture.new(),
onBack = { onBackCount.incrementAndGet() },
onSeedCopy = { onSeedCopyCount.incrementAndGet() },
onSeedCopy = { /* Not tested - debug mode feature only */ },
onBirthdayCopy = { onBirthdayCopyCount.incrementAndGet() },
onDone = { onCompleteCallbackCount.incrementAndGet() },
versionInfo = versionInfo,
)
}
}

View File

@ -11,6 +11,7 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
import co.electriccoin.zcash.ui.design.component.CommonTag
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import co.electriccoin.zcash.ui.test.getStringResource
import org.junit.Rule
import kotlin.test.Test
@ -21,7 +22,10 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
val composeTestRule = createComposeRule()
private fun newTestSetup(): SeedRecoveryTestSetup {
return SeedRecoveryTestSetup(composeTestRule).apply {
return SeedRecoveryTestSetup(
composeTestRule,
VersionInfoFixture.new()
).apply {
setDefaultContent()
}
}
@ -31,7 +35,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
fun default_ui_state_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
assertEquals(0, testSetup.getOnBackCount())
@ -41,10 +44,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
it.assertExists()
}
composeTestRule.onNodeWithText(getStringResource(R.string.seed_recovery_copy)).also {
it.assertExists()
}
composeTestRule.onNodeWithContentDescription(
label = getStringResource(R.string.zcash_logo_content_description)
).also {
@ -75,7 +74,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
it.assertExists()
}
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
assertEquals(0, testSetup.getOnBackCount())
@ -96,35 +94,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
assertEquals(1, testSetup.getOnBackCount())
}
@Test
@MediumTest
fun copy_seed_to_clipboard_from_app_bar_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
composeTestRule.onNodeWithText(getStringResource(R.string.seed_recovery_copy)).also { menuButton ->
menuButton.performClick()
}
assertEquals(1, testSetup.getOnSeedCopyCount())
}
@Test
@MediumTest
fun copy_seed_to_clipboard_content_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
composeTestRule.onNodeWithTag(CommonTag.CHIP_LAYOUT).also {
it.performScrollTo()
it.performClick()
}
assertEquals(1, testSetup.getOnSeedCopyCount())
}
@Test
@MediumTest
fun copy_birthday_to_clipboard_content_test() {
@ -145,7 +114,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
fun click_finish_test() {
val testSetup = newTestSetup()
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(0, testSetup.getOnCompleteCount())
@ -157,7 +125,6 @@ class SeedRecoveryViewTest : UiTestPrerequisites() {
it.performClick()
}
assertEquals(0, testSetup.getOnSeedCopyCount())
assertEquals(0, testSetup.getOnBirthdayCopyCount())
assertEquals(1, testSetup.getOnCompleteCount())
}

View File

@ -9,6 +9,7 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.common.compose.LocalScreenSecurity
import co.electriccoin.zcash.ui.common.compose.ScreenSecurity
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -46,7 +47,8 @@ class SeedRecoveryViewsSecuredScreenTest : UiTestPrerequisites() {
onBack = {},
onSeedCopy = {},
onBirthdayCopy = {},
onDone = {}
onDone = {},
versionInfo = VersionInfoFixture.new()
)
}
}

View File

@ -6,6 +6,7 @@ import cash.z.ecc.android.sdk.model.PersistableWallet
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.screen.newwalletrecovery.view.NewWalletRecovery
@Composable
@ -22,6 +23,8 @@ private fun WrapNewWalletRecovery(
persistableWallet: PersistableWallet,
onBackupComplete: () -> Unit
) {
val versionInfo = VersionInfo.new(activity.applicationContext)
NewWalletRecovery(
persistableWallet,
onSeedCopy = {
@ -38,6 +41,7 @@ private fun WrapNewWalletRecovery(
persistableWallet.birthday?.value.toString()
)
},
onComplete = onBackupComplete
onComplete = onBackupComplete,
versionInfo = versionInfo
)
}

View File

@ -4,5 +4,5 @@ package co.electriccoin.zcash.ui.screen.newwalletrecovery.view
* These are only used for automated testing.
*/
object NewWalletRecoveryTag {
const val WALLET_BIRTHDAY = "wallet_birthday"
const val DEBUG_MENU_TAG = "debug_menu"
}

View File

@ -15,9 +15,20 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@ -30,16 +41,17 @@ import cash.z.ecc.sdk.fixture.PersistableWalletFixture
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.SecureScreen
import co.electriccoin.zcash.ui.common.compose.shouldSecureScreen
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.BodySmall
import co.electriccoin.zcash.ui.design.component.ChipGrid
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import kotlinx.collections.immutable.toPersistentList
@Preview(name = "NewWalletRecovery", device = Devices.PIXEL_4)
@ -52,6 +64,7 @@ private fun ComposablePreview() {
onSeedCopy = {},
onBirthdayCopy = {},
onComplete = {},
versionInfo = VersionInfoFixture.new(),
)
}
}
@ -69,11 +82,13 @@ fun NewWalletRecovery(
onSeedCopy: () -> Unit,
onBirthdayCopy: () -> Unit,
onComplete: () -> Unit,
versionInfo: VersionInfo,
) {
Scaffold(
topBar = {
NewWalletRecoveryTopAppBar(
onSeedCopy = onSeedCopy,
versionInfo = versionInfo,
)
}
) { paddingValues ->
@ -82,6 +97,7 @@ fun NewWalletRecovery(
onComplete = onComplete,
onSeedCopy = onSeedCopy,
onBirthdayCopy = onBirthdayCopy,
versionInfo = versionInfo,
// Horizontal paddings will be part of each UI element to minimize a possible truncation on very
// small screens
modifier =
@ -95,38 +111,54 @@ fun NewWalletRecovery(
@Composable
private fun NewWalletRecoveryTopAppBar(
versionInfo: VersionInfo,
modifier: Modifier = Modifier,
onSeedCopy: () -> Unit
) {
SmallTopAppBar(
modifier = modifier,
regularActions = {
NewWalletRecoveryCopyToBufferMenuItem(
onCopyToClipboard = onSeedCopy
)
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
DebugMenu(onCopyToClipboard = onSeedCopy)
}
}
)
}
@Composable
private fun NewWalletRecoveryCopyToBufferMenuItem(
modifier: Modifier = Modifier,
onCopyToClipboard: () -> Unit,
) {
Reference(
text = stringResource(id = R.string.new_wallet_recovery_copy),
onClick = onCopyToClipboard,
textAlign = TextAlign.Center,
modifier = modifier.padding(all = ZcashTheme.dimens.spacingDefault)
)
private fun DebugMenu(onCopyToClipboard: () -> Unit) {
Column(
modifier = Modifier.testTag(NewWalletRecoveryTag.DEBUG_MENU_TAG)
) {
var expanded by rememberSaveable { mutableStateOf(false) }
IconButton(onClick = { expanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = {
Text(stringResource(id = R.string.new_wallet_recovery_copy))
},
onClick = {
onCopyToClipboard()
expanded = false
}
)
}
}
}
@Composable
@Suppress("LongParameterList")
private fun NewWalletRecoveryMainContent(
wallet: PersistableWallet,
onSeedCopy: () -> Unit,
onBirthdayCopy: () -> Unit,
onComplete: () -> Unit,
versionInfo: VersionInfo,
modifier: Modifier = Modifier,
) {
Column(
@ -156,6 +188,7 @@ private fun NewWalletRecoveryMainContent(
persistableWallet = wallet,
onSeedCopy = onSeedCopy,
onBirthdayCopy = onBirthdayCopy,
versionInfo = versionInfo
)
Spacer(
@ -187,6 +220,7 @@ private fun NewWalletRecoverySeedPhrase(
persistableWallet: PersistableWallet,
onSeedCopy: () -> Unit,
onBirthdayCopy: () -> Unit,
versionInfo: VersionInfo,
) {
if (shouldSecureScreen) {
SecureScreen()
@ -195,7 +229,8 @@ private fun NewWalletRecoverySeedPhrase(
Column {
ChipGrid(
wordList = persistableWallet.seedPhrase.split.toPersistentList(),
onGridClick = onSeedCopy
onGridClick = onSeedCopy,
allowCopy = versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
@ -26,6 +27,8 @@ private fun WrapSeedRecovery(
goBack: () -> Unit,
onDone: () -> Unit
) {
val versionInfo = VersionInfo.new(activity.applicationContext)
val walletViewModel by activity.viewModels<WalletViewModel>()
val persistableWallet =
@ -62,7 +65,8 @@ private fun WrapSeedRecovery(
persistableWallet.birthday?.value.toString()
)
},
onDone = onDone
onDone = onDone,
versionInfo = versionInfo,
)
}
}

View File

@ -0,0 +1,8 @@
package co.electriccoin.zcash.ui.screen.seedrecovery.view
/**
* These are only used for automated testing.
*/
object SeedRecoveryTag {
const val DEBUG_MENU_TAG = "debug_menu"
}

View File

@ -15,9 +15,20 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@ -30,16 +41,17 @@ import cash.z.ecc.sdk.fixture.PersistableWalletFixture
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.SecureScreen
import co.electriccoin.zcash.ui.common.compose.shouldSecureScreen
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.common.test.CommonTag.WALLET_BIRTHDAY
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.BodySmall
import co.electriccoin.zcash.ui.design.component.ChipGrid
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
import kotlinx.collections.immutable.toPersistentList
@Preview(name = "SeedRecovery", device = Devices.PIXEL_4)
@ -53,6 +65,7 @@ private fun ComposablePreview() {
onBirthdayCopy = {},
onDone = {},
onSeedCopy = {},
versionInfo = VersionInfoFixture.new(),
)
}
}
@ -65,18 +78,21 @@ private fun ComposablePreview() {
* @param onDone Callback when the user has confirmed viewing the seed phrase.
*/
@Composable
@Suppress("LongParameterList")
fun SeedRecovery(
wallet: PersistableWallet,
onBack: () -> Unit,
onBirthdayCopy: () -> Unit,
onDone: () -> Unit,
onSeedCopy: () -> Unit,
versionInfo: VersionInfo,
) {
Scaffold(
topBar = {
SeedRecoveryTopAppBar(
onBack = onBack,
onSeedCopy = onSeedCopy,
versionInfo = versionInfo,
)
}
) { paddingValues ->
@ -85,6 +101,7 @@ fun SeedRecovery(
onDone = onDone,
onSeedCopy = onSeedCopy,
onBirthdayCopy = onBirthdayCopy,
versionInfo = versionInfo,
// Horizontal paddings will be part of each UI element to minimize a possible truncation on very
// small screens
modifier =
@ -100,6 +117,7 @@ fun SeedRecovery(
private fun SeedRecoveryTopAppBar(
onBack: () -> Unit,
onSeedCopy: () -> Unit,
versionInfo: VersionInfo,
modifier: Modifier = Modifier,
) {
SmallTopAppBar(
@ -108,32 +126,49 @@ private fun SeedRecoveryTopAppBar(
backContentDescriptionText = stringResource(R.string.seed_recovery_back_content_description),
onBack = onBack,
regularActions = {
SeedRecoveryCopyToBufferMenuItem(
onCopyToClipboard = onSeedCopy
)
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
DebugMenu(
onCopyToClipboard = onSeedCopy
)
}
}
)
}
@Composable
private fun SeedRecoveryCopyToBufferMenuItem(
modifier: Modifier = Modifier,
onCopyToClipboard: () -> Unit,
) {
Reference(
text = stringResource(id = R.string.seed_recovery_copy),
onClick = onCopyToClipboard,
textAlign = TextAlign.Center,
modifier = modifier.padding(all = ZcashTheme.dimens.spacingDefault)
)
private fun DebugMenu(onCopyToClipboard: () -> Unit) {
Column(
modifier = Modifier.testTag(SeedRecoveryTag.DEBUG_MENU_TAG)
) {
var expanded by rememberSaveable { mutableStateOf(false) }
IconButton(onClick = { expanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = {
Text(stringResource(id = R.string.seed_recovery_copy))
},
onClick = {
onCopyToClipboard()
expanded = false
}
)
}
}
}
@Composable
@Suppress("LongParameterList")
private fun SeedRecoveryMainContent(
wallet: PersistableWallet,
onSeedCopy: () -> Unit,
onBirthdayCopy: () -> Unit,
onDone: () -> Unit,
versionInfo: VersionInfo,
modifier: Modifier = Modifier,
) {
Column(
@ -163,6 +198,7 @@ private fun SeedRecoveryMainContent(
persistableWallet = wallet,
onSeedCopy = onSeedCopy,
onBirthdayCopy = onBirthdayCopy,
versionInfo = versionInfo,
)
Spacer(
@ -194,6 +230,7 @@ private fun SeedRecoverySeedPhrase(
persistableWallet: PersistableWallet,
onSeedCopy: () -> Unit,
onBirthdayCopy: () -> Unit,
versionInfo: VersionInfo,
) {
if (shouldSecureScreen) {
SecureScreen()
@ -202,7 +239,8 @@ private fun SeedRecoverySeedPhrase(
Column {
ChipGrid(
wordList = persistableWallet.seedPhrase.split.toPersistentList(),
onGridClick = onSeedCopy
onGridClick = onSeedCopy,
allowCopy = versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))