[#1092] Duplicate Home to separate Account screen

- Closes #1092
- New Account screen + logic created
- Moved a few commonly used logic components into the common package
This commit is contained in:
Honza Rychnovský 2023-12-06 15:29:12 +01:00 committed by GitHub
parent dd81b90fbf
commit 1310a0730d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 494 additions and 66 deletions

View File

@ -30,6 +30,7 @@ android {
res.setSrcDirs(
setOf(
"src/main/res/ui/about",
"src/main/res/ui/account",
"src/main/res/ui/new_wallet_recovery",
"src/main/res/ui/common",
"src/main/res/ui/export_data",

View File

@ -2,8 +2,8 @@ package co.electriccoin.zcash.ui.screen.home
import androidx.compose.runtime.Composable
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import co.electriccoin.zcash.ui.screen.home.view.Home
import java.util.concurrent.atomic.AtomicInteger

View File

@ -10,10 +10,10 @@ import androidx.test.filters.MediumTest
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.PercentDecimal
import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.home.HomeTag
import co.electriccoin.zcash.ui.screen.home.HomeTestSetup
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Rule

View File

@ -6,6 +6,7 @@ import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.toZecString
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.totalBalance
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.test.getAppContext
import co.electriccoin.zcash.ui.test.getStringResource

View File

@ -11,10 +11,10 @@ import androidx.compose.ui.test.performScrollTo
import androidx.test.filters.MediumTest
import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.home.HomeTag
import co.electriccoin.zcash.ui.screen.home.HomeTestSetup
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import co.electriccoin.zcash.ui.test.getStringResource
import org.junit.Assert.assertEquals
import org.junit.Rule

View File

@ -27,15 +27,15 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
import co.electriccoin.zcash.ui.common.BindCompLocalProvider
import co.electriccoin.zcash.ui.common.model.OnboardingState
import co.electriccoin.zcash.ui.common.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.configuration.RemoteConfig
import co.electriccoin.zcash.ui.design.component.ConfigurationOverride
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.Override
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
import co.electriccoin.zcash.ui.screen.home.viewmodel.HomeViewModel
import co.electriccoin.zcash.ui.screen.home.viewmodel.SecretState
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.newwalletrecovery.WrapNewWalletRecovery
import co.electriccoin.zcash.ui.screen.onboarding.WrapOnboarding
import co.electriccoin.zcash.ui.screen.onboarding.persistExistingWalletWithSeedPhrase

View File

@ -26,10 +26,10 @@ import co.electriccoin.zcash.ui.NavigationTargets.WALLET_ADDRESS_DETAILS
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
import co.electriccoin.zcash.ui.configuration.RemoteConfig
import co.electriccoin.zcash.ui.screen.about.WrapAbout
import co.electriccoin.zcash.ui.screen.account.WrapAccount
import co.electriccoin.zcash.ui.screen.address.WrapWalletAddresses
import co.electriccoin.zcash.ui.screen.exportdata.WrapExportPrivateData
import co.electriccoin.zcash.ui.screen.history.WrapHistory
import co.electriccoin.zcash.ui.screen.home.WrapHome
import co.electriccoin.zcash.ui.screen.receive.WrapReceive
import co.electriccoin.zcash.ui.screen.request.WrapRequest
import co.electriccoin.zcash.ui.screen.scan.WrapScanValidator
@ -51,7 +51,7 @@ internal fun MainActivity.Navigation() {
NavHost(navController = navController, startDestination = HOME) {
composable(HOME) {
WrapHome(
WrapAccount(
goHistory = { navController.navigateJustOnce(HISTORY) },
goReceive = { navController.navigateJustOnce(RECEIVE) },
goSend = { navController.navigateJustOnce(SEND) },

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.home.model
package co.electriccoin.zcash.ui.common.model
/**
* Common Onboarding/SecurityWarning/Recovery screen enum.

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.home.model
package co.electriccoin.zcash.ui.common.model
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.block.processor.CompactBlockProcessor
@ -6,7 +6,7 @@ import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.screen.home.viewmodel.SynchronizerError
import co.electriccoin.zcash.ui.common.viewmodel.SynchronizerError
// TODO [#292]: Should be moved to SDK-EXT-UI module.
// TODO [#292]: https://github.com/Electric-Coin-Company/zashi-android/issues/292

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.home.viewmodel
package co.electriccoin.zcash.ui.common.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.home.viewmodel
package co.electriccoin.zcash.ui.common.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.home.viewmodel
package co.electriccoin.zcash.ui.common.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
@ -26,14 +26,14 @@ 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.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.throttle
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceKeys
import co.electriccoin.zcash.ui.preference.EncryptedPreferenceSingleton
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
import co.electriccoin.zcash.ui.preference.StandardPreferenceSingleton
import co.electriccoin.zcash.ui.screen.history.state.TransactionHistorySyncState
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi

View File

@ -5,8 +5,8 @@ import cash.z.ecc.android.sdk.block.processor.CompactBlockProcessor
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.WalletBalance
import cash.z.ecc.android.sdk.model.Zatoshi
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
import co.electriccoin.zcash.ui.screen.home.viewmodel.SynchronizerError
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.viewmodel.SynchronizerError
@Suppress("MagicNumber")
object WalletSnapshotFixture {

View File

@ -3,7 +3,7 @@ package co.electriccoin.zcash.ui.preference
import co.electriccoin.zcash.preference.model.entry.BooleanPreferenceDefault
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.OnboardingState
object StandardPreferenceKeys {

View File

@ -0,0 +1,11 @@
package co.electriccoin.zcash.ui.screen.account
/**
* These are only used for automated testing.
*/
object AccountTag {
const val STATUS_VIEWS = "status_views"
const val SINGLE_LINE_TEXT = "single_line_text"
const val FIAT_CONVERSION = "fiat_conversion"
const val SETTINGS_TOP_BAR_BUTTON = "settings_top_bar_button"
}

View File

@ -0,0 +1,80 @@
@file:Suppress("ktlint:filename")
package co.electriccoin.zcash.ui.screen.account
import androidx.activity.ComponentActivity
import androidx.activity.viewModels
import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
import co.electriccoin.zcash.ui.configuration.RemoteConfig
import co.electriccoin.zcash.ui.screen.account.view.Account
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
@Composable
@Suppress("LongParameterList")
internal fun MainActivity.WrapAccount(
goSettings: () -> Unit,
goReceive: () -> Unit,
goSend: () -> Unit,
goHistory: () -> Unit
) {
WrapAccount(
this,
goSettings = goSettings,
goReceive = goReceive,
goSend = goSend,
goHistory = goHistory,
)
}
@Composable
@Suppress("LongParameterList")
internal fun WrapAccount(
activity: ComponentActivity,
goSettings: () -> Unit,
goReceive: () -> Unit,
goSend: () -> Unit,
goHistory: () -> Unit,
) {
// we want to show information about app update, if available
val checkUpdateViewModel by activity.viewModels<CheckUpdateViewModel> {
CheckUpdateViewModel.CheckUpdateViewModelFactory(
activity.application,
AppUpdateCheckerImp.new()
)
}
val updateAvailable = checkUpdateViewModel.updateInfo.collectAsStateWithLifecycle().value.let {
it?.appUpdateInfo != null && it.state == UpdateState.Prepared
}
val walletViewModel by activity.viewModels<WalletViewModel>()
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
val settingsViewModel by activity.viewModels<SettingsViewModel>()
val isKeepScreenOnWhileSyncing = settingsViewModel.isKeepScreenOnWhileSyncing.collectAsStateWithLifecycle().value
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
if (null == walletSnapshot) {
// Display loading indicator
} else {
Account(
walletSnapshot = walletSnapshot,
isUpdateAvailable = updateAvailable,
isKeepScreenOnDuringSync = isKeepScreenOnWhileSyncing,
isFiatConversionEnabled = isFiatConversionEnabled,
goSettings = goSettings,
goReceive = goReceive,
goSend = goSend,
goHistory = goHistory
)
activity.reportFullyDrawn()
}
}

View File

@ -0,0 +1,111 @@
package co.electriccoin.zcash.ui.screen.account.model
import android.content.Context
import androidx.compose.ui.text.intl.Locale
import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
import cash.z.ecc.android.sdk.model.MonetarySeparators
import cash.z.ecc.android.sdk.model.PercentDecimal
import cash.z.ecc.android.sdk.model.toFiatCurrencyState
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.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.model.spendableBalance
import co.electriccoin.zcash.ui.common.model.totalBalance
import co.electriccoin.zcash.ui.common.toKotlinLocale
data class WalletDisplayValues(
val progress: PercentDecimal,
val zecAmountText: String,
val statusText: String,
val fiatCurrencyAmountState: FiatCurrencyConversionRateState,
val fiatCurrencyAmountText: String
) {
companion object {
@Suppress("MagicNumber", "LongMethod")
internal fun getNextValues(
context: Context,
walletSnapshot: WalletSnapshot,
updateAvailable: Boolean
): WalletDisplayValues {
var progress = PercentDecimal.ZERO_PERCENT
val zecAmountText = walletSnapshot.totalBalance().toZecString()
var statusText = ""
// TODO [#578]: Provide Zatoshi -> USD fiat currency formatting
// TODO [#578]: https://github.com/Electric-Coin-Company/zcash-android-wallet-sdk/issues/578
// We'll ideally provide a "fresh" currencyConversion object here
val fiatCurrencyAmountState = walletSnapshot.spendableBalance().toFiatCurrencyState(
null,
Locale.current.toKotlinLocale(),
MonetarySeparators.current()
)
var fiatCurrencyAmountText = getFiatCurrencyRateValue(context, fiatCurrencyAmountState)
when (walletSnapshot.status) {
Synchronizer.Status.SYNCING -> {
progress = walletSnapshot.progress
// we add "so far" to the amount
if (fiatCurrencyAmountState != FiatCurrencyConversionRateState.Unavailable) {
fiatCurrencyAmountText = context.getString(
R.string.account_status_syncing_amount_suffix,
fiatCurrencyAmountText
)
}
statusText = context.getString(
R.string.account_status_syncing_format,
walletSnapshot.progress.toPercentageWithDecimal()
)
}
Synchronizer.Status.SYNCED -> {
statusText = if (updateAvailable) {
context.getString(R.string.account_status_update)
} else {
context.getString(R.string.account_status_up_to_date)
}
}
Synchronizer.Status.DISCONNECTED -> {
statusText = context.getString(
R.string.account_status_error,
context.getString(R.string.account_status_error_connection)
)
}
Synchronizer.Status.STOPPED -> {
statusText = context.getString(R.string.account_status_stopped)
}
}
// more detailed error message
walletSnapshot.synchronizerError?.let {
statusText = context.getString(
R.string.account_status_error,
walletSnapshot.synchronizerError.getCauseMessage()
?: context.getString(R.string.account_status_error_unknown)
)
}
return WalletDisplayValues(
progress = progress,
zecAmountText = zecAmountText,
statusText = statusText,
fiatCurrencyAmountState = fiatCurrencyAmountState,
fiatCurrencyAmountText = fiatCurrencyAmountText
)
}
}
}
private fun getFiatCurrencyRateValue(
context: Context,
fiatCurrencyAmountState: FiatCurrencyConversionRateState
): String {
return fiatCurrencyAmountState.let { state ->
when (state) {
is FiatCurrencyConversionRateState.Current -> state.formattedFiatValue
is FiatCurrencyConversionRateState.Stale -> state.formattedFiatValue
is FiatCurrencyConversionRateState.Unavailable -> {
context.getString(R.string.fiat_currency_conversion_rate_unavailable)
}
}
}
}

View File

@ -0,0 +1,224 @@
package co.electriccoin.zcash.ui.screen.account.view
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
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.Synchronizer
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.BodyWithFiatCurrencySymbol
import co.electriccoin.zcash.ui.design.component.GradientSurface
import co.electriccoin.zcash.ui.design.component.HeaderWithZecIcon
import co.electriccoin.zcash.ui.design.component.PrimaryButton
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
import co.electriccoin.zcash.ui.design.component.TertiaryButton
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.account.AccountTag
import co.electriccoin.zcash.ui.screen.account.model.WalletDisplayValues
@Preview("Account")
@Composable
private fun ComposablePreview() {
ZcashTheme(forceDarkMode = false) {
GradientSurface {
Account(
walletSnapshot = WalletSnapshotFixture.new(),
isUpdateAvailable = false,
isKeepScreenOnDuringSync = false,
isFiatConversionEnabled = false,
goSettings = {},
goReceive = {},
goSend = {},
goHistory = {}
)
}
}
}
@Suppress("LongParameterList")
@Composable
fun Account(
walletSnapshot: WalletSnapshot,
isUpdateAvailable: Boolean,
isKeepScreenOnDuringSync: Boolean?,
isFiatConversionEnabled: Boolean,
goSettings: () -> Unit,
goReceive: () -> Unit,
goSend: () -> Unit,
goHistory: () -> Unit
) {
Scaffold(topBar = {
AccountTopAppBar(onSettings = goSettings)
}) { paddingValues ->
AccountMainContent(
walletSnapshot = walletSnapshot,
isUpdateAvailable = isUpdateAvailable,
isKeepScreenOnDuringSync = isKeepScreenOnDuringSync,
isFiatConversionEnabled = isFiatConversionEnabled,
goReceive = goReceive,
goSend = goSend,
goHistory = goHistory,
modifier = Modifier.padding(
top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault,
bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingHuge,
start = ZcashTheme.dimens.screenHorizontalSpacing,
end = ZcashTheme.dimens.screenHorizontalSpacing
)
)
}
}
@Composable
private fun AccountTopAppBar(
onSettings: () -> Unit
) {
SmallTopAppBar(
showTitleLogo = true,
hamburgerMenuActions = {
IconButton(
onClick = onSettings,
modifier = Modifier.testTag(AccountTag.SETTINGS_TOP_BAR_BUTTON)
) {
Icon(
painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.hamburger_menu_icon),
contentDescription = stringResource(id = R.string.account_menu_content_description)
)
}
}
)
}
@Suppress("LongParameterList")
@Composable
private fun AccountMainContent(
walletSnapshot: WalletSnapshot,
isUpdateAvailable: Boolean,
isKeepScreenOnDuringSync: Boolean?,
isFiatConversionEnabled: Boolean,
goReceive: () -> Unit,
goSend: () -> Unit,
goHistory: () -> Unit,
modifier: Modifier = Modifier
) {
Column(
Modifier
.fillMaxHeight()
.verticalScroll(
rememberScrollState()
)
.then(modifier),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingDefault))
Status(walletSnapshot, isUpdateAvailable, isFiatConversionEnabled)
Spacer(
modifier = Modifier
.fillMaxHeight()
.weight(MINIMAL_WEIGHT)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
PrimaryButton(
onClick = goSend,
text = stringResource(R.string.account_button_send)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
PrimaryButton(
onClick = goReceive,
text = stringResource(R.string.account_button_receive)
)
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
TertiaryButton(onClick = goHistory, text = stringResource(R.string.account_button_history))
if (isKeepScreenOnDuringSync == true && walletSnapshot.status == Synchronizer.Status.SYNCING) {
DisableScreenTimeout()
}
}
}
@Composable
@Suppress("LongMethod", "MagicNumber")
private fun Status(
walletSnapshot: WalletSnapshot,
updateAvailable: Boolean,
isFiatConversionEnabled: Boolean
) {
val walletDisplayValues = WalletDisplayValues.getNextValues(
LocalContext.current,
walletSnapshot,
updateAvailable
)
Column(
modifier = Modifier
.fillMaxWidth()
.testTag(AccountTag.STATUS_VIEWS),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
if (walletDisplayValues.zecAmountText.isNotEmpty()) {
HeaderWithZecIcon(amount = walletDisplayValues.zecAmountText)
}
if (isFiatConversionEnabled) {
Column(Modifier.testTag(AccountTag.FIAT_CONVERSION)) {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
when (walletDisplayValues.fiatCurrencyAmountState) {
is FiatCurrencyConversionRateState.Current -> {
BodyWithFiatCurrencySymbol(
amount = walletDisplayValues.fiatCurrencyAmountText
)
}
is FiatCurrencyConversionRateState.Stale -> {
// Note: we should show information about staleness too
BodyWithFiatCurrencySymbol(
amount = walletDisplayValues.fiatCurrencyAmountText
)
}
is FiatCurrencyConversionRateState.Unavailable -> {
Body(text = walletDisplayValues.fiatCurrencyAmountText)
}
}
}
}
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
if (walletDisplayValues.statusText.isNotEmpty()) {
Body(
text = walletDisplayValues.statusText,
modifier = Modifier.testTag(AccountTag.SINGLE_LINE_TEXT)
)
}
}
}

View File

@ -9,8 +9,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.address.view.WalletAddresses
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
@Composable
internal fun MainActivity.WrapWalletAddresses(

View File

@ -15,9 +15,9 @@ import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.exportdata.util.FileShareUtil
import co.electriccoin.zcash.ui.screen.exportdata.view.ExportPrivateData
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow

View File

@ -6,8 +6,8 @@ import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cash.z.ecc.android.sdk.internal.Twig
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.history.view.History
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
@Composable
internal fun MainActivity.WrapHistory(

View File

@ -3,25 +3,18 @@
package co.electriccoin.zcash.ui.screen.home
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.viewModels
import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.common.closeDrawerMenu
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
import co.electriccoin.zcash.ui.configuration.RemoteConfig
import co.electriccoin.zcash.ui.screen.home.view.Home
import co.electriccoin.zcash.ui.screen.home.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
import kotlinx.coroutines.CoroutineScope
@Composable
@Suppress("LongParameterList")
@ -85,23 +78,3 @@ internal fun WrapHome(
activity.reportFullyDrawn()
}
}
/**
* Custom Drawer menu composable with back navigation handling feature, which returns its necessary values.
*/
@Composable
internal fun drawerBackHandler(
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
scope: CoroutineScope = rememberCoroutineScope()
): DrawerValuesWrapper {
// Override Android back navigation action to close drawer, if opened
BackHandler(drawerState.isOpen) {
drawerState.closeDrawerMenu(scope)
}
return DrawerValuesWrapper(drawerState, scope)
}
internal data class DrawerValuesWrapper(
val drawerState: DrawerState,
val scope: CoroutineScope
)

View File

@ -10,6 +10,9 @@ import cash.z.ecc.android.sdk.model.toFiatCurrencyState
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.model.WalletSnapshot
import co.electriccoin.zcash.ui.common.model.spendableBalance
import co.electriccoin.zcash.ui.common.model.totalBalance
import co.electriccoin.zcash.ui.common.toKotlinLocale
data class WalletDisplayValues(

View File

@ -25,6 +25,7 @@ import cash.z.ecc.android.sdk.Synchronizer
import cash.z.ecc.android.sdk.model.FiatCurrencyConversionRateState
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
import co.electriccoin.zcash.ui.design.component.Body
import co.electriccoin.zcash.ui.design.component.BodyWithFiatCurrencySymbol
@ -37,7 +38,6 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.fixture.WalletSnapshotFixture
import co.electriccoin.zcash.ui.screen.home.HomeTag
import co.electriccoin.zcash.ui.screen.home.model.WalletDisplayValues
import co.electriccoin.zcash.ui.screen.home.model.WalletSnapshot
@Preview("Home")
@Composable

View File

@ -18,9 +18,9 @@ import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
import co.electriccoin.zcash.spackle.FirebaseTestLabUtil
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.common.model.OnboardingState
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.screen.home.model.OnboardingState
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.onboarding.view.ShortOnboarding
import co.electriccoin.zcash.ui.screen.onboarding.viewmodel.OnboardingViewModel
import co.electriccoin.zcash.ui.screen.restore.WrapRestore

View File

@ -8,7 +8,7 @@ import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cash.z.ecc.android.sdk.model.WalletAddresses
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.receive.view.Receive
@Composable

View File

@ -11,7 +11,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cash.z.ecc.sdk.model.ZecRequest
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.request.view.Request
import kotlinx.coroutines.runBlocking

View File

@ -9,7 +9,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import cash.z.ecc.android.sdk.model.SeedPhrase
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.sdk.type.fromResources
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.onboarding.persistExistingWalletWithSeedPhrase
import co.electriccoin.zcash.ui.screen.onboarding.viewmodel.OnboardingViewModel
import co.electriccoin.zcash.ui.screen.restore.view.RestoreWallet

View File

@ -9,7 +9,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.scan.util.SettingsUtil
import co.electriccoin.zcash.ui.screen.scan.view.Scan
import kotlinx.coroutines.launch

View File

@ -7,8 +7,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.screen.home.viewmodel.SecretState
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.seedrecovery.view.SeedRecovery
@Composable

View File

@ -19,8 +19,8 @@ import cash.z.ecc.android.sdk.model.ZecSend
import cash.z.ecc.sdk.extension.send
import co.electriccoin.zcash.spackle.Twig
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.screen.home.model.spendableBalance
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.common.model.spendableBalance
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.send.ext.Saver
import co.electriccoin.zcash.ui.screen.send.model.SendArgumentsWrapper
import co.electriccoin.zcash.ui.screen.send.model.SendStage

View File

@ -8,9 +8,9 @@ import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.configuration.ConfigurationEntries
import co.electriccoin.zcash.ui.configuration.RemoteConfig
import co.electriccoin.zcash.ui.screen.home.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.settings.model.TroubleshootingParameters
import co.electriccoin.zcash.ui.screen.settings.view.Settings
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel

View File

@ -13,7 +13,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.screen.home.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
import co.electriccoin.zcash.ui.screen.update.model.UpdateInfo
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
import co.electriccoin.zcash.ui.screen.update.util.PlayStoreUtil

View File

@ -0,0 +1,24 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="account_menu_content_description">Open Settings</string>
<string name="account_button_receive">Receive</string>
<string name="account_button_send">Send</string>
<string name="account_button_history">Transaction History</string>
<string name="account_status_syncing_format" formatted="true">Syncing - <xliff:g id="synced_percent" example="50.25">
%1$s</xliff:g>%%</string> <!-- double %% for escaping -->
<string name="account_status_syncing_catchup">Syncing</string>
<string name="account_status_syncing_amount_suffix" formatted="true"><xliff:g id="amount_prefix" example="123$">%1$s</xliff:g> so far</string>
<string name="account_status_syncing_additional_information">We will show you funds as we discover them.</string>
<string name="account_status_up_to_date">Up-to-date</string>
<string name="account_status_sending_format" formatted="true">Sending <xliff:g id="sending_amount" example=".023">%1$s</xliff:g></string>
<string name="account_status_receiving_format" formatted="true">Receiving <xliff:g id="receiving_amount" example=".023">%1$s</xliff:g> ZEC</string>
<string name="account_status_shielding_format" formatted="true">Shielding <xliff:g id="shielding_amount" example=".023">%1$s</xliff:g> ZEC</string>
<string name="account_status_update">Please Update</string>
<string name="account_status_error" formatted="true">Error: <xliff:g id="error_type" example="Lost connection">%1$s</xliff:g></string>
<string name="account_status_error_connection">Disconnected</string>
<string name="account_status_error_unknown">Unknown cause</string>
<string name="account_status_stopped">Synchronizer stopped</string>
<string name="account_status_updating_blockheight">Updating blockheight</string>
<string name="account_status_fiat_currency_price_out_of_date" formatted="true"><xliff:g id="fiat_currency" example="USD">%1$s</xliff:g> price out-of-date</string>
<string name="account_status_spendable" formatted="true">Fully spendable in <xliff:g id="spendable_time" example="2 minutes">%1$s</xliff:g></string>
</resources>

View File

@ -37,9 +37,9 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.NavigationTargets
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
import co.electriccoin.zcash.ui.design.component.ConfigurationOverride
import co.electriccoin.zcash.ui.design.component.UiMode
import co.electriccoin.zcash.ui.screen.home.viewmodel.SecretState
import co.electriccoin.zcash.ui.screen.restore.RestoreTag
import co.electriccoin.zcash.ui.screen.restore.viewmodel.RestoreViewModel
import co.electriccoin.zcash.ui.screen.settings.SettingsTag