diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Button.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Button.kt index 0ea9aee1..37c49a58 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Button.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Button.kt @@ -1,6 +1,7 @@ package co.electriccoin.zcash.ui.design.component import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button @@ -34,6 +35,10 @@ fun PrimaryButton( onClick: () -> Unit, text: String, modifier: Modifier = Modifier, + outerPaddingValues: PaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingSmall + ), enabled: Boolean = true ) { Button( @@ -41,7 +46,7 @@ fun PrimaryButton( modifier = modifier.then( Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(outerPaddingValues) ), enabled = enabled, colors = buttonColors(containerColor = MaterialTheme.colorScheme.primary) @@ -59,6 +64,10 @@ fun SecondaryButton( onClick: () -> Unit, text: String, modifier: Modifier = Modifier, + outerPaddingValues: PaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingSmall + ), enabled: Boolean = true ) { Button( @@ -66,7 +75,7 @@ fun SecondaryButton( modifier = modifier.then( Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(outerPaddingValues) ), enabled = enabled, colors = buttonColors(containerColor = MaterialTheme.colorScheme.secondary) @@ -83,13 +92,17 @@ fun SecondaryButton( fun NavigationButton( onClick: () -> Unit, text: String, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + outerPaddingValues: PaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingSmall + ), ) { Button( onClick = onClick, modifier = modifier.then( Modifier - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(outerPaddingValues) ), colors = buttonColors(containerColor = MaterialTheme.colorScheme.secondary) ) { @@ -102,6 +115,10 @@ fun TertiaryButton( onClick: () -> Unit, text: String, modifier: Modifier = Modifier, + outerPaddingValues: PaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingSmall + ), enabled: Boolean = true ) { Button( @@ -109,7 +126,7 @@ fun TertiaryButton( modifier = modifier.then( Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(outerPaddingValues) ), enabled = enabled, elevation = ButtonDefaults.buttonElevation(0.dp, 0.dp, 0.dp), @@ -127,14 +144,18 @@ fun TertiaryButton( fun DangerousButton( onClick: () -> Unit, text: String, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + outerPaddingValues: PaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingSmall + ), ) { Button( onClick = onClick, modifier = modifier.then( Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) + .padding(outerPaddingValues) ), colors = buttonColors(containerColor = ZcashTheme.colors.dangerous) ) { diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/SwitchWithLabel.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/SwitchWithLabel.kt index f40b3836..f41bcc5a 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/SwitchWithLabel.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/SwitchWithLabel.kt @@ -46,7 +46,7 @@ fun SwitchWithLabel( ) Spacer( modifier = Modifier - .width(ZcashTheme.paddings.padding) + .width(ZcashTheme.dimens.spacingDefault) .constrainAs(spacer) { top.linkTo(parent.top) bottom.linkTo(parent.top) diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Text.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Text.kt index b97459e4..ce865e9a 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Text.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/Text.kt @@ -22,10 +22,10 @@ fun Header( ) { Text( text = text, - textAlign = textAlign, - style = MaterialTheme.typography.headlineLarge, color = color, - modifier = modifier + textAlign = textAlign, + modifier = modifier, + style = MaterialTheme.typography.headlineLarge, ) } @@ -34,14 +34,14 @@ fun Body( text: String, modifier: Modifier = Modifier, textAlign: TextAlign = TextAlign.Start, - color: Color = MaterialTheme.colorScheme.onBackground + color: Color = MaterialTheme.colorScheme.onBackground, ) { Text( text = text, - textAlign = textAlign, - style = MaterialTheme.typography.bodyLarge, color = color, - modifier = modifier + textAlign = textAlign, + modifier = modifier, + style = MaterialTheme.typography.bodyLarge, ) } @@ -49,14 +49,15 @@ fun Body( fun Small( text: String, modifier: Modifier = Modifier, - textAlign: TextAlign = TextAlign.Start + textAlign: TextAlign = TextAlign.Start, + color: Color = MaterialTheme.colorScheme.onBackground, ) { Text( text = text, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onBackground, + color = color, + textAlign = textAlign, modifier = modifier, - textAlign = textAlign + style = MaterialTheme.typography.bodyMedium, ) } @@ -81,7 +82,7 @@ fun ListHeader( Text( text = text, style = ZcashTheme.typography.listItem, - color = MaterialTheme.colorScheme.onBackground, + color = ZcashTheme.colors.onBackgroundHeader, modifier = modifier ) } diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/TextField.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/TextField.kt index de9d669e..7c467f5f 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/TextField.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/component/TextField.kt @@ -1,5 +1,6 @@ package co.electriccoin.zcash.ui.design.component +import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.TextField @@ -8,6 +9,7 @@ import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.input.KeyboardType @Suppress("LongParameterList") @@ -23,7 +25,9 @@ fun FormTextField( keyboardOptions: KeyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), colors: TextFieldColors = TextFieldDefaults.textFieldColors( containerColor = Color.Transparent - ) + ), + keyboardActions: KeyboardActions = KeyboardActions.Default, + shape: Shape = TextFieldDefaults.filledShape ) { TextField( value = value, @@ -33,6 +37,8 @@ fun FormTextField( colors = colors, modifier = modifier, leadingIcon = leadingIcon, - trailingIcon = trailingIcon + trailingIcon = trailingIcon, + keyboardActions = keyboardActions, + shape = shape ) } diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/Dimens.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/Dimens.kt index 1ad55c24..d52df770 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/Dimens.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/Dimens.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.unit.dp @Immutable data class Dimens( // Default spacings: + val spacingNone: Dp, val spacingXtiny: Dp, val spacingTiny: Dp, val spacingSmall: Dp, @@ -22,6 +23,7 @@ data class Dimens( ) private val defaultDimens = Dimens( + spacingNone = 0.dp, spacingXtiny = 2.dp, spacingTiny = 4.dp, spacingSmall = 8.dp, diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/ZcashTheme.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/ZcashTheme.kt index 463f645b..7d1039a2 100644 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/ZcashTheme.kt +++ b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/ZcashTheme.kt @@ -11,7 +11,6 @@ import co.electriccoin.zcash.ui.design.theme.internal.LightColorPalette import co.electriccoin.zcash.ui.design.theme.internal.LightExtendedColorPalette import co.electriccoin.zcash.ui.design.theme.internal.LocalExtendedColors import co.electriccoin.zcash.ui.design.theme.internal.LocalExtendedTypography -import co.electriccoin.zcash.ui.design.theme.internal.Paddings import co.electriccoin.zcash.ui.design.theme.internal.Typography @Composable @@ -57,10 +56,4 @@ object ZcashTheme { val dimens: Dimens @Composable get() = LocalDimens.current - - // TODO [#807]: [Design system] Remove deprecated Paddings class - // TODO [#807]: https://github.com/zcash/secant-android-wallet/issues/807 - val paddings: Paddings - @Composable - get() = Paddings() } diff --git a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/internal/Paddings.kt b/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/internal/Paddings.kt deleted file mode 100644 index 55cb3fb3..00000000 --- a/ui-design-lib/src/main/java/co/electriccoin/zcash/ui/design/theme/internal/Paddings.kt +++ /dev/null @@ -1,10 +0,0 @@ -package co.electriccoin.zcash.ui.design.theme.internal - -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -data class Paddings( - val paddingHalf: Dp = 8.dp, - val padding: Dp = 16.dp, - val paddingDouble: Dp = 32.dp -) diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/AppUpdateCheckerImpTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/util/AppUpdateCheckerImpTest.kt similarity index 98% rename from ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/AppUpdateCheckerImpTest.kt rename to ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/util/AppUpdateCheckerImpTest.kt index 43bba052..278d0061 100644 --- a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/AppUpdateCheckerImpTest.kt +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/util/AppUpdateCheckerImpTest.kt @@ -1,4 +1,4 @@ -package co.electriccoin.zcash.ui.screen.update.view +package co.electriccoin.zcash.ui.screen.update.util import android.app.Activity import android.content.Context diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTest.kt new file mode 100644 index 00000000..d2925dd8 --- /dev/null +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTest.kt @@ -0,0 +1,75 @@ +package co.electriccoin.zcash.ui.screen.update.view + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.test.espresso.Espresso +import androidx.test.filters.MediumTest +import co.electriccoin.zcash.test.UiTestPrerequisites +import co.electriccoin.zcash.ui.R +import co.electriccoin.zcash.ui.fixture.UpdateInfoFixture +import co.electriccoin.zcash.ui.screen.update.AppUpdateChecker +import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo +import co.electriccoin.zcash.ui.screen.update.model.UpdateState +import co.electriccoin.zcash.ui.test.getStringResource +import org.junit.Rule +import org.junit.Test + +// Non-multiplatform tests that require interacting with the Android system (e.g. system back navigation) +// These don't have persistent state, so they are still unit tests. +class UpdateViewAndroidTest : UiTestPrerequisites() { + + @get:Rule + val composeTestRule = createAndroidComposeRule() + + private fun newTestSetup(updateInfo: UpdateInfo) = UpdateViewAndroidTestSetup( + composeTestRule, + updateInfo + ).apply { + setDefaultContent() + } + + @Test + @MediumTest + fun postpone_optional_update_test() { + val updateInfo = UpdateInfoFixture.new( + priority = AppUpdateChecker.Priority.LOW, + force = false, + appUpdateInfo = null, + state = UpdateState.Prepared + ) + newTestSetup(updateInfo) + + composeTestRule.onNodeWithText(getStringResource(R.string.update_header)).also { + it.assertExists() + } + + Espresso.pressBack() + + composeTestRule.onNodeWithText(getStringResource(R.string.update_header)).also { + it.assertDoesNotExist() + } + } + + @Test + @MediumTest + fun postpone_force_update_test() { + val updateInfo = UpdateInfoFixture.new( + priority = AppUpdateChecker.Priority.HIGH, + force = true, + appUpdateInfo = null, + state = UpdateState.Prepared + ) + newTestSetup(updateInfo) + + composeTestRule.onNodeWithText(getStringResource(R.string.update_critical_header)).also { + it.assertExists() + } + + Espresso.pressBack() + + composeTestRule.onNodeWithText(getStringResource(R.string.update_critical_header)).also { + it.assertExists() + } + } +} diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTestSetup.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTestSetup.kt new file mode 100644 index 00000000..4a5aad76 --- /dev/null +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewAndroidTestSetup.kt @@ -0,0 +1,29 @@ +package co.electriccoin.zcash.ui.screen.update.view + +import androidx.compose.runtime.Composable +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import co.electriccoin.zcash.ui.design.theme.ZcashTheme +import co.electriccoin.zcash.ui.screen.update.WrapUpdate +import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo + +class UpdateViewAndroidTestSetup( + private val composeTestRule: AndroidComposeTestRule<*, *>, + private val updateInfo: UpdateInfo +) { + @Composable + @Suppress("TestFunctionName") + fun DefaultContent() { + WrapUpdate( + composeTestRule.activity, + updateInfo + ) + } + + fun setDefaultContent() { + composeTestRule.setContent { + ZcashTheme { + DefaultContent() + } + } + } +} diff --git a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewTest.kt b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewTest.kt index 0467e5d5..d8890b25 100644 --- a/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewTest.kt +++ b/ui-lib/src/androidTest/java/co/electriccoin/zcash/ui/screen/update/view/UpdateViewTest.kt @@ -6,7 +6,6 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick -import androidx.test.espresso.Espresso import androidx.test.filters.MediumTest import co.electriccoin.zcash.test.UiTestPrerequisites import co.electriccoin.zcash.ui.R @@ -108,10 +107,6 @@ class UpdateViewTest : UiTestPrerequisites() { composeTestRule.clickLater() assertEquals(0, testSetup.getOnLaterCount()) - - Espresso.pressBack() - - assertEquals(0, testSetup.getOnLaterCount()) } @Test diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/about/view/AboutView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/about/view/AboutView.kt index da41b4b1..b6e045cf 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/about/view/AboutView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/about/view/AboutView.kt @@ -1,8 +1,8 @@ package co.electriccoin.zcash.ui.screen.about.view import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState @@ -20,7 +20,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp import co.electriccoin.zcash.build.gitSha import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.design.component.Body @@ -57,9 +56,19 @@ fun About( AboutTopAppBar(onBack = goBack) }) { paddingValues -> AboutMainContent( - paddingValues, versionInfo, - configInfo + configInfo, + modifier = Modifier + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) + .padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } } @@ -83,33 +92,33 @@ private fun AboutTopAppBar(onBack: () -> Unit) { } @Composable -fun AboutMainContent(paddingValues: PaddingValues, versionInfo: VersionInfo, configInfo: ConfigInfo) { - Column( - Modifier - .verticalScroll(rememberScrollState()) - .padding(top = paddingValues.calculateTopPadding()) - ) { +fun AboutMainContent( + versionInfo: VersionInfo, + configInfo: ConfigInfo, + modifier: Modifier = Modifier +) { + Column(modifier) { Icon(painterResource(id = R.drawable.ic_launcher_adaptive_foreground), contentDescription = null) Text(stringResource(id = R.string.app_name)) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) Header(stringResource(id = R.string.about_version_header)) Body(stringResource(R.string.about_version_format, versionInfo.versionName, versionInfo.versionCode)) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) Header(stringResource(id = R.string.about_build_header)) Body(gitSha) - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) configInfo.configurationUpdatedAt?.let { updatedAt -> Header(stringResource(id = R.string.about_build_configuration)) Body(updatedAt.toString()) } - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) Header(stringResource(id = R.string.about_legal_header)) Body(stringResource(id = R.string.about_legal_info)) diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/address/view/WalletAddressView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/address/view/WalletAddressView.kt index 3f205e91..a7e4b9e0 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/address/view/WalletAddressView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/address/view/WalletAddressView.kt @@ -12,9 +12,13 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowDropDownCircle @@ -66,7 +70,12 @@ fun ComposablePreview() { fun WalletAddresses(walletAddresses: WalletAddresses, onBack: () -> Unit) { Column { WalletDetailTopAppBar(onBack) - WalletDetailAddresses(walletAddresses) + WalletDetailAddresses( + walletAddresses, + Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + ) } } @@ -96,8 +105,11 @@ private val BIG_INDICATOR_WIDTH = 24.dp private val SMALL_INDICATOR_WIDTH = 16.dp @Composable -private fun WalletDetailAddresses(walletAddresses: WalletAddresses) { - Column(Modifier.fillMaxWidth()) { +private fun WalletDetailAddresses( + walletAddresses: WalletAddresses, + modifier: Modifier = Modifier +) { + Column(modifier) { Row( Modifier .fillMaxWidth() @@ -115,16 +127,36 @@ private fun WalletDetailAddresses(walletAddresses: WalletAddresses) { ExpandableRow( title = stringResource(R.string.wallet_address_unified), content = walletAddresses.unified.address, - isInitiallyExpanded = true + isInitiallyExpanded = true, + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingTiny + ) ) Box(Modifier.height(IntrinsicSize.Min)) { Divider(modifier = Modifier.fillMaxHeight()) - ListHeader(text = stringResource(R.string.wallet_address_header_includes)) + ListHeader( + text = stringResource(R.string.wallet_address_header_includes), + modifier = Modifier.padding(all = ZcashTheme.dimens.spacingSmall) + ) } - SaplingAddress(walletAddresses.sapling.address) - TransparentAddress(walletAddresses.transparent.address) + SaplingAddress( + saplingAddress = walletAddresses.sapling.address, + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + ) + + TransparentAddress( + transparentAddress = walletAddresses.transparent.address, + modifier = Modifier + .fillMaxWidth() + .height(IntrinsicSize.Min) + ) } } } @@ -135,34 +167,44 @@ private fun WalletDetailAddresses(walletAddresses: WalletAddresses) { // of row position will be needed. @Composable -private fun SaplingAddress(saplingAddress: String) { - Row( - Modifier - .fillMaxWidth() - .height(IntrinsicSize.Min) - ) { +private fun SaplingAddress( + saplingAddress: String, + modifier: Modifier = Modifier +) { + Row(modifier) { SmallIndicator(ZcashTheme.colors.addressHighlightSapling) ExpandableRow( title = stringResource(R.string.wallet_address_sapling), content = saplingAddress, - isInitiallyExpanded = false + isInitiallyExpanded = false, + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingTiny + ) ) } } @Composable -private fun TransparentAddress(transparentAddress: String) { - Row( - Modifier - .fillMaxWidth() - .height(IntrinsicSize.Min) - ) { +private fun TransparentAddress( + transparentAddress: String, + modifier: Modifier = Modifier +) { + Row(modifier) { SmallIndicator(ZcashTheme.colors.addressHighlightTransparent) ExpandableRow( title = stringResource(R.string.wallet_address_transparent), content = transparentAddress, - isInitiallyExpanded = false + isInitiallyExpanded = false, + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = ZcashTheme.dimens.spacingDefault, + vertical = ZcashTheme.dimens.spacingTiny + ) ) } } @@ -177,11 +219,9 @@ private fun ExpandableRow( var expandedState by rememberSaveable { mutableStateOf(isInitiallyExpanded) } Column( - modifier - .fillMaxWidth() - .clickable { - expandedState = !expandedState - } + Modifier + .clickable { expandedState = !expandedState } + .then(modifier) // To have proper ripple effect ) { Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.defaultMinSize(minHeight = 48.dp)) { ListItem(text = title) diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt index 880b028b..645fd3cf 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/LongNewWalletBackupView.kt @@ -201,7 +201,7 @@ private fun SeedPhrase(persistableWallet: PersistableWallet) { Column( Modifier .verticalScroll(rememberScrollState()) - .padding(vertical = ZcashTheme.paddings.padding) + .padding(vertical = ZcashTheme.dimens.spacingDefault) ) { Body(stringResource(R.string.new_wallet_3_body_1)) ChipGrid(persistableWallet.seedPhrase.split.toPersistentList()) @@ -248,7 +248,7 @@ private fun TestInProgress( Column( Modifier .verticalScroll(rememberScrollState()) - .padding(vertical = ZcashTheme.paddings.padding) + .padding(vertical = ZcashTheme.dimens.spacingDefault) ) { splitSeedPhrase.chunked(CHIP_GRID_ROW_SIZE).forEachIndexed { chunkIndex, chunk -> Row(Modifier.fillMaxWidth()) { diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt index 9d9eb1b8..a7f44941 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/backup/view/ShortNewWalletBackupView.kt @@ -3,7 +3,7 @@ package co.electriccoin.zcash.ui.screen.backup.view import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -74,23 +74,29 @@ fun ShortNewWalletBackup( } ) { paddingValues -> ShortNewWalletMainContent( - paddingValues = paddingValues, wallet = wallet, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } } @Composable private fun ShortNewWalletMainContent( - paddingValues: PaddingValues, wallet: PersistableWallet, + modifier: Modifier = Modifier, ) { Column( Modifier - .padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() + .fillMaxHeight() + .verticalScroll( + rememberScrollState() ) + .then(modifier) ) { SeedPhrase(wallet) } @@ -99,11 +105,7 @@ private fun ShortNewWalletMainContent( @Composable private fun SeedPhrase(persistableWallet: PersistableWallet) { SecureScreen() - Column( - Modifier - .verticalScroll(rememberScrollState()) - .padding(vertical = ZcashTheme.paddings.padding) - ) { + Column { Body(stringResource(R.string.new_wallet_short_body)) ChipGrid(persistableWallet.seedPhrase.split.toPersistentList()) } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/home/view/HomeView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/home/view/HomeView.kt index 9f1e6ce7..156e1d62 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/home/view/HomeView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/home/view/HomeView.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -145,7 +146,6 @@ fun Home( ) }) { paddingValues -> HomeMainContent( - paddingValues, walletSnapshot, transactionHistory, isUpdateAvailable = isUpdateAvailable, @@ -154,6 +154,12 @@ fun Home( isCircularProgressBarEnabled = isCircularProgressBarEnabled, goReceive = goReceive, goSend = goSend, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } } @@ -241,7 +247,7 @@ private fun HomeDrawer( ModalDrawerSheet( modifier = Modifier.testTag(HomeTag.DRAWER_MENU) ) { - Spacer(Modifier.height(12.dp)) + Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault)) NavigationDrawerItem( icon = { Icon(Icons.Default.Password, contentDescription = null) }, label = { Text(stringResource(id = R.string.home_menu_seed_phrase)) }, @@ -288,7 +294,6 @@ private fun HomeDrawer( @Suppress("LongParameterList") @Composable private fun HomeMainContent( - paddingValues: PaddingValues, walletSnapshot: WalletSnapshot, transactionHistory: ImmutableList, isUpdateAvailable: Boolean, @@ -297,18 +302,41 @@ private fun HomeMainContent( isCircularProgressBarEnabled: Boolean, goReceive: () -> Unit, goSend: () -> Unit, + modifier: Modifier = Modifier ) { Column( Modifier - .verticalScroll(rememberScrollState()) - .padding(top = paddingValues.calculateTopPadding()) + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) + .then(modifier) ) { Status(walletSnapshot, isUpdateAvailable, isFiatConversionEnabled, isCircularProgressBarEnabled) - Spacer(modifier = Modifier.height(24.dp)) + if (isSyncing(walletSnapshot.status)) { + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + Body(text = stringResource(id = R.string.home_information)) + } - PrimaryButton(onClick = goReceive, text = stringResource(R.string.home_button_receive)) - PrimaryButton(onClick = goSend, text = stringResource(R.string.home_button_send)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + + PrimaryButton( + onClick = goSend, + text = stringResource(R.string.home_button_send), + outerPaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingNone, + vertical = ZcashTheme.dimens.spacingSmall + ) + ) + PrimaryButton( + onClick = goReceive, + text = stringResource(R.string.home_button_receive), + outerPaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingNone, + vertical = ZcashTheme.dimens.spacingSmall + ) + ) History(transactionHistory) @@ -386,7 +414,7 @@ private fun Status( .wrapContentSize(), horizontalAlignment = Alignment.CenterHorizontally ) { - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) if (walletDisplayValues.zecAmountText.isNotEmpty()) { HeaderWithZecIcon(amount = walletDisplayValues.zecAmountText) @@ -394,7 +422,7 @@ private fun Status( if (isFiatConversionEnabled) { Column(Modifier.testTag(HomeTag.FIAT_CONVERSION)) { - Spacer(modifier = Modifier.height(8.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) when (walletDisplayValues.fiatCurrencyAmountState) { is FiatCurrencyConversionRateState.Current -> { @@ -415,7 +443,7 @@ private fun Status( } } - Spacer(modifier = Modifier.height(24.dp)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) if (walletDisplayValues.statusText.isNotEmpty()) { Body( diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/LongOnboardingView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/LongOnboardingView.kt index f45f70b9..afd3081e 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/LongOnboardingView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/LongOnboardingView.kt @@ -245,16 +245,16 @@ private fun Wallet(paddingValues: PaddingValues) { Column( Modifier .padding( - start = ZcashTheme.paddings.padding, - end = ZcashTheme.paddings.padding, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault, bottom = paddingValues.calculateBottomPadding() ) .fillMaxWidth() ) { Header( modifier = Modifier.padding( - top = ZcashTheme.paddings.padding, - bottom = ZcashTheme.paddings.paddingHalf + top = ZcashTheme.dimens.spacingDefault, + bottom = ZcashTheme.dimens.spacingSmall ), text = stringResource(R.string.onboarding_4_header) ) @@ -280,8 +280,8 @@ private fun Content( ) { Column( Modifier.padding( - start = ZcashTheme.paddings.padding, - end = ZcashTheme.paddings.padding, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault, bottom = paddingValues.calculateBottomPadding() ) ) { diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/ShortOnboardingView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/ShortOnboardingView.kt index 9947b092..a0ecfe07 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/ShortOnboardingView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/onboarding/view/ShortOnboardingView.kt @@ -4,8 +4,12 @@ package co.electriccoin.zcash.ui.screen.onboarding.view import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +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 @@ -25,6 +29,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import co.electriccoin.zcash.ui.R +import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT +import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.GradientSurface import co.electriccoin.zcash.ui.design.component.Header import co.electriccoin.zcash.ui.design.component.PrimaryButton @@ -64,9 +70,14 @@ fun ShortOnboarding( } ) { paddingValues -> OnboardingMainContent( - paddingValues, onImportWallet = onImportWallet, - onCreateWallet = onCreateWallet + onCreateWallet = onCreateWallet, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } } @@ -109,35 +120,47 @@ private fun DebugMenu(onFixtureWallet: () -> Unit) { @Composable private fun OnboardingMainContent( - paddingValues: PaddingValues, onImportWallet: () -> Unit, onCreateWallet: () -> Unit, + modifier: Modifier = Modifier ) { Column( - Modifier.padding(top = paddingValues.calculateTopPadding()) + Modifier + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) + .then(modifier) ) { - Column( - Modifier - .padding( - start = ZcashTheme.paddings.padding, - end = ZcashTheme.paddings.padding, - bottom = paddingValues.calculateBottomPadding() - ) - .fillMaxWidth() - ) { - Header( - modifier = Modifier.padding( - top = ZcashTheme.paddings.padding, - bottom = ZcashTheme.paddings.paddingHalf - ), - text = stringResource(R.string.onboarding_short_header) + Header(text = stringResource(R.string.onboarding_short_header)) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingXlarge)) + + Body(text = stringResource(R.string.onboarding_short_information)) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) + + Spacer( + modifier = Modifier + .fillMaxHeight() + .weight(MINIMAL_WEIGHT) + ) + + PrimaryButton( + onClick = onCreateWallet, + text = stringResource(R.string.onboarding_short_create_new_wallet), + outerPaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingNone, + vertical = ZcashTheme.dimens.spacingSmall ) - PrimaryButton(onCreateWallet, stringResource(R.string.onboarding_short_create_new_wallet), Modifier.fillMaxWidth()) - TertiaryButton( - onImportWallet, - stringResource(R.string.onboarding_short_import_existing_wallet), - Modifier.fillMaxWidth() + ) + TertiaryButton( + onImportWallet, + stringResource(R.string.onboarding_short_import_existing_wallet), + outerPaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingNone, + vertical = ZcashTheme.dimens.spacingSmall ) - } + ) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/receive/view/ReceiveView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/receive/view/ReceiveView.kt index e016dd5a..2affd68a 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/receive/view/ReceiveView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/receive/view/ReceiveView.kt @@ -2,6 +2,11 @@ package co.electriccoin.zcash.ui.screen.receive.view import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +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 @@ -26,8 +31,9 @@ import cash.z.ecc.android.sdk.model.WalletAddress import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.common.BrightenScreen import co.electriccoin.zcash.ui.common.DisableScreenTimeout -import co.electriccoin.zcash.ui.design.component.Body +import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.component.GradientSurface +import co.electriccoin.zcash.ui.design.component.Header import co.electriccoin.zcash.ui.design.component.PrimaryButton import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.screen.receive.util.AndroidQrCodeImageGenerator @@ -61,6 +67,10 @@ fun Receive( ReceiveContents( walletAddress = walletAddress, onAddressDetails = onAddressDetails, + modifier = Modifier + .fillMaxHeight() + .verticalScroll(rememberScrollState()) + .padding(all = ZcashTheme.dimens.spacingDefault) ) } } @@ -90,21 +100,42 @@ private val DEFAULT_QR_CODE_SIZE = 320.dp private fun ReceiveContents( walletAddress: WalletAddress, onAddressDetails: () -> Unit, + modifier: Modifier = Modifier ) { - Column(Modifier.verticalScroll(rememberScrollState())) { + Column(modifier) { QrCode(data = walletAddress.address, DEFAULT_QR_CODE_SIZE, Modifier.align(Alignment.CenterHorizontally)) - Body(text = stringResource(id = R.string.wallet_address_unified), Modifier.align(Alignment.CenterHorizontally)) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + + Header( + text = stringResource(id = R.string.wallet_address_unified), + Modifier.align(Alignment.CenterHorizontally) + ) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) + // TODO [#163]: Ellipsize center of the string // TODO [#163]: https://github.com/zcash/secant-android-wallet/issues/163 Text( text = walletAddress.address, - style = MaterialTheme.typography.headlineLarge, + style = MaterialTheme.typography.bodyLarge, color = MaterialTheme.colorScheme.onBackground, modifier = Modifier.align(Alignment.CenterHorizontally), overflow = TextOverflow.Ellipsis, maxLines = 1 ) - PrimaryButton(onClick = onAddressDetails, text = stringResource(id = R.string.receive_see_address_details)) + + Spacer( + modifier = Modifier + .fillMaxHeight() + .weight(MINIMAL_WEIGHT) + ) + + PrimaryButton( + onClick = onAddressDetails, + text = stringResource(id = R.string.receive_see_address_details), + outerPaddingValues = PaddingValues(all = ZcashTheme.dimens.spacingNone) + ) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt index d337a272..2dd41c4f 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/restore/view/RestoreView.kt @@ -5,10 +5,12 @@ package co.electriccoin.zcash.ui.screen.restore.view import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -64,6 +66,7 @@ import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.CHIP_GRID_ROW_SIZE import co.electriccoin.zcash.ui.design.component.Chip +import co.electriccoin.zcash.ui.design.component.FormTextField import co.electriccoin.zcash.ui.design.component.GradientSurface import co.electriccoin.zcash.ui.design.component.Header import co.electriccoin.zcash.ui.design.component.NavigationButton @@ -123,7 +126,6 @@ fun PreviewRestoreComplete() { } } -// TODO [#409]: https://github.com/zcash/secant-android-wallet/issues/409 /** * Note that the restore review doesn't allow the user to go back once the seed is entered correctly. * @@ -182,6 +184,15 @@ fun RestoreWallet( } }, content = { paddingValues -> + val commonModifier = Modifier + // We intentionally set the bottom smaller to save space in case of the software keyboard is visible + .padding( + top = paddingValues.calculateTopPadding() + dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + dimens.spacingSmall, + start = dimens.spacingDefault, + end = dimens.spacingDefault + ) + when (currentStage) { RestoreStage.Seed -> { SecureScreen() @@ -194,10 +205,7 @@ fun RestoreWallet( parseResult = parseResult, paste = paste, goNext = { restoreState.goNext() }, - modifier = Modifier.padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() - ) + modifier = commonModifier ) } RestoreStage.Birthday -> { @@ -206,10 +214,7 @@ fun RestoreWallet( initialRestoreHeight = restoreHeight, setRestoreHeight = setRestoreHeight, onNext = { restoreState.goNext() }, - modifier = Modifier.padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() - ) + modifier = commonModifier ) } RestoreStage.Complete -> { @@ -219,10 +224,7 @@ fun RestoreWallet( RestoreComplete( onComplete = onFinished, - modifier = Modifier.padding( - top = paddingValues.calculateTopPadding(), - bottom = paddingValues.calculateBottomPadding() - ) + modifier = commonModifier ) } } @@ -281,12 +283,14 @@ private fun RestoreSeedMainContent( val isSeedValid = userWordList.wordValidation().collectAsState(null).value is SeedPhraseValidation.Valid Column( - modifier.then(Modifier.verticalScroll(scrollState)) + Modifier + .fillMaxHeight() + .verticalScroll(scrollState) + .then(modifier) ) { - Body( - modifier = Modifier.padding(dimens.spacingDefault), - text = stringResource(id = R.string.restore_seed_instructions) - ) + Body(text = stringResource(id = R.string.restore_seed_instructions)) + + Spacer(Modifier.height(dimens.spacingSmall)) ChipGridWithText(currentUserWordList) @@ -299,12 +303,17 @@ private fun RestoreSeedMainContent( ) } - Spacer(modifier = Modifier.weight(MINIMAL_WEIGHT)) + Spacer( + modifier = Modifier + .fillMaxHeight() + .weight(MINIMAL_WEIGHT) + ) PrimaryButton( onClick = goNext, text = stringResource(id = R.string.restore_seed_button_restore), - enabled = isSeedValid + enabled = isSeedValid, + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) } @@ -338,7 +347,17 @@ private fun RestoreSeedBottomBar( // the user can hit the clear button if (!isSeedValid) { Column(modifier) { - Warn(parseResult) + Warn( + parseResult = parseResult, + modifier = Modifier + .fillMaxWidth() + // Note we don't set the top, as it's set by the confirm button above + .padding( + bottom = dimens.spacingDefault, + start = dimens.spacingDefault, + end = dimens.spacingDefault + ) + ) Autocomplete(parseResult = parseResult, { setTextState("") userWordList.append(listOf(it)) @@ -352,11 +371,7 @@ private fun RestoreSeedBottomBar( private fun ChipGridWithText( userWordList: ImmutableList ) { - Column( - Modifier - .padding(start = 12.dp, end = 12.dp) - .testTag(RestoreTag.CHIP_LAYOUT) - ) { + Column(Modifier.testTag(RestoreTag.CHIP_LAYOUT)) { userWordList.chunked(CHIP_GRID_ROW_SIZE).forEachIndexed { chunkIndex, chunk -> Row(Modifier.fillMaxWidth(), verticalAlignment = CenterVertically) { val remainder = (chunk.size % CHIP_GRID_ROW_SIZE) @@ -452,11 +467,20 @@ private fun Autocomplete( } @Suppress("ModifierReused") - LazyRow(highlightModifier.testTag(RestoreTag.AUTOCOMPLETE_LAYOUT)) { + LazyRow( + modifier = highlightModifier.testTag(RestoreTag.AUTOCOMPLETE_LAYOUT), + // Note we don't set the top, as it's set by the confirm button above + // And we also set the bottom smaller, as the keyboard will be always visible + contentPadding = PaddingValues( + bottom = dimens.spacingDefault, + start = dimens.spacingDefault, + end = dimens.spacingSmall + ) + ) { items(it) { Chip( text = it, - modifier = modifier + modifier = Modifier .testTag(RestoreTag.AUTOCOMPLETE_ITEM) .clickable { onSuggestionSelected(it) } ) @@ -466,12 +490,13 @@ private fun Autocomplete( } @Composable -private fun Warn(parseResult: ParseResult) { +private fun Warn( + parseResult: ParseResult, + modifier: Modifier = Modifier +) { if (parseResult is ParseResult.Warn) { Surface( - modifier = Modifier - .fillMaxWidth() - .padding(dimens.spacingTiny), + modifier = modifier, shape = RoundedCornerShape(8.dp), color = MaterialTheme.colorScheme.secondary, shadowElevation = 4.dp @@ -491,8 +516,8 @@ private fun Warn(parseResult: ParseResult) { } } -@OptIn(ExperimentalMaterial3Api::class) @Composable +@Suppress("LongMethod") private fun RestoreBirthday( zcashNetwork: ZcashNetwork, initialRestoreHeight: BlockHeight?, @@ -503,12 +528,22 @@ private fun RestoreBirthday( val (height, setHeight) = rememberSaveable { mutableStateOf(initialRestoreHeight?.value?.toString() ?: "") } - val scrollState = rememberScrollState() - Column(modifier.verticalScroll(scrollState)) { + Column( + Modifier + .fillMaxHeight() + .verticalScroll(rememberScrollState()) + .then(modifier) + ) { Header(stringResource(R.string.restore_birthday_header)) + + Spacer(modifier = Modifier.height(dimens.spacingDefault)) + Body(stringResource(R.string.restore_birthday_body)) - TextField( + + Spacer(modifier = Modifier.height(dimens.spacingDefault)) + + FormTextField( value = height, onValueChange = { heightString -> val filteredHeightString = heightString.filter { it.isDigit() } @@ -528,8 +563,10 @@ private fun RestoreBirthday( keyboardActions = KeyboardActions(onAny = {}), shape = RoundedCornerShape(8.dp), ) + Spacer( modifier = Modifier + .fillMaxHeight() .weight(MINIMAL_WEIGHT) ) @@ -543,28 +580,50 @@ private fun RestoreBirthday( onNext() }, text = stringResource(R.string.restore_birthday_button_restore), - enabled = isBirthdayValid + enabled = isBirthdayValid, + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) + TertiaryButton( onClick = { setRestoreHeight(null) onNext() }, - text = stringResource(R.string.restore_birthday_button_skip) + text = stringResource(R.string.restore_birthday_button_skip), + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) } } @Composable -private fun RestoreComplete(onComplete: () -> Unit, modifier: Modifier = Modifier) { - Column(modifier) { +private fun RestoreComplete( + onComplete: () -> Unit, + modifier: Modifier = Modifier +) { + Column( + Modifier + .fillMaxHeight() + .verticalScroll(rememberScrollState()) + .then(modifier) + ) { Header(stringResource(R.string.restore_complete_header)) + + Spacer(modifier = Modifier.height(dimens.spacingDefault)) + Body(stringResource(R.string.restore_complete_info)) + + Spacer(modifier = Modifier.height(dimens.spacingDefault)) + Spacer( modifier = Modifier .fillMaxHeight() .weight(MINIMAL_WEIGHT) ) - PrimaryButton(onComplete, stringResource(R.string.restore_button_see_wallet)) + + PrimaryButton( + onClick = onComplete, + text = stringResource(R.string.restore_button_see_wallet), + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) + ) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/view/ScanView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/view/ScanView.kt index 6048ecdc..5bda288b 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/view/ScanView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/view/ScanView.kt @@ -14,8 +14,10 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape @@ -37,7 +39,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment -import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onSizeChanged @@ -47,19 +48,19 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import androidx.core.content.ContextCompat import co.electriccoin.zcash.spackle.Twig import co.electriccoin.zcash.ui.R +import co.electriccoin.zcash.ui.design.component.Body import co.electriccoin.zcash.ui.design.component.GradientSurface import co.electriccoin.zcash.ui.design.component.SecondaryButton +import co.electriccoin.zcash.ui.design.component.Small import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.screen.scan.ScanTag import co.electriccoin.zcash.ui.screen.scan.model.ScanState @@ -108,12 +109,20 @@ fun Scan( snackbarHost = { SnackbarHost(snackbarHostState) } ) { paddingValues -> ScanMainContent( - paddingValues, onScanned, onOpenSettings, onBack, onScanStateChanged, - snackbarHostState + snackbarHostState, + modifier = Modifier + .fillMaxSize() + .background(Color.Black) + .padding( + top = paddingValues.calculateTopPadding(), + bottom = paddingValues.calculateBottomPadding(), + start = ZcashTheme.dimens.spacingNone, + end = ZcashTheme.dimens.spacingNone + ) ) } } @@ -121,41 +130,37 @@ fun Scan( @Composable fun ScanBottomItems( scanState: ScanState, - onOpenSettings: () -> Unit + onOpenSettings: () -> Unit, + modifier: Modifier = Modifier ) { - Column(modifier = Modifier.fillMaxWidth()) { - Text( + Column(modifier) { + Body( text = stringResource(id = R.string.scan_hint), - color = Color.White, - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier - .fillMaxWidth() - .align(CenterHorizontally) - .padding(horizontal = 24.dp, vertical = 8.dp) + color = Color.White ) - Text( + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall)) + + Small( text = when (scanState) { ScanState.Permission -> stringResource(id = R.string.scan_state_permission) ScanState.Scanning -> stringResource(id = R.string.scan_state_scanning) ScanState.Failed -> stringResource(id = R.string.scan_state_failed) }, color = Color.White, - fontSize = 16.sp, - modifier = Modifier - .fillMaxWidth() - .align(CenterHorizontally) - .padding(horizontal = 24.dp, vertical = 8.dp) - .testTag(ScanTag.TEXT_STATE) + modifier = Modifier.testTag(ScanTag.TEXT_STATE) ) if (scanState == ScanState.Permission) { + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) + SecondaryButton( onClick = onOpenSettings, text = stringResource(id = R.string.scan_settings_button), - modifier = Modifier - .padding(horizontal = 24.dp, vertical = 12.dp) + outerPaddingValues = PaddingValues( + vertical = ZcashTheme.dimens.spacingSmall, + horizontal = ZcashTheme.dimens.spacingNone + ) ) } } @@ -183,12 +188,12 @@ private fun ScanTopAppBar(onBack: () -> Unit) { @Suppress("MagicNumber", "LongMethod", "LongParameterList") @Composable private fun ScanMainContent( - paddingValues: PaddingValues, onScanned: (String) -> Unit, onOpenSettings: () -> Unit, onBack: () -> Unit, onScanStateChanged: (ScanState) -> Unit, - snackbarHostState: SnackbarHostState + snackbarHostState: SnackbarHostState, + modifier: Modifier = Modifier ) { val context = LocalContext.current @@ -234,12 +239,7 @@ private fun ScanMainContent( (framePossibleSize.value.width * 0.7).roundToInt() } - ConstraintLayout( - modifier = Modifier - .fillMaxSize() - .background(Color.Black) - .padding(top = paddingValues.calculateTopPadding()) - ) { + ConstraintLayout(modifier) { val (frame, bottomItems) = createRefs() when (scanState) { @@ -292,7 +292,16 @@ private fun ScanMainContent( } Box(modifier = Modifier.constrainAs(bottomItems) { bottom.linkTo(parent.bottom) }) { - ScanBottomItems(scanState, onOpenSettings) + ScanBottomItems( + scanState = scanState, + onOpenSettings = onOpenSettings, + modifier = Modifier + .fillMaxWidth() + .padding( + vertical = ZcashTheme.dimens.spacingDefault, + horizontal = ZcashTheme.dimens.spacingDefault + ) + ) } } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt index 07b1ff33..841d4ecb 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/seed/view/SeedView.kt @@ -2,6 +2,9 @@ package co.electriccoin.zcash.ui.screen.seed.view import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -58,9 +61,14 @@ fun Seed( SeedTopAppBar(onBack = onBack) }) { paddingValues -> SeedMainContent( - paddingValues, persistableWallet = persistableWallet, - onCopyToClipboard = onCopyToClipboard + onCopyToClipboard = onCopyToClipboard, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } } @@ -85,19 +93,31 @@ private fun SeedTopAppBar(onBack: () -> Unit) { @Composable private fun SeedMainContent( - paddingValues: PaddingValues, persistableWallet: PersistableWallet, - onCopyToClipboard: () -> Unit + onCopyToClipboard: () -> Unit, + modifier: Modifier = Modifier ) { Column( Modifier - .verticalScroll(rememberScrollState()) - .padding(top = paddingValues.calculateTopPadding()) + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) + .then(modifier) ) { Body(stringResource(R.string.seed_body)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault)) + ChipGrid(persistableWallet.seedPhrase.split.toPersistentList()) - TertiaryButton(onClick = onCopyToClipboard, text = stringResource(R.string.seed_copy)) + TertiaryButton( + onClick = onCopyToClipboard, + text = stringResource(R.string.seed_copy), + outerPaddingValues = PaddingValues( + horizontal = ZcashTheme.dimens.spacingNone, + vertical = ZcashTheme.dimens.spacingSmall + ) + ) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/send/view/SendView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/send/view/SendView.kt index 6ca4c0fa..ff1a3145 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/send/view/SendView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/send/view/SendView.kt @@ -1,6 +1,7 @@ package co.electriccoin.zcash.ui.screen.send.view import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth @@ -108,6 +109,10 @@ fun Send( onQrScannerOpen = onQrScannerOpen, hasCameraFeature = hasCameraFeature, modifier = Modifier + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) .padding( top = paddingValues.calculateTopPadding() + dimens.spacingDefault, bottom = paddingValues.calculateBottomPadding() + dimens.spacingDefault, @@ -238,6 +243,8 @@ private fun SendForm( mutableStateOf>(emptySet()) } + // TODO [#826]: SendArgumentsWrapper object properties validation + // TODO [#826]: https://github.com/zcash/secant-android-wallet/issues/826 if (sendArgumentsWrapper?.recipientAddress != null) { recipientAddressString = sendArgumentsWrapper.recipientAddress } @@ -248,11 +255,7 @@ private fun SendForm( memoString = sendArgumentsWrapper.memo } - Column( - modifier - .fillMaxHeight() - .verticalScroll(rememberScrollState()) - ) { + Column(modifier) { Header( text = stringResource(id = R.string.send_balance, myBalance.toZecString()), textAlign = TextAlign.Center, @@ -314,7 +317,11 @@ private fun SendForm( modifier = Modifier.fillMaxWidth() ) - Spacer(Modifier.fillMaxHeight(MINIMAL_WEIGHT)) + Spacer( + modifier = Modifier + .fillMaxHeight() + .weight(MINIMAL_WEIGHT) + ) if (validation.isNotEmpty()) { /* @@ -348,7 +355,8 @@ private fun SendForm( text = stringResource(id = R.string.send_create), // Check for ABBREVIATION_INDEX goes away once proper address validation is in place. // For now, it just prevents a crash on the confirmation screen. - enabled = amountZecString.isNotBlank() && recipientAddressString.length > ABBREVIATION_INDEX + enabled = amountZecString.isNotBlank() && recipientAddressString.length > ABBREVIATION_INDEX, + outerPaddingValues = PaddingValues(top = dimens.spacingNone) ) } } @@ -359,14 +367,7 @@ private fun Confirmation( onConfirmation: () -> Unit, modifier: Modifier = Modifier ) { - Column( - Modifier - .fillMaxHeight() - .verticalScroll( - rememberScrollState() - ) - .then(modifier) - ) { + Column(modifier) { Body( stringResource( R.string.send_confirmation_amount_and_address_format, @@ -392,7 +393,8 @@ private fun Confirmation( PrimaryButton( modifier = Modifier.padding(top = dimens.spacingSmall), onClick = onConfirmation, - text = stringResource(id = R.string.send_confirmation_button) + text = stringResource(id = R.string.send_confirmation_button), + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) } } @@ -402,14 +404,7 @@ private fun Sending( zecSend: ZecSend, modifier: Modifier = Modifier ) { - Column( - Modifier - .fillMaxHeight() - .verticalScroll( - rememberScrollState() - ) - .then(modifier) - ) { + Column(modifier) { Header( text = stringResource( R.string.send_in_progress_amount_format, @@ -458,14 +453,7 @@ private fun SendSuccessful( onDone: () -> Unit, modifier: Modifier = Modifier ) { - Column( - Modifier - .fillMaxHeight() - .verticalScroll( - rememberScrollState() - ) - .then(modifier) - ) { + Column(modifier) { Header( text = stringResource(R.string.send_successful_title), textAlign = TextAlign.Center, @@ -496,7 +484,8 @@ private fun SendSuccessful( PrimaryButton( modifier = Modifier.padding(top = dimens.spacingSmall), text = stringResource(R.string.send_successful_button), - onClick = onDone + onClick = onDone, + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) } } @@ -507,14 +496,7 @@ private fun SendFailure( onDone: () -> Unit, modifier: Modifier = Modifier ) { - Column( - Modifier - .fillMaxHeight() - .verticalScroll( - rememberScrollState() - ) - .then(modifier) - ) { + Column(modifier) { Header( text = stringResource(R.string.send_failure_title), textAlign = TextAlign.Center, @@ -545,7 +527,8 @@ private fun SendFailure( PrimaryButton( modifier = Modifier.padding(top = dimens.spacingSmall), text = stringResource(R.string.send_failure_button), - onClick = onDone + onClick = onDone, + outerPaddingValues = PaddingValues(top = dimens.spacingSmall) ) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/settings/view/SettingsView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/settings/view/SettingsView.kt index 4f3e98c2..187a3cde 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/settings/view/SettingsView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/settings/view/SettingsView.kt @@ -85,7 +85,7 @@ fun Settings( ) .padding( top = paddingValues.calculateTopPadding() + dimens.spacingDefault, - bottom = dimens.spacingDefault, + bottom = paddingValues.calculateTopPadding() + dimens.spacingDefault, start = dimens.spacingDefault, end = dimens.spacingDefault ) diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/support/view/SupportView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/support/view/SupportView.kt index b75e1ec3..770970e4 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/support/view/SupportView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/support/view/SupportView.kt @@ -1,9 +1,13 @@ package co.electriccoin.zcash.ui.screen.support.view import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth +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.ArrowBack import androidx.compose.material.icons.filled.Send @@ -17,7 +21,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text -import androidx.compose.material3.TextField import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf @@ -26,6 +29,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import co.electriccoin.zcash.ui.R +import co.electriccoin.zcash.ui.design.component.Body +import co.electriccoin.zcash.ui.design.component.FormTextField import co.electriccoin.zcash.ui.design.component.GradientSurface import co.electriccoin.zcash.ui.design.theme.ZcashTheme @@ -68,9 +73,14 @@ fun Support( } ) { paddingValues -> SupportMainContent( - paddingValues, - message, - setMessage + message = message, + setMessage = setMessage, + modifier = Modifier.padding( + top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault, + bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault, + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) if (isShowingDialog) { @@ -101,17 +111,24 @@ private fun SupportTopAppBar(onBack: () -> Unit) { } @Composable -@OptIn(ExperimentalMaterial3Api::class) private fun SupportMainContent( - paddingValues: PaddingValues, message: String, - setMessage: (String) -> Unit + setMessage: (String) -> Unit, + modifier: Modifier = Modifier ) { Column( Modifier - .padding(top = paddingValues.calculateTopPadding()) + .fillMaxHeight() + .verticalScroll( + rememberScrollState() + ) + .then(modifier) ) { - TextField( + Body(stringResource(id = R.string.support_information)) + + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + + FormTextField( value = message, onValueChange = setMessage, modifier = Modifier @@ -119,7 +136,9 @@ private fun SupportMainContent( label = { Text(text = stringResource(id = R.string.support_hint)) } ) - Text(stringResource(id = R.string.support_disclaimer)) + Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge)) + + Body(stringResource(id = R.string.support_disclaimer)) } } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/AndroidUpdate.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/AndroidUpdate.kt index ed6b25f4..026884c9 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/AndroidUpdate.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/AndroidUpdate.kt @@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.update import android.content.Context import androidx.activity.ComponentActivity +import androidx.activity.compose.BackHandler import androidx.activity.viewModels import androidx.annotation.VisibleForTesting import androidx.compose.material3.SnackbarHostState @@ -28,7 +29,7 @@ internal fun MainActivity.WrapCheckForUpdate() { @Composable private fun WrapCheckForUpdate(activity: ComponentActivity) { - // TODO [#382]: https://github.com/zcash/secant-android-wallet/issues/382 + // TODO [#403]: Manual testing of already implemented in-app update mechanisms // TODO [#403]: https://github.com/zcash/secant-android-wallet/issues/403 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) val checkUpdateViewModel by activity.viewModels { @@ -53,8 +54,9 @@ private fun WrapCheckForUpdate(activity: ComponentActivity) { } } +@VisibleForTesting @Composable -private fun WrapUpdate( +internal fun WrapUpdate( activity: ComponentActivity, inputUpdateInfo: UpdateInfo ) { @@ -85,6 +87,16 @@ private fun WrapUpdate( } } + val onLaterAction = { + if (!updateInfo.isForce && updateInfo.state != UpdateState.Running) { + viewModel.remindLater() + } + } + + BackHandler { + onLaterAction() + } + Update( snackbarHostState, updateInfo, @@ -97,9 +109,7 @@ private fun WrapUpdate( updateInfo.appUpdateInfo ) }, - onLater = { - viewModel.remindLater() - }, + onLater = onLaterAction, onReference = { openPlayStoreAppPage( activity.applicationContext, diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/view/UpdateView.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/view/UpdateView.kt index 8300159e..bd205d5e 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/view/UpdateView.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/update/view/UpdateView.kt @@ -1,6 +1,5 @@ package co.electriccoin.zcash.ui.screen.update.view -import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -63,12 +62,6 @@ fun Update( onLater: () -> Unit, onReference: () -> Unit ) { - BackHandler(enabled = true) { - if (updateInfo.isForce) { - return@BackHandler - } - onLater() - } Scaffold( topBar = { UpdateTopAppBar(updateInfo) @@ -80,13 +73,26 @@ fun Update( UpdateBottomAppBar( updateInfo, onDownload, - onLater + onLater, + modifier = Modifier + .fillMaxWidth() + .padding( + vertical = ZcashTheme.dimens.spacingDefault, + horizontal = ZcashTheme.dimens.spacingDefault + ) ) } ) { paddingValues -> UpdateContentNormal( - paddingValues, - onReference + onReference, + modifier = Modifier + .fillMaxWidth() + .padding( + top = paddingValues.calculateTopPadding(), + bottom = paddingValues.calculateBottomPadding(), + start = ZcashTheme.dimens.spacingDefault, + end = ZcashTheme.dimens.spacingDefault + ) ) } UpdateOverlayRunning(updateInfo) @@ -134,16 +140,16 @@ private fun UpdateTopAppBar(updateInfo: UpdateInfo) { private fun UpdateBottomAppBar( updateInfo: UpdateInfo, onDownload: (state: UpdateState) -> Unit, - onLater: () -> Unit + onLater: () -> Unit, + modifier: Modifier = Modifier ) { - Column { + Column(modifier) { PrimaryButton( onClick = { onDownload(UpdateState.Running) }, text = stringResource(R.string.update_download_button), - modifier = Modifier - .fillMaxWidth() - .testTag(UpdateTag.BTN_DOWNLOAD), - enabled = updateInfo.state != UpdateState.Running + modifier = Modifier.testTag(UpdateTag.BTN_DOWNLOAD), + enabled = updateInfo.state != UpdateState.Running, + outerPaddingValues = PaddingValues(all = ZcashTheme.dimens.spacingNone) ) TertiaryButton( @@ -157,23 +163,20 @@ private fun UpdateBottomAppBar( } } ), - modifier = Modifier - .fillMaxWidth() - .testTag(UpdateTag.BTN_LATER), - enabled = !updateInfo.isForce && updateInfo.state != UpdateState.Running + modifier = Modifier.testTag(UpdateTag.BTN_LATER), + enabled = !updateInfo.isForce && updateInfo.state != UpdateState.Running, + outerPaddingValues = PaddingValues(top = ZcashTheme.dimens.spacingSmall) ) } } @Composable private fun UpdateContentNormal( - paddingValues: PaddingValues, - onReference: () -> Unit + onReference: () -> Unit, + modifier: Modifier = Modifier ) { Column( - Modifier - .fillMaxWidth() - .padding(top = paddingValues.calculateTopPadding()), + modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally ) { // TODO [#17]: This suppression and magic number will get replaced once we have real assets diff --git a/ui-lib/src/main/res/ui/home/values/strings.xml b/ui-lib/src/main/res/ui/home/values/strings.xml index 5668a79a..d691c509 100644 --- a/ui-lib/src/main/res/ui/home/values/strings.xml +++ b/ui-lib/src/main/res/ui/home/values/strings.xml @@ -2,6 +2,7 @@ Open menu Receive Send + You won’t be able to transfer funds until your wallet is finished syncing. Please keep your device plugged in and the app open. My secret phrase Settings diff --git a/ui-lib/src/main/res/ui/onboarding/values/strings.xml b/ui-lib/src/main/res/ui/onboarding/values/strings.xml index 0cc36f75..c7e1da0d 100644 --- a/ui-lib/src/main/res/ui/onboarding/values/strings.xml +++ b/ui-lib/src/main/res/ui/onboarding/values/strings.xml @@ -20,6 +20,7 @@ Import an Existing Wallet It‘s time to set up your no-frills wallet, powered by Zcash + We need to create a new wallet or restore an existing one. Select your path: Create New Wallet Import an Existing Wallet diff --git a/ui-lib/src/main/res/ui/support/values/strings.xml b/ui-lib/src/main/res/ui/support/values/strings.xml index 6694eb6c..8b3b840e 100644 --- a/ui-lib/src/main/res/ui/support/values/strings.xml +++ b/ui-lib/src/main/res/ui/support/values/strings.xml @@ -9,6 +9,7 @@ %1$s is about to open your email app with a pre-filled message.\n\nBe sure to hit send within your email app. + Please let us know about any problems you have had, or features you want to see in the future. Information provided is handled in accordance with our Privacy Policy. Unable to launch email app.