[#1264] Handle unavailable AccountBalance

- Closes #1264
- Changelog update
This commit is contained in:
Honza Rychnovský 2024-04-08 12:59:03 +02:00 committed by GitHub
parent b34d086cc0
commit bca1c32b8c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 219 additions and 84 deletions

View File

@ -29,6 +29,8 @@ directly impact users rather than highlighting other key architectural updates.*
screen)
- The sending and shielding funds logic has been connected to the new Proposal API from the Zcash SDK
- The error dialog contains an error description now. It's useful for tracking down the failure cause.
- A small circular progress indicator is displayed when the app runs block synchronization, and the available balance
is zero instead of reflecting a result value.
### Fixed
- Button sizing has been updated to align with the design guidelines and preserve stretching if necessary

View File

@ -11,6 +11,7 @@ import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@ -60,9 +61,12 @@ fun CircularMidProgressIndicator(modifier: Modifier = Modifier) {
}
@Composable
fun CircularSmallProgressIndicator(modifier: Modifier = Modifier) {
fun CircularSmallProgressIndicator(
modifier: Modifier = Modifier,
color: Color = ZcashTheme.colors.circularProgressBarSmall,
) {
CircularProgressIndicator(
color = ZcashTheme.colors.circularProgressBarSmall,
color = color,
strokeWidth = 2.dp,
modifier =
Modifier

View File

@ -12,6 +12,7 @@ data class Dimens(
// Default spacings:
val spacingNone: Dp,
val spacingXtiny: Dp,
val spacingMin: Dp,
val spacingTiny: Dp,
val spacingSmall: Dp,
val spacingMid: Dp,
@ -61,6 +62,7 @@ private val defaultDimens =
spacingNone = 0.dp,
spacingXtiny = 2.dp,
spacingTiny = 4.dp,
spacingMin = 6.dp,
spacingSmall = 8.dp,
spacingMid = 12.dp,
spacingDefault = 16.dp,

View File

@ -15,6 +15,7 @@ data class ExtendedColors(
val callout: Color,
val onCallout: Color,
val circularProgressBarSmall: Color,
val circularProgressBarSmallDark: Color,
val circularProgressBarScreen: Color,
val linearProgressBarTrack: Color,
val linearProgressBarBackground: Color,

View File

@ -51,9 +51,10 @@ internal object Dark {
val radioButtonTextColor = Color(0xFF4E4E4E)
val circularProgressBarSmall = Color(0xFF8B8A8A)
val circularProgressBarSmallDark = textBodyOnBackground
val circularProgressBarScreen = Color(0xFFFFFFFF)
val linearProgressBarTrack = Color(0xFFD9D9D9)
val linearProgressBarBackground = Light.complementaryColor
val linearProgressBarBackground = complementaryColor
val restoringTopAppBarColor = Color(0xFF8A8888)
val callout = Color(0xFFFFFFFF)
@ -111,6 +112,7 @@ internal object Light {
val circularProgressBarSmall = Color(0xFF8B8A8A)
val circularProgressBarScreen = Color(0xFF000000)
val circularProgressBarSmallDark = textBodyOnBackground
val linearProgressBarTrack = Color(0xFFD9D9D9)
val linearProgressBarBackground = complementaryColor
val restoringTopAppBarColor = Color(0xFF8A8888)
@ -164,6 +166,7 @@ internal val DarkExtendedColorPalette =
callout = Dark.callout,
onCallout = Dark.onCallout,
circularProgressBarSmall = Dark.circularProgressBarSmall,
circularProgressBarSmallDark = Dark.circularProgressBarSmallDark,
circularProgressBarScreen = Dark.circularProgressBarScreen,
linearProgressBarTrack = Dark.linearProgressBarTrack,
linearProgressBarBackground = Dark.linearProgressBarBackground,
@ -208,12 +211,13 @@ internal val LightExtendedColorPalette =
onCallout = Light.onCallout,
circularProgressBarScreen = Light.circularProgressBarScreen,
circularProgressBarSmall = Light.circularProgressBarSmall,
circularProgressBarSmallDark = Light.circularProgressBarSmallDark,
linearProgressBarTrack = Light.linearProgressBarTrack,
linearProgressBarBackground = Light.linearProgressBarBackground,
restoringTopAppBarColor = Light.restoringTopAppBarColor,
chipIndex = Light.textChipIndex,
textCommon = Light.textCommon,
textMedium = Dark.textMedium,
textMedium = Light.textMedium,
textDisabled = Light.textDisabled,
textFieldFrame = Light.textFieldFrame,
textFieldError = Light.textFieldError,
@ -253,6 +257,7 @@ internal val LocalExtendedColors =
onCallout = Color.Unspecified,
circularProgressBarScreen = Color.Unspecified,
circularProgressBarSmall = Color.Unspecified,
circularProgressBarSmallDark = Color.Unspecified,
linearProgressBarTrack = Color.Unspecified,
linearProgressBarBackground = Color.Unspecified,
restoringTopAppBarColor = Color.Unspecified,

View File

@ -5,6 +5,7 @@ import androidx.compose.ui.test.junit4.ComposeContentTestRule
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.screen.account.history.fixture.TransactionHistoryUiStateFixture
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
import co.electriccoin.zcash.ui.screen.account.view.Account
@ -59,6 +60,7 @@ class AccountTestSetup(
@Suppress("TestFunctionName")
fun DefaultContent() {
Account(
balanceState = BalanceStateFixture.new(),
goSettings = {
onSettingsCount.incrementAndGet()
},
@ -67,7 +69,6 @@ class AccountTestSetup(
onTransactionItemAction = {
onItemClickCount.incrementAndGet()
},
walletSnapshot = walletSnapshot,
walletRestoringState = WalletRestoringState.NONE,
)
}

View File

@ -5,6 +5,7 @@ import androidx.compose.ui.test.junit4.ComposeContentTestRule
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
import co.electriccoin.zcash.ui.screen.balances.view.Balances
import java.util.concurrent.atomic.AtomicInteger
@ -30,6 +31,7 @@ class BalancesTestSetup(
@Suppress("TestFunctionName")
fun DefaultContent() {
Balances(
balanceState = BalanceStateFixture.new(),
onSettings = {
onSettingsCount.incrementAndGet()
},
@ -40,7 +42,7 @@ class BalancesTestSetup(
onShielding = {},
shieldState = ShieldState.Available,
walletSnapshot = walletSnapshot,
walletRestoringState = WalletRestoringState.NONE
walletRestoringState = WalletRestoringState.NONE,
)
}

View File

@ -14,6 +14,7 @@ import cash.z.ecc.android.sdk.model.ZecSend
import cash.z.ecc.android.sdk.type.AddressType
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.send.ext.Saver
import co.electriccoin.zcash.ui.screen.send.model.AmountState
@ -109,13 +110,7 @@ class SendViewTestSetup(
// TODO [#1260]: Cover Send.Form screen UI with tests
// TODO [#1260]: https://github.com/Electric-Coin-Company/zashi-android/issues/1260
Send(
walletSnapshot =
WalletSnapshotFixture.new(
saplingBalance =
WalletBalanceFixture.new(
available = Zatoshi(Zatoshi.MAX_INCLUSIVE.div(100))
)
),
balanceState = BalanceStateFixture.new(),
sendStage = sendStage,
onCreateZecSend = setZecSend,
focusManager = LocalFocusManager.current,
@ -134,11 +129,18 @@ class SendViewTestSetup(
// TODO [#1260]: Cover Send.Form screen UI with tests
// TODO [#1260]: https://github.com/Electric-Coin-Company/zashi-android/issues/1260
},
amountState = AmountState.new(context, "", monetarySeparators),
setAmountState = {},
memoState = MemoState.new(""),
amountState = AmountState.new(context, "", monetarySeparators),
setMemoState = {},
walletRestoringState = WalletRestoringState.NONE
memoState = MemoState.new(""),
walletRestoringState = WalletRestoringState.NONE,
walletSnapshot =
WalletSnapshotFixture.new(
saplingBalance =
WalletBalanceFixture.new(
available = Zatoshi(Zatoshi.MAX_INCLUSIVE.div(100))
)
),
)
}
}

View File

@ -12,6 +12,7 @@ import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.sdk.fixture.ZecSendFixture
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.MockSynchronizer
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.send.WrapSend
@ -68,18 +69,19 @@ class SendViewIntegrationTest {
restorationTester.setContent {
WrapSend(
balanceState = BalanceStateFixture.new(),
sendArguments = null,
focusManager = LocalFocusManager.current,
synchronizer = synchronizer,
walletSnapshot = walletSnapshot,
spendingKey = spendingKey,
focusManager = LocalFocusManager.current,
goToQrScanner = {},
goBack = {},
goBalances = {},
hasCameraFeature = true,
goSettings = {},
monetarySeparators = monetarySeparators,
goSendConfirmation = {},
hasCameraFeature = true,
monetarySeparators = monetarySeparators,
walletRestoringState = WalletRestoringState.NONE,
)
}

View File

@ -1,5 +1,6 @@
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
@ -17,20 +18,16 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.toZecString
import cash.z.ecc.sdk.type.ZcashCurrency
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.model.spendableBalance
import co.electriccoin.zcash.ui.common.model.totalBalance
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.CircularSmallProgressIndicator
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.StyledBalance
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
@Preview(device = Devices.PIXEL_2)
@Composable
@ -42,14 +39,10 @@ private fun BalanceWidgetPreview() {
@Suppress("MagicNumber")
(
BalanceWidget(
walletSnapshot =
WalletSnapshotFixture.new(
saplingBalance =
WalletBalance(
Zatoshi(1234567891234567),
Zatoshi(123456789),
Zatoshi(123)
)
balanceState =
BalanceState.Available(
totalBalance = Zatoshi(1234567891234567L),
spendableBalance = Zatoshi(1234567891234567L)
),
isReferenceToBalances = true,
onReferenceClick = {},
@ -60,9 +53,35 @@ private fun BalanceWidgetPreview() {
}
}
@Preview(device = Devices.PIXEL_2)
@Composable
private fun BalanceWidgetNotAvailableYetPreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface(
modifier = Modifier.fillMaxWidth()
) {
@Suppress("MagicNumber")
BalanceWidget(
balanceState = BalanceState.Loading(Zatoshi(0L)),
isReferenceToBalances = true,
onReferenceClick = {},
modifier = Modifier
)
}
}
}
sealed class BalanceState(open val totalBalance: Zatoshi) {
data object None : BalanceState(Zatoshi(0L))
data class Loading(override val totalBalance: Zatoshi) : BalanceState(totalBalance)
data class Available(override val totalBalance: Zatoshi, val spendableBalance: Zatoshi) : BalanceState(totalBalance)
}
@Composable
fun BalanceWidget(
walletSnapshot: WalletSnapshot,
balanceState: BalanceState,
isReferenceToBalances: Boolean,
onReferenceClick: () -> Unit,
modifier: Modifier = Modifier
@ -74,10 +93,11 @@ fun BalanceWidget(
.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally
) {
BalanceWidgetBigLineOnly(text = walletSnapshot.totalBalance().toZecString())
BalanceWidgetBigLineOnly(text = balanceState.totalBalance.toZecString())
Row(
verticalAlignment = Alignment.CenterVertically
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.animateContentSize()
) {
if (isReferenceToBalances) {
Reference(
@ -94,16 +114,23 @@ fun BalanceWidget(
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingTiny))
StyledBalance(
balanceString = walletSnapshot.spendableBalance().toZecString(),
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.third,
ZcashTheme.extendedTypography.balanceWidgetStyles.fourth
when (balanceState) {
BalanceState.None, is BalanceState.Loading -> {
CircularSmallProgressIndicator(color = ZcashTheme.colors.circularProgressBarSmallDark)
}
is BalanceState.Available -> {
StyledBalance(
balanceString = balanceState.spendableBalance.toZecString(),
textStyles =
Pair(
ZcashTheme.extendedTypography.balanceWidgetStyles.third,
ZcashTheme.extendedTypography.balanceWidgetStyles.fourth
)
)
)
}
}
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingTiny))
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingMin))
Body(
text = ZcashCurrency.getLocalizedName(LocalContext.current),

View File

@ -27,10 +27,13 @@ import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
import co.electriccoin.zcash.global.getInstance
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.common.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.extension.throttle
import co.electriccoin.zcash.ui.common.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.model.spendableBalance
import co.electriccoin.zcash.ui.common.model.totalBalance
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceKeys
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceSingleton
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
@ -238,6 +241,43 @@ class WalletViewModel(application: Application) : AndroidViewModel(application)
initialValue = TransactionHistorySyncState.Loading
)
/**
* A flow of the wallet balances state used for the UI layer. It combines [WalletSnapshot] with
* [WalletRestoringState] and provides the correct [BalanceState] UI state.
*/
val balanceState: StateFlow<BalanceState> =
walletSnapshot
.filterNotNull()
.combine(walletRestoringState) {
walletSnapshot: WalletSnapshot, walletRestoringState: WalletRestoringState ->
when (walletRestoringState) {
WalletRestoringState.NONE -> BalanceState.None
WalletRestoringState.INITIATING ->
BalanceState.Available(
totalBalance = walletSnapshot.totalBalance(),
spendableBalance = walletSnapshot.spendableBalance()
)
WalletRestoringState.RESTORING, WalletRestoringState.SYNCING -> {
if (walletSnapshot.spendableBalance().value == 0L &&
walletSnapshot.totalBalance().value > 0L
) {
BalanceState.Loading(
totalBalance = walletSnapshot.totalBalance()
)
} else {
BalanceState.Available(
totalBalance = walletSnapshot.totalBalance(),
spendableBalance = walletSnapshot.spendableBalance()
)
}
}
}
}.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
BalanceState.None
)
/**
* Creates a wallet asynchronously and then persists it. Clients observe
* [secretState] to see the side effects. This would be used for a user creating a new wallet.

View File

@ -0,0 +1,19 @@
package co.electriccoin.zcash.ui.fixture
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.common.compose.BalanceState
object BalanceStateFixture {
private const val BALANCE_VALUE = 0L
val TOTAL_BALANCE = Zatoshi(BALANCE_VALUE)
val SPENDABLE_BALANCE = Zatoshi(BALANCE_VALUE)
fun new(
totalBalance: Zatoshi = TOTAL_BALANCE,
spendableBalance: Zatoshi = SPENDABLE_BALANCE
) = BalanceState.Available(
totalBalance = totalBalance,
spendableBalance = spendableBalance
)
}

View File

@ -12,8 +12,8 @@ import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.internal.Twig
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
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
@ -36,8 +36,6 @@ internal fun WrapAccount(
val transactionHistoryViewModel by activity.viewModels<TransactionHistoryViewModel>()
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
val transactionsUiState = transactionHistoryViewModel.transactionUiState.collectAsStateWithLifecycle().value
@ -48,7 +46,10 @@ internal fun WrapAccount(
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
val balanceState = walletViewModel.balanceState.collectAsStateWithLifecycle().value
WrapAccount(
balanceState = balanceState,
context = activity.applicationContext,
goBalances = goBalances,
goSettings = goSettings,
@ -56,7 +57,6 @@ internal fun WrapAccount(
synchronizer = synchronizer,
transactionHistoryViewModel = transactionHistoryViewModel,
transactionsUiState = transactionsUiState,
walletSnapshot = walletSnapshot,
walletRestoringState = walletRestoringState
)
@ -68,6 +68,7 @@ internal fun WrapAccount(
@VisibleForTesting
@Suppress("LongParameterList")
internal fun WrapAccount(
balanceState: BalanceState,
context: Context,
scope: CoroutineScope,
goBalances: () -> Unit,
@ -75,17 +76,16 @@ internal fun WrapAccount(
transactionsUiState: TransactionUiState,
synchronizer: Synchronizer?,
transactionHistoryViewModel: TransactionHistoryViewModel,
walletSnapshot: WalletSnapshot?,
walletRestoringState: WalletRestoringState,
) {
if (null == synchronizer || null == walletSnapshot) {
if (null == synchronizer) {
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
CircularScreenProgressIndicator()
} else {
Account(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
transactionsUiState = transactionsUiState,
onTransactionItemAction = { action ->
when (action) {

View File

@ -15,15 +15,16 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.test.CommonTag
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.screen.account.AccountTag
import co.electriccoin.zcash.ui.screen.account.fixture.TransactionsFixture
import co.electriccoin.zcash.ui.screen.account.model.TransactionUiState
@ -34,12 +35,12 @@ private fun HistoryLoadingComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
Account(
walletSnapshot = WalletSnapshotFixture.new(),
goBalances = {},
goSettings = {},
transactionsUiState = TransactionUiState.Loading,
onTransactionItemAction = {},
walletRestoringState = WalletRestoringState.SYNCING
transactionsUiState = TransactionUiState.Loading,
walletRestoringState = WalletRestoringState.SYNCING,
balanceState = BalanceStateFixture.new()
)
}
}
@ -52,12 +53,12 @@ private fun HistoryListComposablePreview() {
GradientSurface {
@Suppress("MagicNumber")
Account(
walletSnapshot = WalletSnapshotFixture.new(),
goBalances = {},
goSettings = {},
transactionsUiState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
onTransactionItemAction = {},
walletRestoringState = WalletRestoringState.NONE
transactionsUiState = TransactionUiState.Done(transactions = TransactionsFixture.new()),
walletRestoringState = WalletRestoringState.NONE,
balanceState = BalanceState.Available(Zatoshi(123_000_000L), Zatoshi(123_000_000L))
)
}
}
@ -66,12 +67,12 @@ private fun HistoryListComposablePreview() {
@Composable
@Suppress("LongParameterList")
internal fun Account(
balanceState: BalanceState,
goBalances: () -> Unit,
goSettings: () -> Unit,
onTransactionItemAction: (TrxItemAction) -> Unit,
transactionsUiState: TransactionUiState,
walletRestoringState: WalletRestoringState,
walletSnapshot: WalletSnapshot,
) {
Scaffold(topBar = {
AccountTopAppBar(
@ -80,7 +81,7 @@ internal fun Account(
)
}) { paddingValues ->
AccountMainContent(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
goBalances = goBalances,
transactionState = transactionsUiState,
walletRestoringState = walletRestoringState,
@ -125,7 +126,7 @@ private fun AccountTopAppBar(
@Composable
@Suppress("LongParameterList")
private fun AccountMainContent(
walletSnapshot: WalletSnapshot,
balanceState: BalanceState,
goBalances: () -> Unit,
onTransactionItemAction: (TrxItemAction) -> Unit,
transactionState: TransactionUiState,
@ -139,7 +140,7 @@ private fun AccountMainContent(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
BalancesStatus(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
goBalances = goBalances,
modifier =
Modifier
@ -158,9 +159,9 @@ private fun AccountMainContent(
@Composable
private fun BalancesStatus(
walletSnapshot: WalletSnapshot,
balanceState: BalanceState,
goBalances: () -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
) {
Column(
modifier =
@ -172,7 +173,7 @@ private fun BalancesStatus(
horizontalAlignment = Alignment.CenterHorizontally
) {
BalanceWidget(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
isReferenceToBalances = true,
onReferenceClick = goBalances
)

View File

@ -16,6 +16,7 @@ import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
@ -58,7 +59,10 @@ internal fun WrapBalances(
)
}
val balanceState = walletViewModel.balanceState.collectAsStateWithLifecycle().value
WrapBalances(
balanceState = balanceState,
checkUpdateViewModel = checkUpdateViewModel,
createTransactionsViewModel = createTransactionsViewModel,
goSettings = goSettings,
@ -76,6 +80,7 @@ const val DEFAULT_SHIELDING_THRESHOLD = 100000L
@VisibleForTesting
@Suppress("LongParameterList", "LongMethod")
internal fun WrapBalances(
balanceState: BalanceState,
checkUpdateViewModel: CheckUpdateViewModel,
createTransactionsViewModel: CreateTransactionsViewModel,
goSettings: () -> Unit,
@ -123,6 +128,7 @@ internal fun WrapBalances(
CircularScreenProgressIndicator()
} else {
Balances(
balanceState = balanceState,
onSettings = goSettings,
isFiatConversionEnabled = isFiatConversionEnabled,
isUpdateAvailable = isUpdateAvailable,

View File

@ -52,6 +52,7 @@ import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.toZecString
import cash.z.ecc.sdk.extension.toPercentageWithDecimal
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
@ -72,6 +73,7 @@ import co.electriccoin.zcash.ui.design.component.Reference
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.StyledBalance
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.balances.BalancesTag
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
@ -92,6 +94,7 @@ private fun ComposableBalancesPreview() {
shieldState = ShieldState.Available,
walletSnapshot = WalletSnapshotFixture.new(),
walletRestoringState = WalletRestoringState.NONE,
balanceState = BalanceStateFixture.new()
)
}
}
@ -112,6 +115,7 @@ private fun ComposableBalancesShieldFailurePreview() {
shieldState = ShieldState.Available,
walletSnapshot = WalletSnapshotFixture.new(),
walletRestoringState = WalletRestoringState.NONE,
balanceState = BalanceStateFixture.new()
)
}
}
@ -129,6 +133,7 @@ fun Balances(
shieldState: ShieldState,
walletSnapshot: WalletSnapshot?,
walletRestoringState: WalletRestoringState,
balanceState: BalanceState,
) {
Scaffold(topBar = {
BalancesTopAppBar(
@ -140,6 +145,7 @@ fun Balances(
CircularScreenProgressIndicator()
} else {
BalancesMainContent(
balanceState = balanceState,
isFiatConversionEnabled = isFiatConversionEnabled,
isUpdateAvailable = isUpdateAvailable,
onShielding = onShielding,
@ -228,6 +234,7 @@ private fun BalancesTopAppBar(
@Suppress("LongParameterList")
@Composable
private fun BalancesMainContent(
balanceState: BalanceState,
isFiatConversionEnabled: Boolean,
isUpdateAvailable: Boolean,
onShielding: () -> Unit,
@ -246,7 +253,7 @@ private fun BalancesMainContent(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
BalanceWidget(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
isReferenceToBalances = false,
onReferenceClick = {}
)

View File

@ -22,6 +22,7 @@ import cash.z.ecc.android.sdk.model.ZecSend
import cash.z.ecc.android.sdk.model.proposeSend
import cash.z.ecc.android.sdk.model.toZecString
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
@ -74,20 +75,23 @@ internal fun WrapSend(
val walletRestoringState = walletViewModel.walletRestoringState.collectAsStateWithLifecycle().value
val balanceState = walletViewModel.balanceState.collectAsStateWithLifecycle().value
WrapSend(
sendArguments,
synchronizer,
walletSnapshot,
spendingKey,
focusManager,
goToQrScanner,
goBack,
goBalances,
goSettings,
goSendConfirmation,
hasCameraFeature,
monetarySeparators,
walletRestoringState
balanceState = balanceState,
sendArguments = sendArguments,
synchronizer = synchronizer,
walletSnapshot = walletSnapshot,
spendingKey = spendingKey,
focusManager = focusManager,
goToQrScanner = goToQrScanner,
goBack = goBack,
goBalances = goBalances,
goSettings = goSettings,
goSendConfirmation = goSendConfirmation,
hasCameraFeature = hasCameraFeature,
monetarySeparators = monetarySeparators,
walletRestoringState = walletRestoringState
)
}
@ -95,6 +99,7 @@ internal fun WrapSend(
@VisibleForTesting
@Composable
internal fun WrapSend(
balanceState: BalanceState,
sendArguments: SendArguments?,
synchronizer: Synchronizer?,
walletSnapshot: WalletSnapshot?,
@ -178,7 +183,7 @@ internal fun WrapSend(
CircularScreenProgressIndicator()
} else {
Send(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
sendStage = sendStage,
onCreateZecSend = { newZecSend ->
scope.launch {
@ -219,7 +224,8 @@ internal fun WrapSend(
onQrScannerOpen = goToQrScanner,
goBalances = goBalances,
hasCameraFeature = hasCameraFeature,
walletRestoringState = walletRestoringState
walletRestoringState = walletRestoringState,
walletSnapshot = walletSnapshot,
)
}
}

View File

@ -51,6 +51,7 @@ import cash.z.ecc.sdk.fixture.ZatoshiFixture
import cash.z.ecc.sdk.type.ZcashCurrency
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.compose.BalanceState
import co.electriccoin.zcash.ui.common.compose.BalanceWidget
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
@ -67,6 +68,7 @@ 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.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.send.SendTag
import co.electriccoin.zcash.ui.screen.send.model.AmountState
@ -81,7 +83,6 @@ private fun PreviewSendForm() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
Send(
walletSnapshot = WalletSnapshotFixture.new(),
sendStage = SendStage.Form,
onCreateZecSend = {},
focusManager = LocalFocusManager.current,
@ -96,7 +97,9 @@ private fun PreviewSendForm() {
amountState = AmountState.Valid(ZatoshiFixture.ZATOSHI_LONG.toString(), ZatoshiFixture.new()),
setMemoState = {},
memoState = MemoState.new("Test message"),
walletRestoringState = WalletRestoringState.NONE
walletRestoringState = WalletRestoringState.NONE,
walletSnapshot = WalletSnapshotFixture.new(),
balanceState = BalanceStateFixture.new()
)
}
}
@ -108,6 +111,7 @@ private fun PreviewSendForm() {
@Suppress("LongParameterList")
@Composable
fun Send(
balanceState: BalanceState,
sendStage: SendStage,
onCreateZecSend: (ZecSend) -> Unit,
focusManager: FocusManager,
@ -132,6 +136,7 @@ fun Send(
)
}) { paddingValues ->
SendMainContent(
balanceState = balanceState,
walletSnapshot = walletSnapshot,
onBack = onBack,
focusManager = focusManager,
@ -188,6 +193,7 @@ private fun SendTopAppBar(
@Suppress("LongParameterList")
@Composable
private fun SendMainContent(
balanceState: BalanceState,
walletSnapshot: WalletSnapshot,
focusManager: FocusManager,
onBack: () -> Unit,
@ -208,6 +214,7 @@ private fun SendMainContent(
// loader if calling the Proposal API takes longer than expected
SendForm(
balanceState = balanceState,
walletSnapshot = walletSnapshot,
recipientAddressState = recipientAddressState,
onRecipientAddressChange = onRecipientAddressChange,
@ -242,6 +249,7 @@ const val DEFAULT_LESS_THAN_FEE = 100_000L
@Suppress("LongMethod", "LongParameterList")
@Composable
private fun SendForm(
balanceState: BalanceState,
walletSnapshot: WalletSnapshot,
focusManager: FocusManager,
recipientAddressState: RecipientAddressState,
@ -275,7 +283,7 @@ private fun SendForm(
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
BalanceWidget(
walletSnapshot = walletSnapshot,
balanceState = balanceState,
isReferenceToBalances = true,
onReferenceClick = goBalances
)