[#1414] Hide Balances

* [#1414] Hide Balances

- Closes #1414
- Reworked TopAppBar back navigation-related parameters across the app to enable us to inject a different action - hide balances instead of just the back navigation
- Tests updated to reflect the above changes
- A simple new button UI test was added, too
- Changelog update
This commit is contained in:
Honza Rychnovský 2024-07-03 15:29:49 +02:00 committed by GitHub
parent 42deed3391
commit bbf730d8f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 632 additions and 203 deletions

View File

@ -9,11 +9,12 @@ directly impact users rather than highlighting other key architectural updates.*
## [Unreleased]
### Fixed
- The app navigation has been improved to always behave the same for system, gesture, or top app bar back navigation actions.
### Added
- Proper ZEC amount abbreviation has been added across the entire app as described by the design document
- The new Hide Balances feature has been added to the Account, Send, and Balances screen.
### Fixed
- The app navigation has been improved to always behave the same for system, gesture, or top app bar back navigation actions
### Fixed
- The app authentication now correctly handles authentication success after a previous failed state

View File

@ -1,18 +1,24 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import cash.z.ecc.android.sdk.model.MonetarySeparators
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import java.util.Locale
@ -24,6 +30,20 @@ private fun StyledBalanceComposablePreview() {
Column {
StyledBalance(
balanceParts = ZecAmountTriple(main = "1,234.56789012"),
isHideBalances = false,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.first,
ZcashTheme.extendedTypography.balanceWidgetStyles.second
),
modifier = Modifier
)
Spacer(modifier = Modifier.height(24.dp))
StyledBalance(
balanceParts = ZecAmountTriple(main = "1,234.56789012"),
isHideBalances = true,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.first,
@ -41,52 +61,67 @@ private fun StyledBalanceComposablePreview() {
* requirements. The function displays the balance within two parts.
*
* @param balanceParts [ZecAmountTriple] class that holds balance parts
* @param isHideBalances Flag referring about the balance being hidden or not
* @param hiddenBalancePlaceholder String holding the placeholder for the hidden balance
* @param textStyles Styles for the first and second part of the balance
* @param textColor Optional color to modify the default font color from [textStyles]
* @param modifier Modifier to modify the Text UI element as needed
*/
@OptIn(ExperimentalFoundationApi::class)
@Suppress("LongParameterList")
@Composable
fun StyledBalance(
balanceParts: ZecAmountTriple,
textStyles: Pair<TextStyle, TextStyle>,
modifier: Modifier = Modifier,
isHideBalances: Boolean = false,
hiddenBalancePlaceholder: String = stringResource(id = R.string.hide_balance_placeholder),
textColor: Color? = null,
) {
val balanceSplit = splitBalance(balanceParts)
val content =
buildAnnotatedString {
withStyle(
style = textStyles.first.toSpanStyle()
) {
append(balanceSplit.first)
if (isHideBalances) {
buildAnnotatedString {
withStyle(
style = textStyles.first.toSpanStyle()
) {
append(hiddenBalancePlaceholder)
}
}
withStyle(
style = textStyles.second.toSpanStyle()
) {
append(balanceSplit.second)
} else {
val balanceSplit = splitBalance(balanceParts)
buildAnnotatedString {
withStyle(
style = textStyles.first.toSpanStyle()
) {
append(balanceSplit.first)
}
withStyle(
style = textStyles.second.toSpanStyle()
) {
append(balanceSplit.second)
}
}
}
val resultModifier =
Modifier
.basicMarquee()
.animateContentSize()
.then(modifier)
if (textColor != null) {
Text(
text = content,
color = textColor,
maxLines = 1,
modifier =
Modifier
.basicMarquee()
.then(modifier)
modifier = resultModifier
)
} else {
Text(
text = content,
maxLines = 1,
modifier =
Modifier
.basicMarquee()
.then(modifier)
modifier = resultModifier
)
}
}

View File

@ -3,7 +3,6 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
@ -34,6 +33,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
@ -51,7 +51,16 @@ import co.electriccoin.zcash.ui.design.theme.internal.TopAppBarColors
private fun TopAppBarTextComposablePreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface {
SmallTopAppBar(titleText = "Screen A", backText = "Back")
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
titleText = "Screen A"
)
}
}
}
@ -61,7 +70,16 @@ private fun TopAppBarTextComposablePreview() {
private fun TopAppBarTextDarkComposablePreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
SmallTopAppBar(titleText = "Screen A", backText = "Back")
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
titleText = "Screen A"
)
}
}
}
@ -72,8 +90,14 @@ private fun TopAppBarTextRestoringComposablePreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface {
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
titleText = "Screen A",
backText = "Back",
subTitle = "[RESTORING YOUR WALLET…]"
)
}
@ -86,9 +110,15 @@ private fun TopAppBarTextRestoringLongComposablePreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface {
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
subTitle = "[RESTORING YOUR WALLET LONG TEXT…]",
titleText = "Screen A",
backText = "Back",
subTitle = "[RESTORING YOUR WALLET LONG TEXT…]"
)
}
}
@ -99,7 +129,16 @@ private fun TopAppBarTextRestoringLongComposablePreview() {
private fun TopAppBarLogoComposablePreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface {
SmallTopAppBar(showTitleLogo = true, backText = "Back")
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
showTitleLogo = true
)
}
}
}
@ -110,8 +149,14 @@ private fun TopAppBarLogoRestoringComposablePreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface {
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
showTitleLogo = true,
backText = "Back",
subTitle = "[RESTORING YOUR WALLET…]"
)
}
@ -124,8 +169,14 @@ private fun TopAppBarLogoRestoringDarkComposablePreview() {
ZcashTheme(forceDarkMode = true) {
BlankSurface {
SmallTopAppBar(
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
showTitleLogo = true,
backText = "Back",
subTitle = "[RESTORING YOUR WALLET…]"
)
}
@ -157,7 +208,13 @@ private fun TopAppBarOneVisibleActionMenuComposablePreview() {
BlankSurface {
SmallTopAppBar(
titleText = "Screen C",
backText = "Back",
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
regularActions = {
TopBarOneVisibleActionMenuExample(
actionCallback = {}
@ -175,12 +232,18 @@ private fun TopAppBarHamburgerMenuComposablePreview() {
BlankSurface {
SmallTopAppBar(
titleText = "Screen D",
backText = "Back",
hamburgerMenuActions = {
TopBarHamburgerMenuExample(
actionCallback = {}
)
}
},
navigationAction = {
TopAppBarBackNavigation(
onBack = {},
backText = "BACK",
backContentDescriptionText = "BACK"
)
},
)
}
}
@ -285,15 +348,61 @@ private fun TopBarOneVisibleActionMenuExample(
)
}
@Composable
fun TopAppBarBackNavigation(
backContentDescriptionText: String? = null,
backIconVector: ImageVector = Icons.AutoMirrored.Filled.ArrowBack,
backText: String? = null,
onBack: () -> Unit
) {
Row(
modifier =
Modifier
.wrapContentSize()
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
.clickable { onBack() }
.padding(all = ZcashTheme.dimens.spacingMid),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = backIconVector,
contentDescription = backContentDescriptionText,
)
backText?.let {
Spacer(modifier = Modifier.size(size = ZcashTheme.dimens.spacingSmall))
Text(text = backText)
}
}
}
@Composable
fun TopAppBarHideBalancesNavigation(
iconVector: ImageVector,
onClick: () -> Unit,
modifier: Modifier = Modifier,
contentDescription: String? = null,
) {
IconButton(
onClick = onClick,
modifier = modifier
) {
Icon(
imageVector = iconVector,
contentDescription = contentDescription,
modifier = Modifier.size(24.dp)
)
}
}
@Composable
@Suppress("LongParameterList")
fun GridBgSmallTopAppBar(
modifier: Modifier = Modifier,
backContentDescriptionText: String? = null,
backText: String? = null,
colors: TopAppBarColors = ZcashTheme.colors.topAppBarColors,
hamburgerMenuActions: (@Composable RowScope.() -> Unit)? = null,
onBack: (() -> Unit)? = null,
navigationAction: @Composable () -> Unit = {},
regularActions: (@Composable RowScope.() -> Unit)? = null,
subTitle: String? = null,
showTitleLogo: Boolean = false,
@ -309,11 +418,9 @@ fun GridBgSmallTopAppBar(
gridLineWidth = ZcashTheme.dimens.gridLineWidth
)
),
backContentDescriptionText = backContentDescriptionText,
backText = backText,
colors = colors.copyColors(containerColor = Color.Transparent),
hamburgerMenuActions = hamburgerMenuActions,
onBack = onBack,
navigationAction = navigationAction,
regularActions = regularActions,
subTitle = subTitle,
showTitleLogo = showTitleLogo,
@ -322,15 +429,13 @@ fun GridBgSmallTopAppBar(
}
@Composable
@Suppress("LongParameterList", "LongMethod")
@Suppress("LongParameterList")
@OptIn(ExperimentalMaterial3Api::class)
fun SmallTopAppBar(
modifier: Modifier = Modifier,
backContentDescriptionText: String? = null,
backText: String? = null,
colors: TopAppBarColors = ZcashTheme.colors.topAppBarColors,
hamburgerMenuActions: (@Composable RowScope.() -> Unit)? = null,
onBack: (() -> Unit)? = null,
navigationAction: @Composable () -> Unit = {},
regularActions: (@Composable RowScope.() -> Unit)? = null,
subTitle: String? = null,
showTitleLogo: Boolean = false,
@ -377,28 +482,7 @@ fun SmallTopAppBar(
}
},
navigationIcon = {
backText?.let {
Box(
modifier =
Modifier
.wrapContentSize()
.clip(RoundedCornerShape(ZcashTheme.dimens.regularRippleEffectCorner))
.clickable { onBack?.run { onBack() } }
) {
Row(
modifier = Modifier.padding(all = ZcashTheme.dimens.spacingDefault),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = backContentDescriptionText,
tint = colors.navigationColor,
)
Spacer(modifier = Modifier.size(size = ZcashTheme.dimens.spacingSmall))
Text(text = backText.uppercase())
}
}
}
navigationAction()
},
actions = {
regularActions?.invoke(this)

View File

@ -1,3 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="amount_with_fiat_currency_symbol" formatted="true"><xliff:g id="fiat_currency_symbol" example="$">%1$s</xliff:g><xliff:g id="amount" example="123">%2$s</xliff:g></string>
<string name="hide_balance_placeholder">-----</string>
</resources>

View File

@ -26,7 +26,7 @@ class AboutViewTest {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithText(getStringResource(R.string.about_back).uppercase()).also {
composeTestRule.onNodeWithText(getStringResource(R.string.back_navigation).uppercase()).also {
it.assertExists()
}
@ -61,7 +61,9 @@ class AboutViewTest {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.about_back_content_description)).also {
composeTestRule.onNodeWithContentDescription(
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
}

View File

@ -24,6 +24,7 @@ class AccountTestSetup(
val initialTransactionState: TransactionUiState = TransactionHistoryUiStateFixture.new()
private val onSettingsCount = AtomicInteger(0)
private val onHideBalancesCount = AtomicInteger(0)
private val onReceiveCount = AtomicInteger(0)
private val onSendCount = AtomicInteger(0)
private val onItemClickCount = AtomicInteger(0)
@ -44,6 +45,11 @@ class AccountTestSetup(
return onSettingsCount.get()
}
fun getOnHideBalancesCount(): Int {
composeTestRule.waitForIdle()
return onHideBalancesCount.get()
}
fun getOnReceiveCount(): Int {
composeTestRule.waitForIdle()
return onReceiveCount.get()
@ -61,31 +67,35 @@ class AccountTestSetup(
@Composable
@Suppress("TestFunctionName")
fun DefaultContent() {
fun DefaultContent(isHideBalances: Boolean) {
Account(
balanceState = BalanceStateFixture.new(),
goSettings = {
onSettingsCount.incrementAndGet()
},
goBalances = {},
transactionsUiState = initialTransactionState,
hideStatusDialog = {},
onHideBalances = {
onHideBalancesCount.incrementAndGet()
},
isHideBalances = isHideBalances,
onTransactionItemAction = {
onItemClickCount.incrementAndGet()
},
hideStatusDialog = {},
showStatusDialog = null,
onStatusClick = {},
showStatusDialog = null,
snackbarHostState = SnackbarHostState(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
transactionsUiState = initialTransactionState,
walletRestoringState = WalletRestoringState.NONE,
walletSnapshot = WalletSnapshotFixture.new(),
)
}
fun setDefaultContent() {
fun setDefaultContent(isHideBalances: Boolean = false) {
composeTestRule.setContent {
ZcashTheme {
DefaultContent()
DefaultContent(isHideBalances)
}
}
}

View File

@ -29,11 +29,12 @@ class HistoryTestSetup(
composeTestRule.setContent {
ZcashTheme {
HistoryContainer(
transactionState = initialHistoryUiState,
isHideBalances = false,
onStatusClick = {},
onTransactionItemAction = {
onItemIdClickCount.incrementAndGet()
},
transactionState = initialHistoryUiState,
walletRestoringState = WalletRestoringState.NONE,
walletSnapshot = WalletSnapshotFixture.new()
)

View File

@ -40,7 +40,7 @@ class AccountViewIntegrationTest : UiTestPrerequisites() {
val testSetup = newTestSetup(walletSnapshot)
restorationTester.setContent {
testSetup.DefaultContent()
testSetup.DefaultContent(isHideBalances = false)
}
assertEquals(WalletSnapshotFixture.SAPLING_BALANCE, testSetup.getWalletSnapshot().saplingBalance)

View File

@ -10,6 +10,7 @@ import co.electriccoin.zcash.ui.design.component.CommonTag
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.account.AccountTag
import co.electriccoin.zcash.ui.screen.account.AccountTestSetup
import co.electriccoin.zcash.ui.screen.send.clickHideBalances
import co.electriccoin.zcash.ui.screen.send.clickSettingsTopAppBarMenu
import org.junit.Assert
import org.junit.Rule
@ -49,11 +50,25 @@ class AccountViewTest : UiTestPrerequisites() {
Assert.assertEquals(1, testSetup.getOnSettingsCount())
}
private fun newTestSetup(walletSnapshot: WalletSnapshot = WalletSnapshotFixture.new()) =
AccountTestSetup(
composeTestRule,
walletSnapshot = walletSnapshot,
).apply {
setDefaultContent()
}
@Test
@MediumTest
fun hide_balances_btn_click_test() {
val testSetup = newTestSetup()
Assert.assertEquals(0, testSetup.getOnHideBalancesCount())
composeTestRule.clickHideBalances()
Assert.assertEquals(1, testSetup.getOnHideBalancesCount())
}
private fun newTestSetup(
walletSnapshot: WalletSnapshot = WalletSnapshotFixture.new(),
isHideBalances: Boolean = false
) = AccountTestSetup(
composeTestRule,
walletSnapshot = walletSnapshot,
).apply {
setDefaultContent(isHideBalances)
}
}

View File

@ -38,6 +38,8 @@ class BalancesTestSetup(
onSettingsCount.incrementAndGet()
},
hideStatusDialog = {},
isHideBalances = false,
onHideBalances = {},
showStatusDialog = null,
onStatusClick = {},
snackbarHostState = SnackbarHostState(),

View File

@ -113,7 +113,7 @@ class ExportPrivateDataViewTest : UiTestPrerequisites() {
}
private fun ComposeContentTestRule.clickBack() {
onNodeWithContentDescription(getStringResource(R.string.support_back_content_description)).also {
onNodeWithContentDescription(getStringResource(R.string.back_navigation_content_description)).also {
it.performClick()
}
}

View File

@ -311,7 +311,7 @@ class RestoreViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(
getStringResource(R.string.restore_back_content_description)
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
}
@ -331,7 +331,7 @@ class RestoreViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(
getStringResource(R.string.restore_back_content_description)
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
}

View File

@ -98,7 +98,7 @@ class SecurityWarningViewTest : UiTestPrerequisites() {
}
private fun ComposeContentTestRule.clickBack() {
onNodeWithContentDescription(getStringResource(R.string.support_back_content_description)).also {
onNodeWithContentDescription(getStringResource(R.string.back_navigation_content_description)).also {
it.performClick()
}
}

View File

@ -39,7 +39,7 @@ class SeedRecoveryRecoveryViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnCompleteCount())
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.seed_recovery_back_content_description))
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.back_navigation_content_description))
.also {
it.assertExists()
}
@ -86,7 +86,7 @@ class SeedRecoveryRecoveryViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getOnBackCount())
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.seed_recovery_back_content_description))
composeTestRule.onNodeWithContentDescription(getStringResource(R.string.back_navigation_content_description))
.also {
it.performClick()
}

View File

@ -24,6 +24,12 @@ internal fun ComposeContentTestRule.clickSettingsTopAppBarMenu() {
}
}
internal fun ComposeContentTestRule.clickHideBalances() {
onNodeWithContentDescription(getStringResource(R.string.hide_balances_content_description)).also {
it.performClick()
}
}
internal fun ComposeContentTestRule.clickScanner() {
onNodeWithContentDescription(getStringResource(R.string.send_scan_content_description)).also {
it.performClick()

View File

@ -114,6 +114,8 @@ class SendViewTestSetup(
// TODO [#1194]: Cover Current balances UI widget with tests
// TODO [#1194]: https://github.com/Electric-Coin-Company/zashi-android/issues/1194
},
isHideBalances = false,
onHideBalances = {},
hasCameraFeature = hasCameraFeature,
recipientAddressState = RecipientAddressState("", AddressType.Invalid()),
onRecipientAddressChange = {

View File

@ -75,6 +75,8 @@ class SendViewIntegrationTest {
goBalances = {},
goSettings = {},
goSendConfirmation = {},
isHideBalances = false,
onHideBalances = {},
hasCameraFeature = true,
monetarySeparators = monetarySeparators,
topAppBarSubTitleState = TopAppBarSubTitleState.None,

View File

@ -31,7 +31,7 @@ class SettingsViewTest : UiTestPrerequisites() {
assertEquals(0, testSetup.getBackCount())
composeTestRule.onNodeWithContentDescription(
getStringResource(R.string.settings_back_content_description)
getStringResource(R.string.back_navigation_content_description)
).also {
it.performClick()
}

View File

@ -116,7 +116,7 @@ class SupportViewTest : UiTestPrerequisites() {
}
private fun ComposeContentTestRule.clickBack() {
onNodeWithContentDescription(getStringResource(R.string.support_back_content_description)).also {
onNodeWithContentDescription(getStringResource(R.string.back_navigation_content_description)).also {
it.performClick()
}
}

View File

@ -1,6 +1,5 @@
package co.electriccoin.zcash.ui.common.compose
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@ -46,6 +45,7 @@ private fun BalanceWidgetPreview() {
totalBalance = Zatoshi(1234567891234567L),
spendableBalance = Zatoshi(1234567891234567L)
),
isHideBalances = false,
isReferenceToBalances = true,
onReferenceClick = {},
modifier = Modifier
@ -65,6 +65,26 @@ private fun BalanceWidgetNotAvailableYetPreview() {
@Suppress("MagicNumber")
BalanceWidget(
balanceState = BalanceState.Loading(Zatoshi(0L)),
isHideBalances = false,
isReferenceToBalances = true,
onReferenceClick = {},
modifier = Modifier
)
}
}
}
@Preview
@Composable
private fun BalanceWidgetHiddenAmountPreview() {
ZcashTheme(forceDarkMode = false) {
BlankSurface(
modifier = Modifier.fillMaxWidth()
) {
@Suppress("MagicNumber")
BalanceWidget(
balanceState = BalanceState.Loading(Zatoshi(0L)),
isHideBalances = true,
isReferenceToBalances = true,
onReferenceClick = {},
modifier = Modifier
@ -86,6 +106,7 @@ sealed class BalanceState(open val totalBalance: Zatoshi) {
fun BalanceWidget(
balanceState: BalanceState,
isReferenceToBalances: Boolean,
isHideBalances: Boolean,
onReferenceClick: () -> Unit,
modifier: Modifier = Modifier
) {
@ -96,12 +117,12 @@ fun BalanceWidget(
.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally
) {
BalanceWidgetBigLineOnly(parts = balanceState.totalBalance.toZecStringFull().asZecAmountTriple())
BalanceWidgetBigLineOnly(
isHideBalances = isHideBalances,
parts = balanceState.totalBalance.toZecStringFull().asZecAmountTriple()
)
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.animateContentSize()
) {
Row(verticalAlignment = Alignment.CenterVertically) {
if (isReferenceToBalances) {
Reference(
text = stringResource(id = co.electriccoin.zcash.ui.R.string.balance_widget_available),
@ -135,6 +156,7 @@ fun BalanceWidget(
is BalanceState.Available -> {
StyledBalance(
balanceParts = balanceState.spendableBalance.toZecStringFull().asZecAmountTriple(),
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.third,
@ -157,6 +179,7 @@ fun BalanceWidget(
@Composable
fun BalanceWidgetBigLineOnly(
parts: ZecAmountTriple,
isHideBalances: Boolean,
modifier: Modifier = Modifier
) {
Row(
@ -165,6 +188,7 @@ fun BalanceWidgetBigLineOnly(
) {
StyledBalance(
balanceParts = parts,
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.first,

View File

@ -6,4 +6,5 @@ package co.electriccoin.zcash.ui.common.test
object CommonTag {
const val WALLET_BIRTHDAY = "wallet_birthday"
const val SETTINGS_TOP_BAR_BUTTON = "settings_top_bar_button"
const val HIDE_BALANCES_TOP_BAR_BUTTON = "hide_balances_top_bar_button"
}

View File

@ -13,6 +13,8 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.WhileSubscribed
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@ -40,6 +42,29 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
setBooleanPreference(StandardPreferenceKeys.IS_RESTORING_INITIAL_WARNING_SEEN, true)
}
/**
* A flow of the wallet balances visibility.
*/
val isHideBalances: StateFlow<Boolean?> = booleanStateFlow(StandardPreferenceKeys.IS_HIDE_BALANCES)
fun showOrHideBalances() {
viewModelScope.launch {
setBooleanPreference(StandardPreferenceKeys.IS_HIDE_BALANCES, isHideBalances.filterNotNull().first().not())
}
}
val configurationFlow: StateFlow<Configuration?> =
AndroidConfigurationFactory.getInstance(application).getConfigurationFlow()
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT.inWholeMilliseconds),
null
)
//
// PRIVATE HELPERS
//
private fun booleanStateFlow(default: BooleanPreferenceDefault): StateFlow<Boolean?> =
flow<Boolean?> {
val preferenceProvider = StandardPreferenceSingleton.getInstance(getApplication())
@ -50,14 +75,6 @@ class HomeViewModel(application: Application) : AndroidViewModel(application) {
null
)
val configurationFlow: StateFlow<Configuration?> =
AndroidConfigurationFactory.getInstance(application).getConfigurationFlow()
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT.inWholeMilliseconds),
null
)
private fun setBooleanPreference(
default: BooleanPreferenceDefault,
newState: Boolean

View File

@ -32,8 +32,6 @@ object StandardPreferenceKeys {
val IS_KEEP_SCREEN_ON_DURING_SYNC = BooleanPreferenceDefault(PreferenceKey("is_keep_screen_on_during_sync"), true)
val IS_DETAILED_SYNC_STATUS = BooleanPreferenceDefault(PreferenceKey("is_detailed_sync_status"), false)
val IS_RESTORING_INITIAL_WARNING_SEEN =
BooleanPreferenceDefault(PreferenceKey("IS_RESTORING_INITIAL_WARNING_SEEN"), false)
@ -70,4 +68,9 @@ object StandardPreferenceKeys {
PreferenceKey("IS_SEND_FUNDS_AUTHENTICATION"),
true
)
val IS_HIDE_BALANCES =
BooleanPreferenceDefault(
PreferenceKey("IS_HIDE_BALANCES"),
false
)
}

View File

@ -44,6 +44,7 @@ import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.ConfigInfoFixture
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@ -119,9 +120,13 @@ private fun AboutTopAppBar(
TopAppBarSubTitleState.None -> null
},
titleText = stringResource(id = R.string.about_title).uppercase(),
backText = stringResource(id = R.string.about_back).uppercase(),
backContentDescriptionText = stringResource(R.string.about_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
regularActions = {
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
DebugMenu(versionInfo, configInfo)

View File

@ -20,6 +20,7 @@ import co.electriccoin.zcash.ui.common.compose.LocalActivity
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
@ -43,6 +44,8 @@ internal fun WrapAccount(
val transactionHistoryViewModel by activity.viewModels<TransactionHistoryViewModel>()
val homeViewModel by activity.viewModels<HomeViewModel>()
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
val transactionsUiState = transactionHistoryViewModel.transactionUiState.collectAsStateWithLifecycle().value
@ -59,10 +62,14 @@ internal fun WrapAccount(
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
val isHideBalances = homeViewModel.isHideBalances.collectAsStateWithLifecycle().value ?: false
WrapAccount(
balanceState = balanceState,
goBalances = goBalances,
goSettings = goSettings,
isHideBalances = isHideBalances,
onHideBalances = { homeViewModel.showOrHideBalances() },
synchronizer = synchronizer,
topAppBarSubTitleState = walletState,
transactionHistoryViewModel = transactionHistoryViewModel,
@ -82,9 +89,11 @@ internal fun WrapAccount(
balanceState: BalanceState,
goBalances: () -> Unit,
goSettings: () -> Unit,
transactionsUiState: TransactionUiState,
isHideBalances: Boolean,
synchronizer: Synchronizer?,
onHideBalances: () -> Unit,
topAppBarSubTitleState: TopAppBarSubTitleState,
transactionsUiState: TransactionUiState,
transactionHistoryViewModel: TransactionHistoryViewModel,
walletRestoringState: WalletRestoringState,
walletSnapshot: WalletSnapshot?
@ -107,9 +116,11 @@ internal fun WrapAccount(
} else {
Account(
balanceState = balanceState,
isHideBalances = isHideBalances,
transactionsUiState = transactionsUiState,
showStatusDialog = showStatusDialog.value,
hideStatusDialog = { showStatusDialog.value = null },
onHideBalances = onHideBalances,
onStatusClick = { status ->
when (status) {
is StatusAction.Detailed -> showStatusDialog.value = status

View File

@ -12,9 +12,11 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
@ -27,6 +29,7 @@ import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.test.CommonTag
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarHideBalancesNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
@ -41,12 +44,14 @@ private fun HistoryLoadingComposablePreview() {
ZcashTheme(forceDarkMode = false) {
Account(
balanceState = BalanceStateFixture.new(),
isHideBalances = false,
goBalances = {},
goSettings = {},
hideStatusDialog = {},
showStatusDialog = null,
onHideBalances = {},
onStatusClick = {},
onTransactionItemAction = {},
showStatusDialog = null,
snackbarHostState = SnackbarHostState(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
transactionsUiState = TransactionUiState.Loading,
@ -67,12 +72,14 @@ private fun HistoryListComposablePreview() {
Zatoshi(123_000_000L),
Zatoshi(123_000_000L)
),
isHideBalances = false,
goBalances = {},
goSettings = {},
hideStatusDialog = {},
showStatusDialog = null,
onHideBalances = {},
onStatusClick = {},
onTransactionItemAction = {},
showStatusDialog = null,
snackbarHostState = SnackbarHostState(),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
transactionsUiState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
@ -88,10 +95,12 @@ internal fun Account(
balanceState: BalanceState,
goBalances: () -> Unit,
goSettings: () -> Unit,
isHideBalances: Boolean,
hideStatusDialog: () -> Unit,
showStatusDialog: StatusAction.Detailed?,
onHideBalances: () -> Unit,
onStatusClick: (StatusAction) -> Unit,
onTransactionItemAction: (TrxItemAction) -> Unit,
showStatusDialog: StatusAction.Detailed?,
snackbarHostState: SnackbarHostState,
topAppBarSubTitleState: TopAppBarSubTitleState,
transactionsUiState: TransactionUiState,
@ -101,6 +110,8 @@ internal fun Account(
BlankBgScaffold(
topBar = {
AccountTopAppBar(
isHideBalances = isHideBalances,
onHideBalances = onHideBalances,
onSettings = goSettings,
subTitleState = topAppBarSubTitleState,
)
@ -111,6 +122,7 @@ internal fun Account(
) { paddingValues ->
AccountMainContent(
balanceState = balanceState,
isHideBalances = isHideBalances,
goBalances = goBalances,
onStatusClick = onStatusClick,
onTransactionItemAction = onTransactionItemAction,
@ -137,6 +149,8 @@ internal fun Account(
@Composable
private fun AccountTopAppBar(
isHideBalances: Boolean,
onHideBalances: () -> Unit,
onSettings: () -> Unit,
subTitleState: TopAppBarSubTitleState
) {
@ -158,7 +172,22 @@ private fun AccountTopAppBar(
contentDescription = stringResource(id = R.string.settings_menu_content_description)
)
}
}
},
navigationAction = {
TopAppBarHideBalancesNavigation(
contentDescription = stringResource(id = R.string.hide_balances_content_description),
iconVector =
ImageVector.vectorResource(
if (isHideBalances) {
R.drawable.ic_hide_balances_on
} else {
R.drawable.ic_hide_balances_off
}
),
onClick = onHideBalances,
modifier = Modifier.testTag(CommonTag.HIDE_BALANCES_TOP_BAR_BUTTON)
)
},
)
}
@ -167,10 +196,11 @@ private fun AccountTopAppBar(
private fun AccountMainContent(
balanceState: BalanceState,
goBalances: () -> Unit,
isHideBalances: Boolean,
isWalletRestoringState: WalletRestoringState,
onTransactionItemAction: (TrxItemAction) -> Unit,
onStatusClick: (StatusAction) -> Unit,
transactionState: TransactionUiState,
isWalletRestoringState: WalletRestoringState,
walletSnapshot: WalletSnapshot,
modifier: Modifier = Modifier,
) {
@ -183,6 +213,7 @@ private fun AccountMainContent(
BalancesStatus(
balanceState = balanceState,
goBalances = goBalances,
isHideBalances = isHideBalances,
modifier =
Modifier
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular)
@ -191,6 +222,7 @@ private fun AccountMainContent(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
HistoryContainer(
isHideBalances = isHideBalances,
onStatusClick = onStatusClick,
onTransactionItemAction = onTransactionItemAction,
transactionState = transactionState,
@ -204,6 +236,7 @@ private fun AccountMainContent(
private fun BalancesStatus(
balanceState: BalanceState,
goBalances: () -> Unit,
isHideBalances: Boolean,
modifier: Modifier = Modifier,
) {
Column(
@ -217,6 +250,7 @@ private fun BalancesStatus(
) {
BalanceWidget(
balanceState = balanceState,
isHideBalances = isHideBalances,
isReferenceToBalances = true,
onReferenceClick = goBalances
)

View File

@ -83,6 +83,7 @@ private fun ComposablePreview() {
HistoryContainer(
onTransactionItemAction = {},
onStatusClick = {},
isHideBalances = false,
transactionState = TransactionUiState.Loading,
walletRestoringState = WalletRestoringState.SYNCING,
walletSnapshot = WalletSnapshotFixture.new()
@ -98,6 +99,7 @@ private fun ComposableHistoryListPreview() {
transactionState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
onTransactionItemAction = {},
onStatusClick = {},
isHideBalances = false,
walletRestoringState = WalletRestoringState.RESTORING,
walletSnapshot = WalletSnapshotFixture.new()
)
@ -116,6 +118,7 @@ private val dateFormat: DateFormat by lazy {
internal fun HistoryContainer(
onStatusClick: (StatusAction) -> Unit,
onTransactionItemAction: (TrxItemAction) -> Unit,
isHideBalances: Boolean,
transactionState: TransactionUiState,
walletRestoringState: WalletRestoringState,
walletSnapshot: WalletSnapshot,
@ -167,6 +170,7 @@ internal fun HistoryContainer(
is TransactionUiState.Prepared -> {
HistoryList(
transactions = transactionState.transactions,
isHideBalances = isHideBalances,
onAction = onTransactionItemAction,
)
}
@ -211,6 +215,7 @@ private fun EmptyTransactionHistory() {
@Composable
private fun HistoryList(
transactions: ImmutableList<TransactionUi>,
isHideBalances: Boolean,
onAction: (TrxItemAction) -> Unit,
modifier: Modifier = Modifier
) {
@ -220,6 +225,7 @@ private fun HistoryList(
items(transactions.size) { index ->
HistoryItem(
transaction = transactions[index],
isHideBalances = isHideBalances,
onAction = onAction
)
@ -239,6 +245,7 @@ private fun ComposableHistoryListItemPreview() {
BlankSurface {
HistoryItem(
onAction = {},
isHideBalances = false,
transaction = TransactionUiFixture.new()
)
}
@ -253,6 +260,7 @@ private fun ComposableHistoryListItemExpandedPreview() {
Column {
HistoryItem(
onAction = {},
isHideBalances = false,
transaction =
TransactionUiFixture.new(
overview = TransactionOverviewFixture.new().copy(isSentTransaction = true),
@ -261,6 +269,7 @@ private fun ComposableHistoryListItemExpandedPreview() {
)
HistoryItem(
onAction = {},
isHideBalances = false,
transaction =
TransactionUiFixture.new(
overview = TransactionOverviewFixture.new().copy(isSentTransaction = false),
@ -279,6 +288,7 @@ private fun ComposableHistoryListItemsPreview() {
BlankSurface {
HistoryItem(
onAction = {},
isHideBalances = false,
transaction =
TransactionUiFixture.new(
messages = persistentListOf("Message 1", "Message 2", "Message 3"),
@ -295,6 +305,7 @@ const val ADDRESS_IN_TITLE_WIDTH_RATIO = 0.5f
@Suppress("LongMethod")
private fun HistoryItem(
transaction: TransactionUi,
isHideBalances: Boolean,
onAction: (TrxItemAction) -> Unit,
modifier: Modifier = Modifier
) {
@ -373,6 +384,7 @@ private fun HistoryItem(
Column {
HistoryItemCollapsedMainPart(
transaction = transaction,
isHideBalances = isHideBalances,
typeText = typeText,
textStyle = textStyle,
textColor = textColor,
@ -417,6 +429,7 @@ private fun HistoryItemCollapsedMainPart(
typeText: String,
textStyle: TextStyle,
textColor: Color,
isHideBalances: Boolean,
onAction: (TrxItemAction) -> Unit,
modifier: Modifier = Modifier,
) {
@ -475,6 +488,7 @@ private fun HistoryItemCollapsedMainPart(
suffix = stringResource(id = R.string.general_etc)
).asZecAmountTriple(prefix)
},
isHideBalances = isHideBalances,
textStyles =
Pair(
first = valueTextStyle,
@ -812,6 +826,8 @@ private fun HistoryItemTransactionFeePart(
} else {
StyledBalance(
balanceParts = fee.toZecStringFull().asZecAmountTriple(),
// Fees are always visible
isHideBalances = false,
textStyles =
Pair(
first = ZcashTheme.extendedTypography.transactionItemStyles.feeFirstPart,

View File

@ -23,6 +23,7 @@ import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.ZcashTheme.dimens
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsTag
@ -97,9 +98,13 @@ private fun AdvancedSettingsTopAppBar(
},
modifier = Modifier.testTag(AdvancedSettingsTag.ADVANCED_SETTINGS_TOP_APP_BAR),
showTitleLogo = true,
backText = stringResource(id = R.string.advanced_settings_back).uppercase(),
backContentDescriptionText = stringResource(R.string.advanced_settings_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
}
)
}

View File

@ -26,6 +26,7 @@ import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
import co.electriccoin.zcash.ui.configuration.RemoteConfig
@ -54,6 +55,8 @@ internal fun WrapBalances(
val createTransactionsViewModel by activity.viewModels<CreateTransactionsViewModel>()
val homeViewModel by activity.viewModels<HomeViewModel>()
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
@ -64,6 +67,8 @@ internal fun WrapBalances(
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
val isHideBalances = homeViewModel.isHideBalances.collectAsStateWithLifecycle().value ?: false
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
CheckUpdateViewModel.CheckUpdateViewModelFactory(
activity.application,
@ -79,7 +84,9 @@ internal fun WrapBalances(
checkUpdateViewModel = checkUpdateViewModel,
goSettings = goSettings,
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
isHideBalances = isHideBalances,
lifecycleScope = activity.lifecycleScope,
onHideBalances = { homeViewModel.showOrHideBalances() },
spendingKey = spendingKey,
synchronizer = synchronizer,
topAppBarSubTitleState = walletState,
@ -101,6 +108,8 @@ internal fun WrapBalances(
goSettings: () -> Unit,
goMultiTrxSubmissionFailure: () -> Unit,
lifecycleScope: CoroutineScope,
isHideBalances: Boolean,
onHideBalances: () -> Unit,
spendingKey: UnifiedSpendingKey?,
synchronizer: Synchronizer?,
topAppBarSubTitleState: TopAppBarSubTitleState,
@ -158,7 +167,9 @@ internal fun WrapBalances(
Balances(
balanceState = balanceState,
isFiatConversionEnabled = isFiatConversionEnabled,
isHideBalances = isHideBalances,
isUpdateAvailable = isUpdateAvailable,
onHideBalances = onHideBalances,
onSettings = goSettings,
isShowingErrorDialog = isShowingErrorDialog,
setShowErrorDialog = setShowErrorDialog,

View File

@ -79,6 +79,7 @@ import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.Small
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.StyledBalance
import co.electriccoin.zcash.ui.design.component.TopAppBarHideBalancesNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
@ -94,11 +95,13 @@ private fun ComposableBalancesPreview() {
Balances(
balanceState = BalanceStateFixture.new(),
isFiatConversionEnabled = false,
isHideBalances = false,
isUpdateAvailable = false,
isShowingErrorDialog = false,
hideStatusDialog = {},
showStatusDialog = null,
setShowErrorDialog = {},
onHideBalances = {},
onSettings = {},
onShielding = {},
onStatusClick = {},
@ -118,11 +121,13 @@ private fun ComposableBalancesShieldDarkPreview() {
Balances(
balanceState = BalanceStateFixture.new(),
isFiatConversionEnabled = false,
isHideBalances = false,
isUpdateAvailable = false,
isShowingErrorDialog = true,
hideStatusDialog = {},
showStatusDialog = null,
setShowErrorDialog = {},
onHideBalances = {},
onSettings = {},
onShielding = {},
onStatusClick = {},
@ -153,14 +158,16 @@ private fun ComposableBalancesShieldErrorDialogPreview() {
fun Balances(
balanceState: BalanceState,
isFiatConversionEnabled: Boolean,
isHideBalances: Boolean,
isUpdateAvailable: Boolean,
isShowingErrorDialog: Boolean,
hideStatusDialog: () -> Unit,
showStatusDialog: StatusAction.Detailed?,
setShowErrorDialog: (Boolean) -> Unit,
onHideBalances: () -> Unit,
onSettings: () -> Unit,
onShielding: () -> Unit,
onStatusClick: (StatusAction) -> Unit,
showStatusDialog: StatusAction.Detailed?,
setShowErrorDialog: (Boolean) -> Unit,
shieldState: ShieldState,
snackbarHostState: SnackbarHostState,
topAppBarSubTitleState: TopAppBarSubTitleState,
@ -170,6 +177,8 @@ fun Balances(
BlankBgScaffold(
topBar = {
BalancesTopAppBar(
isHideBalances = isHideBalances,
onHideBalances = onHideBalances,
onSettings = onSettings,
subTitleState = topAppBarSubTitleState,
)
@ -184,6 +193,7 @@ fun Balances(
BalancesMainContent(
balanceState = balanceState,
isFiatConversionEnabled = isFiatConversionEnabled,
isHideBalances = isHideBalances,
isUpdateAvailable = isUpdateAvailable,
onShielding = onShielding,
onStatusClick = onStatusClick,
@ -256,6 +266,8 @@ fun ShieldingErrorDialog(
@Composable
private fun BalancesTopAppBar(
isHideBalances: Boolean,
onHideBalances: () -> Unit,
onSettings: () -> Unit,
subTitleState: TopAppBarSubTitleState
) {
@ -279,6 +291,21 @@ private fun BalancesTopAppBar(
)
}
},
navigationAction = {
TopAppBarHideBalancesNavigation(
contentDescription = stringResource(id = R.string.hide_balances_content_description),
iconVector =
ImageVector.vectorResource(
if (isHideBalances) {
R.drawable.ic_hide_balances_on
} else {
R.drawable.ic_hide_balances_off
}
),
onClick = onHideBalances,
modifier = Modifier.testTag(CommonTag.HIDE_BALANCES_TOP_BAR_BUTTON)
)
},
)
}
@ -287,6 +314,7 @@ private fun BalancesTopAppBar(
private fun BalancesMainContent(
balanceState: BalanceState,
isFiatConversionEnabled: Boolean,
isHideBalances: Boolean,
isUpdateAvailable: Boolean,
onShielding: () -> Unit,
onStatusClick: (StatusAction) -> Unit,
@ -307,6 +335,7 @@ private fun BalancesMainContent(
BalanceWidget(
balanceState = balanceState,
isHideBalances = isHideBalances,
isReferenceToBalances = false,
onReferenceClick = {}
)
@ -321,13 +350,15 @@ private fun BalancesMainContent(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
BalancesOverview(
walletSnapshot = walletSnapshot,
isFiatConversionEnabled = isFiatConversionEnabled,
isHideBalances = isHideBalances,
walletSnapshot = walletSnapshot,
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
TransparentBalancePanel(
isHideBalances = isHideBalances,
onShielding = onShielding,
shieldState = shieldState,
walletSnapshot = walletSnapshot,
@ -366,6 +397,7 @@ const val DEFAULT_LESS_THAN_FEE = 100_000L
@Composable
fun TransparentBalancePanel(
isHideBalances: Boolean,
onShielding: () -> Unit,
shieldState: ShieldState,
walletSnapshot: WalletSnapshot,
@ -383,6 +415,7 @@ fun TransparentBalancePanel(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
TransparentBalanceRow(
isHideBalances = isHideBalances,
isProgressbarVisible = shieldState == ShieldState.Running,
onHelpClick = { showHelpPanel = !showHelpPanel },
walletSnapshot = walletSnapshot
@ -428,6 +461,7 @@ fun TransparentBalancePanel(
@Composable
fun TransparentBalanceRow(
isHideBalances: Boolean,
isProgressbarVisible: Boolean,
onHelpClick: () -> Unit,
walletSnapshot: WalletSnapshot,
@ -466,6 +500,7 @@ fun TransparentBalanceRow(
Row(verticalAlignment = Alignment.CenterVertically) {
StyledBalance(
balanceParts = walletSnapshot.transparentBalance.toZecStringFull().asZecAmountTriple(),
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceSingleStyles.first,
@ -526,18 +561,19 @@ fun TransparentBalanceHelpPanel(onHideHelpPanel: () -> Unit) {
fun BalancesOverview(
walletSnapshot: WalletSnapshot,
isFiatConversionEnabled: Boolean,
isHideBalances: Boolean,
) {
Column {
SpendableBalanceRow(walletSnapshot)
SpendableBalanceRow(isHideBalances, walletSnapshot)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
ChangePendingRow(walletSnapshot)
ChangePendingRow(isHideBalances, walletSnapshot)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
// aka value pending
PendingTransactionsRow(walletSnapshot)
PendingTransactionsRow(isHideBalances, walletSnapshot)
if (isFiatConversionEnabled) {
val walletDisplayValues =
@ -574,7 +610,10 @@ fun BalancesOverview(
const val TEXT_PART_WIDTH_RATIO = 0.6f
@Composable
fun SpendableBalanceRow(walletSnapshot: WalletSnapshot) {
fun SpendableBalanceRow(
isHideBalances: Boolean,
walletSnapshot: WalletSnapshot
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
@ -588,6 +627,7 @@ fun SpendableBalanceRow(walletSnapshot: WalletSnapshot) {
Row(verticalAlignment = Alignment.CenterVertically) {
StyledBalance(
balanceParts = walletSnapshot.spendableBalance().toZecStringFull().asZecAmountTriple(),
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceSingleStyles.first,
@ -609,7 +649,10 @@ fun SpendableBalanceRow(walletSnapshot: WalletSnapshot) {
}
@Composable
fun ChangePendingRow(walletSnapshot: WalletSnapshot) {
fun ChangePendingRow(
isHideBalances: Boolean,
walletSnapshot: WalletSnapshot
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
@ -623,6 +666,7 @@ fun ChangePendingRow(walletSnapshot: WalletSnapshot) {
Row(verticalAlignment = Alignment.CenterVertically) {
StyledBalance(
balanceParts = walletSnapshot.changePendingBalance().toZecStringFull().asZecAmountTriple(),
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceSingleStyles.first,
@ -643,7 +687,10 @@ fun ChangePendingRow(walletSnapshot: WalletSnapshot) {
}
@Composable
fun PendingTransactionsRow(walletSnapshot: WalletSnapshot) {
fun PendingTransactionsRow(
isHideBalances: Boolean,
walletSnapshot: WalletSnapshot
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
@ -657,6 +704,7 @@ fun PendingTransactionsRow(walletSnapshot: WalletSnapshot) {
Row(verticalAlignment = Alignment.CenterVertically) {
StyledBalance(
balanceParts = walletSnapshot.valuePendingBalance().toZecStringFull().asZecAmountTriple(),
isHideBalances = isHideBalances,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceSingleStyles.first,

View File

@ -45,6 +45,7 @@ import co.electriccoin.zcash.ui.design.component.FormTextField
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.RadioButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.chooseserver.ChooseServerTag
import co.electriccoin.zcash.ui.screen.chooseserver.validateCustomServerValue
@ -233,9 +234,13 @@ private fun ChooseServerTopAppBar(
},
modifier = Modifier.testTag(ChooseServerTag.CHOOSE_SERVER_TOP_APP_BAR),
showTitleLogo = true,
backText = stringResource(id = R.string.choose_server_back).uppercase(),
backContentDescriptionText = stringResource(R.string.choose_server_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
}
)
}

View File

@ -28,6 +28,7 @@ import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -88,9 +89,13 @@ private fun DeleteWalletDataTopAppBar(
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
TopAppBarSubTitleState.None -> null
},
backText = stringResource(R.string.delete_wallet_back).uppercase(),
backContentDescriptionText = stringResource(R.string.delete_wallet_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
}
)
}

View File

@ -30,6 +30,7 @@ import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -93,9 +94,13 @@ private fun ExportPrivateDataTopAppBar(
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
TopAppBarSubTitleState.None -> null
},
backText = stringResource(R.string.export_data_back).uppercase(),
backContentDescriptionText = stringResource(R.string.export_data_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
)
}

View File

@ -73,6 +73,7 @@ import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.restore.RestoreTag
@ -355,9 +356,13 @@ private fun RestoreSeedTopAppBar(
) {
GridBgSmallTopAppBar(
modifier = modifier,
backText = stringResource(id = R.string.restore_back).uppercase(),
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
regularActions = {
ClearSeedMenuItem(
onSeedClear = onClear
@ -373,9 +378,13 @@ private fun RestoreSeedBirthdayTopAppBar(
) {
GridBgSmallTopAppBar(
modifier = modifier,
backText = stringResource(id = R.string.restore_back).uppercase(),
backContentDescriptionText = stringResource(R.string.restore_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
)
}

View File

@ -71,6 +71,7 @@ import co.electriccoin.zcash.ui.design.component.BlankSurface
import co.electriccoin.zcash.ui.design.component.SecondaryButton
import co.electriccoin.zcash.ui.design.component.Small
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
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
@ -284,15 +285,16 @@ private fun ScanTopAppBar(
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
TopAppBarSubTitleState.None -> null
},
backText =
navigationAction = {
if (showBack) {
stringResource(id = R.string.scan_back)
} else {
null
},
backContentDescriptionText = stringResource(id = R.string.scan_back_content_description),
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
}
},
colors = ZcashTheme.colors.transparentTopAppBarColors,
onBack = onBack,
)
}

View File

@ -29,6 +29,7 @@ import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.LabeledCheckBox
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@ -90,9 +91,13 @@ fun SecurityWarning(
@Composable
private fun SecurityWarningTopAppBar(onBack: () -> Unit) {
GridBgSmallTopAppBar(
backText = stringResource(R.string.security_warning_back).uppercase(),
backContentDescriptionText = stringResource(R.string.security_warning_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
}
)
}

View File

@ -49,6 +49,7 @@ import co.electriccoin.zcash.ui.design.component.ChipGrid
import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.TopScreenLogoTitle
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
@ -127,9 +128,13 @@ private fun SeedRecoveryTopAppBar(
TopAppBarSubTitleState.None -> null
},
modifier = modifier,
backText = stringResource(id = R.string.seed_recovery_back).uppercase(),
backContentDescriptionText = stringResource(R.string.seed_recovery_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
regularActions = {
if (versionInfo.isDebuggable && !versionInfo.isRunningUnderTestService) {
DebugMenu(

View File

@ -24,6 +24,7 @@ import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.compose.LocalActivity
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
import co.electriccoin.zcash.ui.screen.send.ext.Saver
@ -50,6 +51,8 @@ internal fun WrapSend(
val walletViewModel by activity.viewModels<WalletViewModel>()
val homeViewModel by activity.viewModels<HomeViewModel>()
val hasCameraFeature = activity.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
@ -66,8 +69,12 @@ internal fun WrapSend(
val balanceState = walletViewModel.balanceState.collectAsStateWithLifecycle().value
val isHideBalances = homeViewModel.isHideBalances.collectAsStateWithLifecycle().value ?: false
WrapSend(
balanceState = balanceState,
isHideBalances = isHideBalances,
onHideBalances = { homeViewModel.showOrHideBalances() },
sendArguments = sendArguments,
synchronizer = synchronizer,
walletSnapshot = walletSnapshot,
@ -88,6 +95,7 @@ internal fun WrapSend(
@Composable
internal fun WrapSend(
balanceState: BalanceState,
isHideBalances: Boolean,
goToQrScanner: () -> Unit,
goBack: () -> Unit,
goBalances: () -> Unit,
@ -95,6 +103,7 @@ internal fun WrapSend(
goSendConfirmation: (ZecSend) -> Unit,
hasCameraFeature: Boolean,
monetarySeparators: MonetarySeparators,
onHideBalances: () -> Unit,
sendArguments: SendArguments?,
spendingKey: UnifiedSpendingKey?,
synchronizer: Synchronizer?,
@ -181,6 +190,7 @@ internal fun WrapSend(
} else {
Send(
balanceState = balanceState,
isHideBalances = isHideBalances,
sendStage = sendStage,
onCreateZecSend = { newZecSend ->
scope.launch {
@ -199,6 +209,7 @@ internal fun WrapSend(
}
},
onBack = onBackAction,
onHideBalances = onHideBalances,
onSettings = goSettings,
recipientAddressState = recipientAddressState,
onRecipientAddressChange = {

View File

@ -32,6 +32,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.platform.LocalContext
@ -39,6 +40,7 @@ import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
@ -74,6 +76,7 @@ import co.electriccoin.zcash.ui.design.component.FormTextField
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.Small
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarHideBalancesNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
@ -93,6 +96,7 @@ private fun PreviewSendForm() {
sendStage = SendStage.Form,
onCreateZecSend = {},
onBack = {},
onHideBalances = {},
onSettings = {},
onQrScannerOpen = {},
goBalances = {},
@ -105,7 +109,8 @@ private fun PreviewSendForm() {
memoState = MemoState.new("Test message"),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
walletSnapshot = WalletSnapshotFixture.new(),
balanceState = BalanceStateFixture.new()
balanceState = BalanceStateFixture.new(),
isHideBalances = false,
)
}
}
@ -118,6 +123,7 @@ private fun SendFormTransparentAddressPreview() {
sendStage = SendStage.Form,
onCreateZecSend = {},
onBack = {},
onHideBalances = {},
onSettings = {},
onQrScannerOpen = {},
goBalances = {},
@ -134,7 +140,8 @@ private fun SendFormTransparentAddressPreview() {
memoState = MemoState.new("Test message"),
topAppBarSubTitleState = TopAppBarSubTitleState.None,
walletSnapshot = WalletSnapshotFixture.new(),
balanceState = BalanceStateFixture.new()
balanceState = BalanceStateFixture.new(),
isHideBalances = false,
)
}
}
@ -146,6 +153,8 @@ private fun SendFormTransparentAddressPreview() {
@Composable
fun Send(
balanceState: BalanceState,
isHideBalances: Boolean,
onHideBalances: () -> Unit,
sendStage: SendStage,
onCreateZecSend: (ZecSend) -> Unit,
onBack: () -> Unit,
@ -164,12 +173,15 @@ fun Send(
) {
BlankBgScaffold(topBar = {
SendTopAppBar(
isHideBalances = isHideBalances,
onHideBalances = onHideBalances,
subTitleState = topAppBarSubTitleState,
onSettings = onSettings
)
}) { paddingValues ->
SendMainContent(
balanceState = balanceState,
isHideBalances = isHideBalances,
walletSnapshot = walletSnapshot,
onBack = onBack,
sendStage = sendStage,
@ -197,6 +209,8 @@ fun Send(
@Composable
private fun SendTopAppBar(
isHideBalances: Boolean,
onHideBalances: () -> Unit,
onSettings: () -> Unit,
subTitleState: TopAppBarSubTitleState
) {
@ -219,6 +233,21 @@ private fun SendTopAppBar(
)
}
},
navigationAction = {
TopAppBarHideBalancesNavigation(
contentDescription = stringResource(id = R.string.hide_balances_content_description),
iconVector =
ImageVector.vectorResource(
if (isHideBalances) {
R.drawable.ic_hide_balances_on
} else {
R.drawable.ic_hide_balances_off
}
),
onClick = onHideBalances,
modifier = Modifier.testTag(CommonTag.HIDE_BALANCES_TOP_BAR_BUTTON)
)
},
)
}
@ -226,6 +255,7 @@ private fun SendTopAppBar(
@Composable
private fun SendMainContent(
balanceState: BalanceState,
isHideBalances: Boolean,
walletSnapshot: WalletSnapshot,
onBack: () -> Unit,
goBalances: () -> Unit,
@ -246,6 +276,7 @@ private fun SendMainContent(
SendForm(
balanceState = balanceState,
isHideBalances = isHideBalances,
walletSnapshot = walletSnapshot,
recipientAddressState = recipientAddressState,
onRecipientAddressChange = onRecipientAddressChange,
@ -278,6 +309,7 @@ private fun SendMainContent(
@Composable
private fun SendForm(
balanceState: BalanceState,
isHideBalances: Boolean,
walletSnapshot: WalletSnapshot,
recipientAddressState: RecipientAddressState,
onRecipientAddressChange: (String) -> Unit,
@ -311,6 +343,7 @@ private fun SendForm(
BalanceWidget(
balanceState = balanceState,
isHideBalances = isHideBalances,
isReferenceToBalances = true,
onReferenceClick = goBalances
)

View File

@ -55,6 +55,7 @@ import co.electriccoin.zcash.ui.design.component.Small
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.StyledBalance
import co.electriccoin.zcash.ui.design.component.Tiny
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.sendconfirmation.SendConfirmationTag
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage
@ -303,12 +304,13 @@ private fun SendConfirmationTopAppBar(
SmallTopAppBar(
subTitle = subTitle,
titleText = stringResource(id = R.string.send_confirmation_multiple_error_title),
backText = stringResource(id = R.string.send_confirmation_multiple_error_back),
backContentDescriptionText =
stringResource(
id = R.string.send_confirmation_multiple_error_back_content_description
),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
)
}
}
@ -371,7 +373,11 @@ private fun SendConfirmationContent(
Small(stringResource(R.string.send_confirmation_amount))
BalanceWidgetBigLineOnly(parts = zecSend.amount.toZecStringFull().asZecAmountTriple())
BalanceWidgetBigLineOnly(
parts = zecSend.amount.toZecStringFull().asZecAmountTriple(),
// We don't hide any balance in confirmation screen
isHideBalances = false
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
@ -392,6 +398,8 @@ private fun SendConfirmationContent(
// due to: "Smart cast to 'Proposal' is impossible, because 'zecSend.proposal' is a public API
// property declared in different module. See more details on the Kotlin forum.
balanceParts = zecSend.proposal!!.totalFeeRequired().toZecStringFull().asZecAmountTriple(),
// We don't hide any balance in confirmation screen
isHideBalances = false,
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceSingleStyles.first,

View File

@ -33,6 +33,7 @@ import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.ZcashTheme.dimens
import co.electriccoin.zcash.ui.screen.settings.SettingsTag
@ -128,9 +129,13 @@ private fun SettingsTopAppBar(
},
modifier = Modifier.testTag(SettingsTag.SETTINGS_TOP_APP_BAR),
showTitleLogo = true,
backText = stringResource(id = R.string.settings_back).uppercase(),
backContentDescriptionText = stringResource(R.string.settings_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
regularActions = {
if (troubleshootingParameters.isEnabled) {
TroubleshootingMenu(

View File

@ -38,6 +38,7 @@ import co.electriccoin.zcash.ui.design.component.FormTextField
import co.electriccoin.zcash.ui.design.component.GridBgScaffold
import co.electriccoin.zcash.ui.design.component.GridBgSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.TopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@Preview
@ -141,9 +142,13 @@ private fun SupportTopAppBar(
TopAppBarSubTitleState.None -> null
},
titleText = stringResource(id = R.string.support_header),
backText = stringResource(id = R.string.support_back).uppercase(),
backContentDescriptionText = stringResource(R.string.support_back_content_description),
onBack = onBack,
navigationAction = {
TopAppBarBackNavigation(
backText = stringResource(id = R.string.back_navigation).uppercase(),
backContentDescriptionText = stringResource(R.string.back_navigation_content_description),
onBack = onBack
)
},
)
}

View File

@ -1,7 +1,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="about_title">About</string>
<string name="about_back">Back</string>
<string name="about_back_content_description">Back</string>
<string name="about_version_format" formatted="true">Version <xliff:g example="1.0" id="version_name">%1$s
</xliff:g></string>
<string name="about_debug_menu_app_name">App name:

View File

@ -1,7 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="advanced_settings_back">Back</string>
<string name="advanced_settings_back_content_description">Back</string>
<string name="advanced_settings_backup_wallet">Recovery phrase</string>
<string name="advanced_settings_export_private_data">Export private data</string>
<string name="advanced_settings_choose_server">Choose a server</string>
@ -10,5 +7,4 @@
Delete <xliff:g id="app_name" example="Zashi">%1$s</xliff:g>
</string>
<string name="advanced_settings_delete_wallet_footnote">(You will be asked to confirm on next screen)</string>
</resources>

View File

@ -1,7 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="choose_server_back">Back</string>
<string name="choose_server_back_content_description">Back</string>
<string name="choose_server_title">Server</string>
<string name="choose_server_default_label">default: <xliff:g id="server" example="example.com:123">%1$s</xliff:g></string>
<string name="choose_server_custom">custom</string>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="11dp"
android:viewportWidth="17"
android:viewportHeight="11">
<group>
<clip-path
android:pathData="M0,0.5h17v10h-17z"/>
<path
android:pathData="M8.498,10.5C5.022,10.491 1.809,8.678 0.062,5.733C-0.024,5.589 -0.024,5.412 0.062,5.267C2.756,0.705 8.717,-0.856 13.377,1.781C14.858,2.62 16.086,3.823 16.943,5.272C17.029,5.416 17.029,5.593 16.943,5.738C15.196,8.683 11.982,10.5 8.502,10.505L8.498,10.5ZM1.028,5.5C3.59,9.54 9.007,10.78 13.134,8.273C14.286,7.574 15.253,6.623 15.967,5.5C13.411,1.465 7.993,0.22 3.866,2.727C2.714,3.426 1.742,4.377 1.028,5.505V5.5ZM8.498,8.538C6.784,8.538 5.399,7.178 5.399,5.5C5.399,3.823 6.789,2.467 8.502,2.467C10.216,2.467 11.602,3.827 11.602,5.5C11.602,7.178 10.212,8.534 8.498,8.534V8.538Z"
android:fillColor="#101010"/>
</group>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="17dp"
android:viewportWidth="17"
android:viewportHeight="17">
<path
android:pathData="M2.476,16.569L15.977,1.194C16.186,0.95 16.167,0.573 15.92,0.366C15.673,0.159 15.293,0.178 15.084,0.423L11.723,4.262C10.698,3.848 9.673,3.641 8.609,3.641C3.691,3.641 0.254,8.195 0.121,8.383C-0.05,8.59 -0.031,8.872 0.121,9.079C1.45,10.717 2.856,11.921 4.28,12.712L1.583,15.798C1.374,16.043 1.393,16.419 1.64,16.626C1.754,16.72 1.887,16.777 2.02,16.777C2.191,16.758 2.362,16.701 2.476,16.569ZM1.355,8.703C2.229,7.687 5.02,4.789 8.609,4.789C9.388,4.789 10.147,4.92 10.888,5.184L9.976,6.238C9.54,5.974 9.046,5.843 8.495,5.843C6.9,5.843 5.59,7.141 5.59,8.722C5.59,9.399 5.837,10.02 6.217,10.51L5.077,11.808C3.805,11.15 2.571,10.115 1.355,8.703ZM16.869,8.346C17.04,8.553 17.04,8.854 16.888,9.061C16.736,9.249 13.318,13.803 8.4,13.803C7.812,13.803 7.223,13.728 6.653,13.596L7.565,12.561C7.85,12.599 8.134,12.618 8.419,12.618C11.97,12.636 14.762,9.738 15.635,8.722C14.781,7.725 13.907,6.934 13.034,6.313L13.812,5.429C14.856,6.181 15.882,7.141 16.869,8.346Z"
android:fillColor="#000000"/>
</vector>

View File

@ -2,12 +2,17 @@
<!-- This is replaced by a resource overlay via app/build.gradle.kts -->
<string name="app_name">zashi-ui</string>
<string name="back_navigation">Back</string>
<string name="back_navigation_content_description">Back</string>
<string name="fiat_currency_conversion_rate_unavailable">Unavailable</string>
<string name="empty_char">-</string>
<string name="zcash_logo_content_description">Zcash logo</string>
<string name="settings_menu_content_description">Open Settings</string>
<string name="balance_widget_available">Available Balance:</string>
<string name="hide_balances_content_description">Hide balances</string>
<!-- This is replaced by a resource overlay via app/build.gradle.kts -->
<string name="support_email_address" />

View File

@ -1,7 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="delete_wallet_back">Back</string>
<string name="delete_wallet_back_content_description">Back</string>
<string name="delete_wallet_title">
Delete <xliff:g id="app_name" example="Zashi">%1$s</xliff:g>
</string>
@ -23,5 +20,4 @@
</string>
<string name="delete_wallet_failed">Wallet deletion failed. Try it again, please.</string>
</resources>

View File

@ -9,8 +9,6 @@
funds, only the ability to see what you do with your funds.</string>
<string name="export_data_confirm">Export private data</string>
<string name="export_data_agree">I agree</string>
<string name="export_data_back">Back</string>
<string name="export_data_back_content_description">Back</string>
<string name="export_data_export_data_chooser_title">Share internal Zashi data with:</string>
<string name="export_data_unable_to_share">Unable to find an application to share with.</string>
</resources>

View File

@ -1,6 +1,4 @@
<resources>
<string name="restore_back">Back</string>
<string name="restore_back_content_description">Back</string>
<string name="restore_button_clear">Clear Seed</string>
<string name="restore_title">Enter secret recovery phrase</string>
@ -14,5 +12,4 @@
<string name="restore_birthday_header">Wallet birthday height</string>
<string name="restore_birthday_sub_header">(optional)</string>
<string name="restore_birthday_button_restore">Restore</string>
</resources>

View File

@ -1,6 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="scan_back">Back</string>
<string name="scan_back_content_description">Back</string>
<string name="scan_preview_content_description">Camera</string>
<string name="scan_cancel_button">Cancel</string>

View File

@ -1,7 +1,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="security_warning_header">Security warning:</string>
<string name="security_warning_back">Back</string>
<string name="security_warning_back_content_description">Back</string>
<string name="security_warning_text" formatted="true">Zashi <xliff:g example="0.2.0" id="version_name">%1$s
</xliff:g>is a Zcash-only, shielded wallet — built by Zcashers for Zcashers. Zashi has been engineered for your

View File

@ -1,6 +1,4 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="seed_recovery_back">Back</string>
<string name="seed_recovery_back_content_description">Back</string>
<string name="seed_recovery_header">Your secret recovery phrase</string>
<string name="seed_recovery_description">The following 24 words are the keys to your funds and are the only way to
recover your funds if you get locked out or get a new device. Protect your ZEC by storing this phrase in a

View File

@ -13,8 +13,6 @@
<string name="send_confirmation_dialog_error_btn">OK</string>
<string name="send_confirmation_multiple_error_title">Transaction error</string>
<string name="send_confirmation_multiple_error_back">Back</string>
<string name="send_confirmation_multiple_error_back_content_description">Back</string>
<string name="send_confirmation_multiple_error_text_1">Sending to this recipient required multiple transactions,
but only some of them succeeded. Your funds are safe, but they need to be recovered with the help of Zashi
team support.</string>

View File

@ -1,7 +1,4 @@
<resources>
<string name="settings_back">Back</string>
<string name="settings_back_content_description">Back</string>
<string name="settings_troubleshooting_menu_content_description">Additional settings</string>
<string name="settings_troubleshooting_rescan">Rescan blockchain</string>
<string name="settings_troubleshooting_enable_background_sync">Background sync</string>
@ -11,5 +8,4 @@
<string name="settings_send_us_feedback">Send us feedback</string>
<string name="settings_advanced_settings">Advanced</string>
<string name="settings_about">About</string>
</resources>

View File

@ -1,7 +1,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="support_header">Support</string>
<string name="support_back">Back</string>
<string name="support_back_content_description">Back</string>
<string name="support_hint">How can we help?</string>
<string name="support_send">Send</string>