Code cleanup
This commit is contained in:
parent
d488daeafd
commit
0db65c410a
|
@ -3,7 +3,9 @@ package co.electriccoin.zcash.preference.model.entry
|
|||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import java.time.Instant
|
||||
|
||||
class TimestampPreferenceDefault(override val key: PreferenceKey): PreferenceDefault<Instant?> {
|
||||
class TimestampPreferenceDefault(
|
||||
override val key: PreferenceKey
|
||||
) : PreferenceDefault<Instant?> {
|
||||
override suspend fun getValue(preferenceProvider: PreferenceProvider) =
|
||||
preferenceProvider.getLong(key)?.let { Instant.ofEpochMilli(it) }
|
||||
|
||||
|
|
|
@ -65,7 +65,8 @@ fun ZashiBigIconButton(
|
|||
Modifier.background(darkBgGradient)
|
||||
|
||||
Surface(
|
||||
modifier = modifier
|
||||
modifier =
|
||||
modifier
|
||||
.pointerInput(Unit) {
|
||||
awaitPointerEventScope {
|
||||
while (true) {
|
||||
|
|
|
@ -41,12 +41,12 @@ fun ZashiScreenDialog(
|
|||
|
||||
@Composable
|
||||
private fun Dialog(
|
||||
modifier: Modifier = Modifier,
|
||||
positive: ButtonState,
|
||||
negative: ButtonState,
|
||||
onDismissRequest: (() -> Unit),
|
||||
title: StringResource,
|
||||
message: StringResource,
|
||||
onDismissRequest: (() -> Unit),
|
||||
modifier: Modifier = Modifier,
|
||||
properties: DialogProperties = DialogProperties()
|
||||
) {
|
||||
AlertDialog(
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
@file:Suppress("TooManyFunctions")
|
||||
|
||||
package co.electriccoin.zcash.ui.design.component
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyItemScope
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
|
@ -84,7 +84,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
.align(Alignment.Center),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.height(34.dp)
|
||||
.padding(top = 1.dp)
|
||||
|
@ -92,7 +93,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
)
|
||||
Spacer(36.dp)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.height(34.dp)
|
||||
.padding(top = 1.dp)
|
||||
|
@ -109,7 +111,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
itemVerticalOffset = verticallyVisibleItems,
|
||||
isInfiniteScroll = false,
|
||||
onFocusItem = {
|
||||
state = state.copy(
|
||||
state =
|
||||
state.copy(
|
||||
selectedDate = state.selectedDate.withMonth(state.months[it].value)
|
||||
)
|
||||
},
|
||||
|
@ -133,7 +136,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
isInfiniteScroll = false,
|
||||
onFocusItem = {
|
||||
val year = state.years[it]
|
||||
val normalizedSelectedMonth = getSelectedMonthForYear(
|
||||
val normalizedSelectedMonth =
|
||||
getSelectedMonthForYear(
|
||||
year = year,
|
||||
selectedMonth = state.selectedDate.month,
|
||||
startYearMonth = startInclusive,
|
||||
|
@ -141,7 +145,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
)
|
||||
val months = getMonthsForYear(year, startInclusive, endInclusive)
|
||||
val selectedDate = state.selectedDate.withYear(year.value).withMonth(normalizedSelectedMonth.value)
|
||||
state = state.copy(
|
||||
state =
|
||||
state.copy(
|
||||
selectedDate = selectedDate,
|
||||
months = months
|
||||
)
|
||||
|
@ -161,8 +166,8 @@ fun ZashiYearMonthWheelDatePicker(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getMonthsForYear(year: Year, startYearMonth: YearMonth, endYearMonth: YearMonth): List<Month> {
|
||||
return when (year.value) {
|
||||
private fun getMonthsForYear(year: Year, startYearMonth: YearMonth, endYearMonth: YearMonth): List<Month> =
|
||||
when (year.value) {
|
||||
startYearMonth.year -> {
|
||||
(startYearMonth.month.value..Month.DECEMBER.value).map { index ->
|
||||
Month.entries.first { it.value == index }
|
||||
|
@ -192,24 +197,25 @@ private fun getMonthsForYear(year: Year, startYearMonth: YearMonth, endYearMonth
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedMonthForYear(
|
||||
year: Year,
|
||||
selectedMonth: Month,
|
||||
startYearMonth: YearMonth,
|
||||
endYearMonth: YearMonth
|
||||
): Month {
|
||||
return when (year.value) {
|
||||
): Month =
|
||||
when (year.value) {
|
||||
startYearMonth.year -> {
|
||||
val months = (startYearMonth.month.value..Month.DECEMBER.value).map { index ->
|
||||
val months =
|
||||
(startYearMonth.month.value..Month.DECEMBER.value).map { index ->
|
||||
Month.entries.first { it.value == index }
|
||||
}
|
||||
if (selectedMonth in months) selectedMonth else months.findClosest(selectedMonth)
|
||||
}
|
||||
|
||||
endYearMonth.year -> {
|
||||
val months = (Month.JANUARY.value..endYearMonth.month.value).map { index ->
|
||||
val months =
|
||||
(Month.JANUARY.value..endYearMonth.month.value).map { index ->
|
||||
Month.entries.first { it.value == index }
|
||||
}
|
||||
if (selectedMonth in months) selectedMonth else months.findClosest(selectedMonth)
|
||||
|
@ -217,7 +223,6 @@ private fun getSelectedMonthForYear(
|
|||
|
||||
else -> selectedMonth
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<Month>.findClosest(target: Month): Month {
|
||||
var closestNumber = this[0] // Initialize with the first element
|
||||
|
@ -400,7 +405,8 @@ private data class InternalState(
|
|||
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun Preview() = ZcashTheme {
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
BlankSurface {
|
||||
ZashiYearMonthWheelDatePicker(
|
||||
selection = YearMonth.now(),
|
||||
|
|
|
@ -8,11 +8,15 @@ import androidx.compose.runtime.Stable
|
|||
sealed interface ImageResource {
|
||||
@Immutable
|
||||
@JvmInline
|
||||
value class ByDrawable(@DrawableRes val resource: Int) : ImageResource
|
||||
value class ByDrawable(
|
||||
@DrawableRes val resource: Int
|
||||
) : ImageResource
|
||||
|
||||
@JvmInline
|
||||
@Immutable
|
||||
value class DisplayString(val value: String) : ImageResource
|
||||
value class DisplayString(
|
||||
val value: String
|
||||
) : ImageResource
|
||||
|
||||
@Immutable
|
||||
data object Loading : ImageResource
|
||||
|
|
|
@ -64,7 +64,9 @@ sealed interface StringResource {
|
|||
}
|
||||
|
||||
@Immutable
|
||||
private data class CompositeStringResource(val resources: List<StringResource>): StringResource
|
||||
private data class CompositeStringResource(
|
||||
val resources: List<StringResource>
|
||||
) : StringResource
|
||||
|
||||
@Stable
|
||||
fun stringRes(
|
||||
|
@ -116,7 +118,8 @@ fun StringResource.getValue(
|
|||
convertYearMonth: (YearMonth) -> String = StringResourceDefaults::convertYearMonth,
|
||||
convertAddress: (StringResource.ByAddress) -> String = StringResourceDefaults::convertAddress,
|
||||
convertTransactionId: (StringResource.ByTransactionId) -> String = StringResourceDefaults::convertTransactionId
|
||||
): String = getString(
|
||||
): String =
|
||||
getString(
|
||||
context = LocalContext.current,
|
||||
convertZatoshi = convertZatoshi,
|
||||
convertDateTime = convertDateTime,
|
||||
|
@ -133,7 +136,8 @@ fun StringResource.getString(
|
|||
convertYearMonth: (YearMonth) -> String = StringResourceDefaults::convertYearMonth,
|
||||
convertAddress: (StringResource.ByAddress) -> String = StringResourceDefaults::convertAddress,
|
||||
convertTransactionId: (StringResource.ByTransactionId) -> String = StringResourceDefaults::convertTransactionId
|
||||
): String = when (this) {
|
||||
): String =
|
||||
when (this) {
|
||||
is StringResource.ByResource -> context.getString(resource, *args.normalize(context).toTypedArray())
|
||||
is StringResource.ByString -> value
|
||||
is StringResource.ByZatoshi -> convertZatoshi(zatoshi)
|
||||
|
@ -141,7 +145,8 @@ fun StringResource.getString(
|
|||
is StringResource.ByYearMonth -> convertYearMonth(yearMonth)
|
||||
is StringResource.ByAddress -> convertAddress(this)
|
||||
is StringResource.ByTransactionId -> convertTransactionId(this)
|
||||
is CompositeStringResource -> this.resources.joinToString(separator = "") {
|
||||
is CompositeStringResource ->
|
||||
this.resources.joinToString(separator = "") {
|
||||
it.getString(
|
||||
context = context,
|
||||
convertZatoshi = convertZatoshi,
|
||||
|
|
|
@ -37,7 +37,6 @@ import co.electriccoin.zcash.ui.screen.scan.Scan
|
|||
import co.electriccoin.zcash.ui.screen.scan.viewmodel.ScanViewModel
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.viewmodel.ScanKeystonePCZTViewModel
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.viewmodel.ScanKeystoneSignInRequestViewModel
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackupViewModel
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.SelectKeystoneAccount
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.viewmodel.SelectKeystoneAccountViewModel
|
||||
import co.electriccoin.zcash.ui.screen.send.SendViewModel
|
||||
|
@ -54,6 +53,7 @@ import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHist
|
|||
import co.electriccoin.zcash.ui.screen.transactionnote.TransactionNote
|
||||
import co.electriccoin.zcash.ui.screen.transactionnote.viewmodel.TransactionNoteViewModel
|
||||
import co.electriccoin.zcash.ui.screen.transactionprogress.TransactionProgressViewModel
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackupViewModel
|
||||
import co.electriccoin.zcash.ui.screen.warning.viewmodel.StorageCheckViewModel
|
||||
import co.electriccoin.zcash.ui.screen.whatsnew.viewmodel.WhatsNewViewModel
|
||||
import org.koin.core.module.dsl.viewModel
|
||||
|
|
|
@ -16,18 +16,21 @@ import kotlinx.coroutines.flow.update
|
|||
interface MessageAvailabilityDataSource {
|
||||
val canShowMessage: Flow<Boolean>
|
||||
val canShowShieldMessage: Flow<Boolean>
|
||||
|
||||
fun onMessageShown()
|
||||
|
||||
fun onThirdPartyUiShown()
|
||||
|
||||
fun onShieldingInitiated()
|
||||
}
|
||||
|
||||
class MessageAvailabilityDataSourceImpl(
|
||||
applicationStateProvider: ApplicationStateProvider
|
||||
) : MessageAvailabilityDataSource {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
private val state = MutableStateFlow(
|
||||
private val state =
|
||||
MutableStateFlow(
|
||||
MessageAvailabilityData(
|
||||
isAppInForeground = true,
|
||||
isThirdPartyUiShown = false,
|
||||
|
@ -58,8 +61,7 @@ class MessageAvailabilityDataSourceImpl(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
override fun onMessageShown() {
|
||||
|
|
|
@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.flowOf
|
|||
import java.time.Instant
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface ShieldFundsDataSource {
|
||||
suspend fun observe(forAccount: AccountUuid): Flow<ShieldFundsAvailability>
|
||||
|
@ -27,9 +26,9 @@ class ShieldFundsDataSourceImpl(
|
|||
private val shieldFundsRemindMeCountStorageProvider: ShieldFundsRemindMeCountStorageProvider,
|
||||
private val shieldFundsRemindMeTimestampStorageProvider: ShieldFundsRemindMeTimestampStorageProvider
|
||||
) : ShieldFundsDataSource {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<ShieldFundsAvailability> = combine(
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<ShieldFundsAvailability> =
|
||||
combine(
|
||||
shieldFundsRemindMeCountStorageProvider.observe(forAccount),
|
||||
shieldFundsRemindMeTimestampStorageProvider.observe(forAccount)
|
||||
) { count, timestamp ->
|
||||
|
@ -37,15 +36,18 @@ class ShieldFundsDataSourceImpl(
|
|||
}.flatMapLatest { (count, timestamp) ->
|
||||
when {
|
||||
timestamp == null -> flowOf(ShieldFundsAvailability.Available(ShieldFundsLockoutDuration.TWO_DAYS))
|
||||
count == 1 -> calculateNext(
|
||||
count == 1 ->
|
||||
calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = ShieldFundsLockoutDuration.TWO_DAYS,
|
||||
nextLockoutDuration = ShieldFundsLockoutDuration.TWO_WEEKS
|
||||
)
|
||||
|
||||
else -> calculateNext(
|
||||
else ->
|
||||
calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = if (count == 2) {
|
||||
lastLockoutDuration =
|
||||
if (count == 2) {
|
||||
ShieldFundsLockoutDuration.TWO_WEEKS
|
||||
} else {
|
||||
ShieldFundsLockoutDuration.ONE_MONTH
|
||||
|
@ -83,11 +85,17 @@ class ShieldFundsDataSourceImpl(
|
|||
}
|
||||
|
||||
sealed interface ShieldFundsAvailability {
|
||||
data class Available(val lockoutDuration: ShieldFundsLockoutDuration) : ShieldFundsAvailability
|
||||
data class Available(
|
||||
val lockoutDuration: ShieldFundsLockoutDuration
|
||||
) : ShieldFundsAvailability
|
||||
|
||||
data object Unavailable : ShieldFundsAvailability
|
||||
}
|
||||
|
||||
enum class ShieldFundsLockoutDuration(val duration: Duration, @StringRes val res: Int) {
|
||||
enum class ShieldFundsLockoutDuration(
|
||||
val duration: Duration,
|
||||
@StringRes val res: Int
|
||||
) {
|
||||
TWO_DAYS(2.days, R.string.general_remind_me_in_two_days),
|
||||
TWO_WEEKS(2.days, R.string.general_remind_me_in_two_weeks),
|
||||
ONE_MONTH(30.days, R.string.general_remind_me_in_two_months)
|
||||
|
|
|
@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.flowOf
|
|||
import java.time.Instant
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface WalletBackupDataSource {
|
||||
fun observe(): Flow<WalletBackupAvailability>
|
||||
|
@ -30,9 +29,9 @@ class WalletBackupDataSourceImpl(
|
|||
private val walletBackupRemindMeCountStorageProvider: WalletBackupRemindMeCountStorageProvider,
|
||||
private val walletBackupRemindMeTimestampStorageProvider: WalletBackupRemindMeTimestampStorageProvider
|
||||
) : WalletBackupDataSource {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun observe(): Flow<WalletBackupAvailability> = combine(
|
||||
override fun observe(): Flow<WalletBackupAvailability> =
|
||||
combine(
|
||||
walletBackupFlagStorageProvider.observe(),
|
||||
walletBackupRemindMeCountStorageProvider.observe(),
|
||||
walletBackupRemindMeTimestampStorageProvider.observe()
|
||||
|
@ -42,15 +41,18 @@ class WalletBackupDataSourceImpl(
|
|||
when {
|
||||
isBackedUp -> flowOf(WalletBackupAvailability.Unavailable)
|
||||
timestamp == null -> flowOf(WalletBackupAvailability.Available(WalletBackupLockoutDuration.TWO_DAYS))
|
||||
count == 1 -> calculateNext(
|
||||
count == 1 ->
|
||||
calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = WalletBackupLockoutDuration.TWO_DAYS,
|
||||
nextLockoutDuration = WalletBackupLockoutDuration.TWO_WEEKS
|
||||
)
|
||||
|
||||
else -> calculateNext(
|
||||
else ->
|
||||
calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = if (count == 2) {
|
||||
lastLockoutDuration =
|
||||
if (count == 2) {
|
||||
WalletBackupLockoutDuration.TWO_WEEKS
|
||||
} else {
|
||||
WalletBackupLockoutDuration.ONE_MONTH
|
||||
|
@ -92,11 +94,17 @@ class WalletBackupDataSourceImpl(
|
|||
}
|
||||
|
||||
sealed interface WalletBackupAvailability {
|
||||
data class Available(val lockoutDuration: WalletBackupLockoutDuration) : WalletBackupAvailability
|
||||
data class Available(
|
||||
val lockoutDuration: WalletBackupLockoutDuration
|
||||
) : WalletBackupAvailability
|
||||
|
||||
data object Unavailable : WalletBackupAvailability
|
||||
}
|
||||
|
||||
enum class WalletBackupLockoutDuration(val duration: Duration, @StringRes val res: Int) {
|
||||
enum class WalletBackupLockoutDuration(
|
||||
val duration: Duration,
|
||||
@StringRes val res: Int
|
||||
) {
|
||||
TWO_DAYS(2.days, R.string.general_remind_me_in_two_days),
|
||||
TWO_WEEKS(14.days, R.string.general_remind_me_in_two_weeks),
|
||||
ONE_MONTH(30.days, R.string.general_remind_me_in_two_months),
|
||||
|
|
|
@ -30,11 +30,11 @@ class WalletSnapshotDataSourceImpl(
|
|||
synchronizerProvider: SynchronizerProvider,
|
||||
walletRestoringStateProvider: WalletRestoringStateProvider,
|
||||
) : WalletSnapshotDataSource {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val flow = synchronizerProvider
|
||||
val flow =
|
||||
synchronizerProvider
|
||||
.synchronizer
|
||||
.flatMapLatest { synchronizer ->
|
||||
if (synchronizer == null) {
|
||||
|
@ -56,8 +56,7 @@ class WalletSnapshotDataSourceImpl(
|
|||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = null
|
||||
|
|
|
@ -53,17 +53,10 @@ sealed interface WalletAccount : Comparable<WalletAccount> {
|
|||
val isShieldedPending: Boolean
|
||||
get() = pendingShieldedBalance > Zatoshi(0)
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
val isShieldingAvailable: Boolean
|
||||
get() = totalTransparentBalance > Zatoshi(100000L)
|
||||
|
||||
val isProcessingZeroSpendableBalance: Boolean
|
||||
get() {
|
||||
if (totalShieldedBalance == Zatoshi(0) && totalTransparentBalance > Zatoshi(0)) {
|
||||
return false
|
||||
}
|
||||
return totalBalance > Zatoshi(0) && totalShieldedBalance == Zatoshi(0)
|
||||
}
|
||||
|
||||
fun canSpend(amount: Zatoshi): Boolean = spendableShieldedBalance >= amount
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package co.electriccoin.zcash.ui.common.model
|
||||
|
||||
import cash.z.ecc.android.sdk.Synchronizer
|
||||
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.common.viewmodel.SynchronizerError
|
||||
|
||||
// TODO [#292]: Should be moved to SDK-EXT-UI module.
|
||||
|
|
|
@ -5,6 +5,9 @@ import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
|||
|
||||
interface BooleanStorageProvider : StorageProvider<Boolean>
|
||||
|
||||
abstract class BaseBooleanStorageProvider(key: PreferenceKey) : BaseStorageProvider<Boolean>(), BooleanStorageProvider {
|
||||
abstract class BaseBooleanStorageProvider(
|
||||
key: PreferenceKey
|
||||
) : BaseStorageProvider<Boolean>(),
|
||||
BooleanStorageProvider {
|
||||
override val default = BooleanPreferenceDefault(key = key, defaultValue = false)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
|||
|
||||
interface IntStorageProvider : StorageProvider<Int>
|
||||
|
||||
abstract class BaseIntStorageProvider(key: PreferenceKey) : IntStorageProvider, BaseStorageProvider<Int>() {
|
||||
abstract class BaseIntStorageProvider(
|
||||
key: PreferenceKey
|
||||
) : BaseStorageProvider<Int>(),
|
||||
IntStorageProvider {
|
||||
override val default = IntegerPreferenceDefault(key = key, defaultValue = 0)
|
||||
}
|
||||
|
|
|
@ -7,4 +7,5 @@ interface RestoreTimestampStorageProvider : TimestampStorageProvider
|
|||
|
||||
class RestoreTimestampStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseTimestampStorageProvider(PreferenceKey("restore_timestamp")), RestoreTimestampStorageProvider
|
||||
) : BaseTimestampStorageProvider(PreferenceKey("restore_timestamp")),
|
||||
RestoreTimestampStorageProvider
|
||||
|
|
|
@ -2,7 +2,6 @@ package co.electriccoin.zcash.ui.common.provider
|
|||
|
||||
import cash.z.ecc.android.sdk.model.AccountUuid
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -18,22 +17,21 @@ interface ShieldFundsRemindMeCountStorageProvider {
|
|||
class ShieldFundsRemindMeCountStorageProviderImpl(
|
||||
private val encryptedPreferenceProvider: EncryptedPreferenceProvider
|
||||
) : ShieldFundsRemindMeCountStorageProvider {
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun getDefault(forAccount: AccountUuid): IntegerPreferenceDefault {
|
||||
val key = PreferenceKey("shield_funds_remind_me_count_${forAccount.value.toHexString()}")
|
||||
return IntegerPreferenceDefault(key = key, defaultValue = 0)
|
||||
}
|
||||
|
||||
override suspend fun get(forAccount: AccountUuid): Int {
|
||||
return getDefault(forAccount).getValue(encryptedPreferenceProvider())
|
||||
}
|
||||
override suspend fun get(forAccount: AccountUuid): Int =
|
||||
getDefault(forAccount)
|
||||
.getValue(encryptedPreferenceProvider())
|
||||
|
||||
override suspend fun store(forAccount: AccountUuid, amount: Int) {
|
||||
getDefault(forAccount).putValue(encryptedPreferenceProvider(), amount)
|
||||
}
|
||||
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Int> {
|
||||
return getDefault(forAccount).observe(encryptedPreferenceProvider())
|
||||
}
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Int> =
|
||||
getDefault(forAccount)
|
||||
.observe(encryptedPreferenceProvider())
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ package co.electriccoin.zcash.ui.common.provider
|
|||
|
||||
import cash.z.ecc.android.sdk.model.AccountUuid
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.TimestampPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import co.electriccoin.zcash.preference.model.entry.TimestampPreferenceDefault
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.Instant
|
||||
|
||||
|
@ -24,15 +24,13 @@ class ShieldFundsRemindMeTimestampStorageProviderImpl(
|
|||
return TimestampPreferenceDefault(key = key)
|
||||
}
|
||||
|
||||
override suspend fun get(forAccount: AccountUuid): Instant? {
|
||||
return getDefault(forAccount).getValue(encryptedPreferenceProvider())
|
||||
}
|
||||
override suspend fun get(forAccount: AccountUuid) = getDefault(forAccount).getValue(encryptedPreferenceProvider())
|
||||
|
||||
override suspend fun store(forAccount: AccountUuid, timestamp: Instant) {
|
||||
getDefault(forAccount).putValue(encryptedPreferenceProvider(), timestamp)
|
||||
}
|
||||
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Instant?> {
|
||||
return getDefault(forAccount).observe(encryptedPreferenceProvider())
|
||||
}
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Instant?> =
|
||||
getDefault(forAccount)
|
||||
.observe(encryptedPreferenceProvider())
|
||||
}
|
||||
|
|
|
@ -58,4 +58,3 @@ abstract class BaseNullableStorageProvider<T : Any> : NullableStorageProvider<T>
|
|||
|
||||
private suspend fun getPreferenceProvider(): PreferenceProvider = preferenceHolder()
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
@ -18,7 +17,6 @@ import kotlinx.coroutines.flow.flow
|
|||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.time.Duration
|
||||
|
||||
interface SynchronizerProvider {
|
||||
val synchronizer: StateFlow<Synchronizer?>
|
||||
|
|
|
@ -8,6 +8,7 @@ interface TimestampStorageProvider : NullableStorageProvider<Instant>
|
|||
|
||||
abstract class BaseTimestampStorageProvider(
|
||||
key: PreferenceKey
|
||||
) : BaseNullableStorageProvider<Instant>(), TimestampStorageProvider {
|
||||
) : BaseNullableStorageProvider<Instant>(),
|
||||
TimestampStorageProvider {
|
||||
override val default = TimestampPreferenceDefault(key)
|
||||
}
|
|
@ -7,4 +7,5 @@ interface WalletBackupConsentStorageProvider : BooleanStorageProvider
|
|||
|
||||
class WalletBackupConsentStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseBooleanStorageProvider(key = PreferenceKey("wallet_backup_consent")), WalletBackupConsentStorageProvider
|
||||
) : BaseBooleanStorageProvider(key = PreferenceKey("wallet_backup_consent")),
|
||||
WalletBackupConsentStorageProvider
|
||||
|
|
|
@ -7,4 +7,5 @@ interface WalletBackupFlagStorageProvider : BooleanStorageProvider
|
|||
|
||||
class WalletBackupFlagStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseBooleanStorageProvider(key = PreferenceKey("wallet_backup_flag")), WalletBackupFlagStorageProvider
|
||||
) : BaseBooleanStorageProvider(key = PreferenceKey("wallet_backup_flag")),
|
||||
WalletBackupFlagStorageProvider
|
||||
|
|
|
@ -11,12 +11,12 @@ interface WalletRestoringStateProvider : StorageProvider<WalletRestoringState>
|
|||
|
||||
class WalletRestoringStateProviderImpl(
|
||||
override val preferenceHolder: StandardPreferenceProvider,
|
||||
) : BaseStorageProvider<WalletRestoringState>(), WalletRestoringStateProvider {
|
||||
) : BaseStorageProvider<WalletRestoringState>(),
|
||||
WalletRestoringStateProvider {
|
||||
override val default: PreferenceDefault<WalletRestoringState> = WalletRestoringStatePreferenceDefault()
|
||||
}
|
||||
|
||||
private class WalletRestoringStatePreferenceDefault : PreferenceDefault<WalletRestoringState> {
|
||||
|
||||
private val internal = StandardPreferenceKeys.WALLET_RESTORING_STATE
|
||||
|
||||
override val key: PreferenceKey = internal.key
|
||||
|
|
|
@ -44,7 +44,6 @@ class ExchangeRateRepositoryImpl(
|
|||
private val synchronizerProvider: SynchronizerProvider,
|
||||
private val standardPreferenceProvider: StandardPreferenceProvider,
|
||||
) : ExchangeRateRepository {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
private val isExchangeRateUsdOptedIn = nullableBooleanStateFlow(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN)
|
||||
|
|
|
@ -28,7 +28,6 @@ interface HomeMessageCacheRepository {
|
|||
class HomeMessageCacheRepositoryImpl(
|
||||
private val messageAvailabilityDataSource: MessageAvailabilityDataSource
|
||||
) : HomeMessageCacheRepository {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
override var lastShownMessage: HomeMessageData? = null
|
||||
|
@ -42,8 +41,7 @@ class HomeMessageCacheRepositoryImpl(
|
|||
lastShownMessage = null
|
||||
lastMessage = null
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
}.launchIn(scope)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
|
@ -52,21 +50,33 @@ class HomeMessageCacheRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
sealed interface HomeMessageData {
|
||||
|
||||
val priority: Int
|
||||
|
||||
data class Error(val synchronizerError: SynchronizerError) : RuntimeMessage()
|
||||
data class Error(
|
||||
val synchronizerError: SynchronizerError
|
||||
) : RuntimeMessage()
|
||||
|
||||
data object Disconnected : RuntimeMessage()
|
||||
data class Restoring(val progress: Float) : RuntimeMessage()
|
||||
data class Syncing(val progress: Float) : RuntimeMessage()
|
||||
|
||||
data class Restoring(
|
||||
val progress: Float
|
||||
) : RuntimeMessage()
|
||||
|
||||
data class Syncing(
|
||||
val progress: Float
|
||||
) : RuntimeMessage()
|
||||
|
||||
data object Updating : RuntimeMessage()
|
||||
|
||||
data object Backup : Prioritized {
|
||||
override val priority: Int = 4
|
||||
}
|
||||
|
||||
data class ShieldFunds(val zatoshi: Zatoshi) : Prioritized {
|
||||
data class ShieldFunds(
|
||||
val zatoshi: Zatoshi
|
||||
) : Prioritized {
|
||||
override val priority: Int = 3
|
||||
}
|
||||
|
||||
|
@ -82,6 +92,7 @@ sealed interface HomeMessageData {
|
|||
/**
|
||||
* Message which always is shown.
|
||||
*/
|
||||
@Suppress("MagicNumber")
|
||||
sealed class RuntimeMessage : HomeMessageData {
|
||||
override val priority: Int = 5
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
interface ShieldFundsRepository {
|
||||
val availability: Flow<ShieldFundsData>
|
||||
|
@ -25,7 +24,8 @@ class ShieldFundsRepositoryImpl(
|
|||
private val messageAvailabilityDataSource: MessageAvailabilityDataSource,
|
||||
) : ShieldFundsRepository {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val availability: Flow<ShieldFundsData> = accountDataSource
|
||||
override val availability: Flow<ShieldFundsData> =
|
||||
accountDataSource
|
||||
.selectedAccount
|
||||
.flatMapLatest { account ->
|
||||
when {
|
||||
|
@ -38,7 +38,8 @@ class ShieldFundsRepositoryImpl(
|
|||
) { canShowShieldMessage, availability ->
|
||||
when {
|
||||
!canShowShieldMessage -> ShieldFundsData.Unavailable
|
||||
availability is ShieldFundsAvailability.Available -> ShieldFundsData.Available(
|
||||
availability is ShieldFundsAvailability.Available ->
|
||||
ShieldFundsData.Available(
|
||||
lockoutDuration = availability.lockoutDuration,
|
||||
amount = account.transparent.balance
|
||||
)
|
||||
|
|
|
@ -73,19 +73,21 @@ class TransactionRepositoryImpl(
|
|||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val currentTransactions: Flow<List<Transaction>?> = accountDataSource.selectedAccount
|
||||
override val currentTransactions: Flow<List<Transaction>?> =
|
||||
accountDataSource.selectedAccount
|
||||
.distinctUntilChangedBy { it?.sdkAccount?.accountUuid }
|
||||
.flatMapLatest { selected ->
|
||||
if (selected is ZashiAccount) {
|
||||
zashiTransactions
|
||||
} else {
|
||||
observeTransactions(
|
||||
accountFlow = accountDataSource.selectedAccount.map { it?.sdkAccount?.accountUuid }
|
||||
accountFlow =
|
||||
accountDataSource.selectedAccount
|
||||
.map { it?.sdkAccount?.accountUuid }
|
||||
.distinctUntilChanged()
|
||||
)
|
||||
}
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.WhileSubscribed(5.seconds, Duration.ZERO),
|
||||
initialValue = null
|
||||
|
@ -123,6 +125,7 @@ class TransactionRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private suspend fun createTransactions(
|
||||
transactions: List<TransactionOverview>,
|
||||
synchronizer: Synchronizer
|
||||
|
|
|
@ -6,7 +6,6 @@ import cash.z.ecc.android.sdk.Synchronizer
|
|||
import cash.z.ecc.android.sdk.WalletInitMode
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.FastestServersResult
|
||||
import cash.z.ecc.android.sdk.model.PercentDecimal
|
||||
import cash.z.ecc.android.sdk.model.PersistableWallet
|
||||
import cash.z.ecc.android.sdk.model.SeedPhrase
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
|
@ -14,7 +13,6 @@ import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
|||
import co.electriccoin.lightwallet.client.model.LightWalletEndpoint
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.StandardPreferenceProvider
|
||||
import co.electriccoin.zcash.spackle.Twig
|
||||
import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletSnapshotDataSource
|
||||
|
@ -28,7 +26,6 @@ import co.electriccoin.zcash.ui.common.provider.PersistableWalletProvider
|
|||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletRestoringStateProvider
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.SecretState
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.SynchronizerError
|
||||
import co.electriccoin.zcash.ui.preference.PersistableWalletPreferenceDefault
|
||||
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
|
||||
import co.electriccoin.zcash.ui.screen.chooseserver.AvailableServerProvider
|
||||
|
@ -36,13 +33,11 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
|
@ -51,7 +46,6 @@ import kotlinx.coroutines.flow.filterNotNull
|
|||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -196,7 +190,8 @@ class WalletRepositoryImpl(
|
|||
/**
|
||||
* A flow of the wallet block synchronization state.
|
||||
*/
|
||||
override val walletRestoringState: StateFlow<WalletRestoringState> = walletRestoringStateProvider
|
||||
override val walletRestoringState: StateFlow<WalletRestoringState> =
|
||||
walletRestoringStateProvider
|
||||
.observe()
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
|
|
|
@ -23,7 +23,6 @@ class WalletSnapshotRepositoryImpl(
|
|||
private val synchronizerProvider: SynchronizerProvider,
|
||||
private val walletRestoringStateProvider: WalletRestoringStateProvider
|
||||
) : WalletSnapshotRepository {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
@ -38,8 +37,7 @@ class WalletSnapshotRepositoryImpl(
|
|||
status to restoringState
|
||||
}
|
||||
}
|
||||
}
|
||||
.collect { (status, restoringState) ->
|
||||
}.collect { (status, restoringState) ->
|
||||
// Once the wallet is fully synced and still in restoring state, persist the new state
|
||||
if (status == Synchronizer.Status.SYNCED && restoringState in listOf(RESTORING, NONE)) {
|
||||
walletRestoringStateProvider.store(WalletRestoringState.SYNCING)
|
||||
|
|
|
@ -43,7 +43,8 @@ class CreateFlexaTransactionUseCase(
|
|||
)
|
||||
}.onSuccess { proposal ->
|
||||
Twig.debug { "Transaction proposal successful: ${proposal.toPrettyString()}" }
|
||||
val result = submitTransactions(
|
||||
val result =
|
||||
submitTransactions(
|
||||
proposal = proposal,
|
||||
spendingKey = zashiSpendingKeyDataSource.getZashiSpendingKey()
|
||||
)
|
||||
|
|
|
@ -38,36 +38,44 @@ class GetHomeMessageUseCase(
|
|||
private val messageAvailabilityDataSource: MessageAvailabilityDataSource,
|
||||
private val cache: HomeMessageCacheRepository,
|
||||
) {
|
||||
private val backupFlow = combine(
|
||||
private val backupFlow =
|
||||
combine(
|
||||
transactionRepository.zashiTransactions,
|
||||
walletBackupDataSource.observe()
|
||||
) { transactions, backup ->
|
||||
if (backup is WalletBackupAvailability.Available && transactions.orEmpty().any { it is ReceiveTransaction }) {
|
||||
if (backup is WalletBackupAvailability.Available &&
|
||||
transactions.orEmpty().any { it is ReceiveTransaction }
|
||||
) {
|
||||
backup
|
||||
} else {
|
||||
WalletBackupAvailability.Unavailable
|
||||
}
|
||||
}.distinctUntilChanged()
|
||||
|
||||
private val runtimeMessage = channelFlow {
|
||||
@Suppress("MagicNumber")
|
||||
private val runtimeMessage =
|
||||
channelFlow {
|
||||
var firstSyncing: WalletSnapshot? = null
|
||||
launch {
|
||||
walletSnapshotDataSource
|
||||
.observe()
|
||||
.filterNotNull()
|
||||
.collect { walletSnapshot ->
|
||||
val result = when {
|
||||
val result =
|
||||
when {
|
||||
walletSnapshot.synchronizerError != null ->
|
||||
HomeMessageData.Error(walletSnapshot.synchronizerError)
|
||||
|
||||
walletSnapshot.status == Synchronizer.Status.DISCONNECTED ->
|
||||
HomeMessageData.Disconnected
|
||||
|
||||
walletSnapshot.status in listOf(
|
||||
walletSnapshot.status in
|
||||
listOf(
|
||||
Synchronizer.Status.INITIALIZING,
|
||||
Synchronizer.Status.SYNCING,
|
||||
Synchronizer.Status.STOPPED
|
||||
) -> {
|
||||
)
|
||||
-> {
|
||||
val progress = walletSnapshot.progress.decimal * 100f
|
||||
if (walletSnapshot.restoringState == WalletRestoringState.RESTORING) {
|
||||
HomeMessageData.Restoring(progress = progress)
|
||||
|
@ -102,7 +110,8 @@ class GetHomeMessageUseCase(
|
|||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
private val flow = combine(
|
||||
private val flow =
|
||||
combine(
|
||||
runtimeMessage,
|
||||
backupFlow,
|
||||
exchangeRateRepository.state.map { it == ExchangeRateState.OptIn }.distinctUntilChanged(),
|
||||
|
@ -133,11 +142,13 @@ class GetHomeMessageUseCase(
|
|||
val someMessageBeenShown = cache.lastShownMessage != null // has any message been shown while app in fg
|
||||
val hasNoMessageBeenShownLately = cache.lastMessage == null // has no message been shown
|
||||
val isHigherPriorityMessage = (message?.priority ?: 0) > (cache.lastShownMessage?.priority ?: 0)
|
||||
val result = when {
|
||||
val result =
|
||||
when {
|
||||
message == null -> null
|
||||
message is RuntimeMessage -> message
|
||||
isSameMessageUpdate -> message
|
||||
isHigherPriorityMessage -> if (hasNoMessageBeenShownLately) {
|
||||
isHigherPriorityMessage ->
|
||||
if (hasNoMessageBeenShownLately) {
|
||||
if (someMessageBeenShown) null else message
|
||||
} else {
|
||||
message
|
||||
|
|
|
@ -29,8 +29,19 @@ class NavigateToErrorUseCase(
|
|||
}
|
||||
|
||||
sealed interface ErrorArgs {
|
||||
data class SyncError(val synchronizerError: SynchronizerError) : ErrorArgs
|
||||
data class ShieldingError(val error: SubmitResult.Failure): ErrorArgs
|
||||
data class ShieldingGeneralError(val exception: Exception): ErrorArgs
|
||||
data class General(val exception: Exception): ErrorArgs
|
||||
data class SyncError(
|
||||
val synchronizerError: SynchronizerError
|
||||
) : ErrorArgs
|
||||
|
||||
data class ShieldingError(
|
||||
val error: SubmitResult.Failure
|
||||
) : ErrorArgs
|
||||
|
||||
data class ShieldingGeneralError(
|
||||
val exception: Exception
|
||||
) : ErrorArgs
|
||||
|
||||
data class General(
|
||||
val exception: Exception
|
||||
) : ErrorArgs
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSource
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldFundsRepository
|
||||
|
||||
class RemindShieldFundsLaterUseCase(
|
||||
|
|
|
@ -50,7 +50,6 @@ class SendEmailUseCase(
|
|||
runCatching { context.startActivity(mailIntent) }
|
||||
}
|
||||
|
||||
|
||||
suspend operator fun invoke(synchronizerError: SynchronizerError) {
|
||||
val fullMessage =
|
||||
EmailUtil.formatMessage(
|
||||
|
|
|
@ -46,11 +46,13 @@ class ShieldFundsUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
private suspend fun shieldZashiFunds() {
|
||||
try {
|
||||
zashiProposalRepository.createShieldProposal()
|
||||
zashiProposalRepository.submitTransaction()
|
||||
val result = zashiProposalRepository.submitState
|
||||
val result =
|
||||
zashiProposalRepository.submitState
|
||||
.filterIsInstance<SubmitProposalState.Result>()
|
||||
.first()
|
||||
.submitResult
|
||||
|
@ -65,6 +67,7 @@ class ShieldFundsUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
private suspend fun createKeystoneShieldProposal() {
|
||||
try {
|
||||
keystoneProposalRepository.createShieldProposal()
|
||||
|
|
|
@ -8,8 +8,8 @@ import co.electriccoin.zcash.ui.NavigationTargets
|
|||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToTaxExportUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.listitem.ZashiListItemState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
|
|
@ -103,7 +103,8 @@ private fun BalanceWidgetPreview() {
|
|||
state =
|
||||
BalanceWidgetState(
|
||||
totalBalance = Zatoshi(1234567891234567L),
|
||||
button = BalanceButtonState(
|
||||
button =
|
||||
BalanceButtonState(
|
||||
icon = R.drawable.ic_help,
|
||||
text = stringRes("text"),
|
||||
amount = Zatoshi(1000),
|
||||
|
|
|
@ -41,7 +41,8 @@ internal fun BalanceWidgetButton(
|
|||
state: BalanceButtonState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val colors = ZashiButtonDefaults.secondaryColors(
|
||||
val colors =
|
||||
ZashiButtonDefaults.secondaryColors(
|
||||
containerColor = ZashiColors.Surfaces.bgPrimary,
|
||||
borderColor = ZashiColors.Utility.Gray.utilityGray100
|
||||
)
|
||||
|
@ -53,7 +54,8 @@ internal fun BalanceWidgetButton(
|
|||
shape = RoundedCornerShape(ZashiDimensions.Radius.radiusIg),
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 10.dp),
|
||||
colors = colors.toButtonColors(),
|
||||
elevation = ButtonDefaults.buttonElevation(
|
||||
elevation =
|
||||
ButtonDefaults.buttonElevation(
|
||||
defaultElevation = 1.dp,
|
||||
pressedElevation = 0.dp
|
||||
),
|
||||
|
@ -110,10 +112,12 @@ data class BalanceButtonState(
|
|||
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun Preview() = ZcashTheme {
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
BlankSurface {
|
||||
BalanceWidgetButton(
|
||||
state = BalanceButtonState(
|
||||
state =
|
||||
BalanceButtonState(
|
||||
icon = R.drawable.ic_help,
|
||||
text = stringRes("text"),
|
||||
amount = Zatoshi(1000),
|
||||
|
|
|
@ -34,17 +34,20 @@ class BalanceWidgetViewModel(
|
|||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = createState(
|
||||
initialValue =
|
||||
createState(
|
||||
account = accountDataSource.allAccounts.value?.firstOrNull { it.isSelected },
|
||||
exchangeRateUsd = exchangeRateRepository.state.value
|
||||
)
|
||||
)
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun createState(account: WalletAccount?, exchangeRateUsd: ExchangeRateState) =
|
||||
BalanceWidgetState(
|
||||
totalBalance = account?.totalBalance ?: Zatoshi(0),
|
||||
exchangeRate = if (args.isExchangeRateButtonEnabled) exchangeRateUsd else null,
|
||||
button = when {
|
||||
button =
|
||||
when {
|
||||
!args.isBalanceButtonEnabled -> null
|
||||
account == null -> null
|
||||
account.totalBalance == account.spendableShieldedBalance -> null
|
||||
|
@ -72,8 +75,8 @@ class BalanceWidgetViewModel(
|
|||
onClick = ::onBalanceButtonClick
|
||||
)
|
||||
|
||||
|
||||
account.totalBalance > account.spendableShieldedBalance -> BalanceButtonState(
|
||||
account.totalBalance > account.spendableShieldedBalance ->
|
||||
BalanceButtonState(
|
||||
icon = R.drawable.ic_balances_expand,
|
||||
text = stringRes(R.string.widget_balances_button_spendable),
|
||||
amount = account.spendableShieldedBalance,
|
||||
|
|
|
@ -108,7 +108,8 @@ private fun BalanceActionRow(state: BalanceActionRowState) {
|
|||
)
|
||||
Spacer(1f)
|
||||
when (state.icon) {
|
||||
is ImageResource.ByDrawable -> Image(
|
||||
is ImageResource.ByDrawable ->
|
||||
Image(
|
||||
modifier = Modifier.size(20.dp),
|
||||
painter = painterResource(state.icon.resource),
|
||||
contentDescription = null
|
||||
|
@ -122,7 +123,8 @@ private fun BalanceActionRow(state: BalanceActionRowState) {
|
|||
SelectionContainer {
|
||||
Text(
|
||||
text = state.value.getValue(),
|
||||
color = if (state.icon is ImageResource.Loading) {
|
||||
color =
|
||||
if (state.icon is ImageResource.Loading) {
|
||||
ZashiColors.Text.textTertiary
|
||||
} else {
|
||||
ZashiColors.Text.textPrimary
|
||||
|
@ -176,9 +178,11 @@ private fun BalanceShieldButton(state: BalanceShieldButtonState) {
|
|||
}
|
||||
Spacer(1f)
|
||||
ZashiButton(
|
||||
state = ButtonState(
|
||||
state =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.balance_action_shield),
|
||||
onClick = state.onShieldClick)
|
||||
onClick = state.onShieldClick
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -187,16 +191,20 @@ private fun BalanceShieldButton(state: BalanceShieldButtonState) {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun Preview() = ZcashTheme {
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
BalanceActionView(
|
||||
state = BalanceActionState(
|
||||
state =
|
||||
BalanceActionState(
|
||||
title = stringRes("Title"),
|
||||
message = stringRes("Subtitle"),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes("Positive")
|
||||
),
|
||||
onBack = {},
|
||||
rows = listOf(
|
||||
rows =
|
||||
listOf(
|
||||
BalanceActionRowState(
|
||||
title = stringRes("Row"),
|
||||
icon = loadingImageRes(),
|
||||
|
@ -208,7 +216,8 @@ private fun Preview() = ZcashTheme {
|
|||
value = stringRes("Value")
|
||||
)
|
||||
),
|
||||
shieldButton = BalanceShieldButtonState(
|
||||
shieldButton =
|
||||
BalanceShieldButtonState(
|
||||
amount = Zatoshi(10000),
|
||||
onShieldClick = {}
|
||||
)
|
||||
|
|
|
@ -23,14 +23,19 @@ class BalanceActionViewModel(
|
|||
private val navigationRouter: NavigationRouter,
|
||||
private val shieldFunds: ShieldFundsUseCase,
|
||||
) : ViewModel() {
|
||||
val state = accountDataSource.selectedAccount
|
||||
val state =
|
||||
accountDataSource.selectedAccount
|
||||
.mapNotNull {
|
||||
createState(it)
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = createState(accountDataSource.allAccounts.value.orEmpty().firstOrNull { it.isSelected })
|
||||
initialValue =
|
||||
createState(
|
||||
accountDataSource.allAccounts.value
|
||||
.orEmpty()
|
||||
.firstOrNull { it.isSelected }
|
||||
)
|
||||
)
|
||||
|
||||
private fun createState(account: WalletAccount?): BalanceActionState? {
|
||||
|
@ -47,7 +52,8 @@ class BalanceActionViewModel(
|
|||
}
|
||||
|
||||
private fun createMessage(account: WalletAccount): StringResource {
|
||||
val pending = when {
|
||||
val pending =
|
||||
when {
|
||||
account.totalShieldedBalance == account.spendableShieldedBalance ->
|
||||
stringRes(R.string.balance_action_all_shielded)
|
||||
|
||||
|
@ -66,8 +72,10 @@ class BalanceActionViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun createPositiveButton(account: WalletAccount) = ButtonState(
|
||||
text = if (account.isShieldingAvailable) {
|
||||
private fun createPositiveButton(account: WalletAccount) =
|
||||
ButtonState(
|
||||
text =
|
||||
if (account.isShieldingAvailable) {
|
||||
stringRes(R.string.general_dismiss)
|
||||
} else {
|
||||
stringRes(R.string.general_ok)
|
||||
|
@ -75,7 +83,8 @@ class BalanceActionViewModel(
|
|||
onClick = ::onBack
|
||||
)
|
||||
|
||||
private fun createInfoRows(account: WalletAccount) = listOfNotNull(
|
||||
private fun createInfoRows(account: WalletAccount) =
|
||||
listOfNotNull(
|
||||
BalanceActionRowState(
|
||||
title = stringRes(R.string.balance_action_info_shielded),
|
||||
icon = imageRes(R.drawable.ic_balance_shield),
|
||||
|
@ -93,7 +102,8 @@ class BalanceActionViewModel(
|
|||
BalanceActionRowState(
|
||||
title = stringRes(R.string.balance_action_info_pending),
|
||||
icon = loadingImageRes(),
|
||||
value = stringRes(
|
||||
value =
|
||||
stringRes(
|
||||
R.string.general_zec,
|
||||
stringRes(account.totalShieldedBalance - account.spendableShieldedBalance)
|
||||
)
|
||||
|
@ -103,12 +113,11 @@ class BalanceActionViewModel(
|
|||
},
|
||||
)
|
||||
|
||||
private fun createShieldButtonState(account: WalletAccount): BalanceShieldButtonState? {
|
||||
return BalanceShieldButtonState(
|
||||
private fun createShieldButtonState(account: WalletAccount): BalanceShieldButtonState? =
|
||||
BalanceShieldButtonState(
|
||||
amount = account.transparent.balance,
|
||||
onShieldClick = ::onShieldClick
|
||||
).takeIf { account.isShieldingAvailable }
|
||||
}
|
||||
|
||||
private fun onBack() = navigationRouter.back()
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import androidx.compose.material3.SnackbarHostState
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.MainActivity
|
||||
import co.electriccoin.zcash.ui.R
|
||||
|
|
|
@ -85,15 +85,19 @@ fun BottomSheetContent(state: ErrorState, modifier: Modifier = Modifier) {
|
|||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun Preview() = ZcashTheme {
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
BottomSheetErrorView(
|
||||
state = ErrorState(
|
||||
state =
|
||||
ErrorState(
|
||||
title = stringRes("Error"),
|
||||
message = stringRes("Something went wrong"),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes("Positive")
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes("Negative")
|
||||
),
|
||||
onBack = {}
|
||||
|
|
|
@ -11,7 +11,8 @@ import co.electriccoin.zcash.ui.design.util.stringRes
|
|||
@Composable
|
||||
fun DialogView(state: ErrorState?) {
|
||||
ZashiScreenDialog(
|
||||
state = state?.let {
|
||||
state =
|
||||
state?.let {
|
||||
DialogState(
|
||||
title = it.title,
|
||||
message = it.message,
|
||||
|
@ -25,15 +26,19 @@ fun DialogView(state: ErrorState?) {
|
|||
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
private fun Preview() = ZcashTheme {
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
DialogView(
|
||||
state = ErrorState(
|
||||
state =
|
||||
ErrorState(
|
||||
title = stringRes("Error"),
|
||||
message = stringRes("Something went wrong"),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes("Positive")
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes("Negative")
|
||||
),
|
||||
onBack = {}
|
||||
|
|
|
@ -33,93 +33,112 @@ class ErrorViewModel(
|
|||
|
||||
private fun onBack() = navigationRouter.back()
|
||||
|
||||
private fun createState(args: ErrorArgs): ErrorState = when (args) {
|
||||
private fun createState(args: ErrorArgs): ErrorState =
|
||||
when (args) {
|
||||
is ErrorArgs.SyncError -> createSyncErrorState(args)
|
||||
is ErrorArgs.ShieldingError -> createShieldingErrorState(args)
|
||||
is ErrorArgs.General -> createGeneralErrorState(args)
|
||||
is ErrorArgs.ShieldingGeneralError -> createGeneralShieldingErrorState(args)
|
||||
}
|
||||
|
||||
private fun createSyncErrorState(args: ErrorArgs.SyncError) = ErrorState(
|
||||
private fun createSyncErrorState(args: ErrorArgs.SyncError) =
|
||||
ErrorState(
|
||||
title = stringRes(R.string.error_sync_title),
|
||||
message = stringRes(args.synchronizerError.getStackTrace(STACKTRACE_LIMIT).orEmpty()),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = { navigationRouter.back() }
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_report),
|
||||
onClick = { sendReportClick(args) }
|
||||
),
|
||||
onBack = ::onBack,
|
||||
)
|
||||
|
||||
private fun createShieldingErrorState(args: ErrorArgs.ShieldingError) = ErrorState(
|
||||
private fun createShieldingErrorState(args: ErrorArgs.ShieldingError) =
|
||||
ErrorState(
|
||||
title = stringRes(R.string.error_shielding_title),
|
||||
message = when (args.error) {
|
||||
message =
|
||||
when (args.error) {
|
||||
is SubmitResult.MultipleTrxFailure -> stringRes(R.string.error_shielding_message_grpc)
|
||||
is SubmitResult.SimpleTrxFailure -> stringRes(
|
||||
is SubmitResult.SimpleTrxFailure ->
|
||||
stringRes(
|
||||
R.string.error_shielding_message,
|
||||
stringRes(args.error.toErrorStacktrace())
|
||||
)
|
||||
},
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = { navigationRouter.back() }
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_report),
|
||||
onClick = { sendReportClick(args) }
|
||||
),
|
||||
onBack = ::onBack,
|
||||
)
|
||||
|
||||
private fun createGeneralErrorState(args: ErrorArgs.General) = ErrorState(
|
||||
private fun createGeneralErrorState(args: ErrorArgs.General) =
|
||||
ErrorState(
|
||||
title = stringRes(R.string.error_general_title),
|
||||
message = stringRes(R.string.error_general_message),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = { navigationRouter.back() }
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_report),
|
||||
onClick = { sendReportClick(args.exception) }
|
||||
),
|
||||
onBack = ::onBack,
|
||||
)
|
||||
|
||||
private fun createGeneralShieldingErrorState(args: ErrorArgs.ShieldingGeneralError) = ErrorState(
|
||||
private fun createGeneralShieldingErrorState(args: ErrorArgs.ShieldingGeneralError) =
|
||||
ErrorState(
|
||||
title = stringRes(R.string.error_shielding_title),
|
||||
message = stringRes(
|
||||
message =
|
||||
stringRes(
|
||||
R.string.error_shielding_message,
|
||||
stringRes(args.exception.stackTraceToString().take(STACKTRACE_LIMIT))
|
||||
),
|
||||
positive = ButtonState(
|
||||
positive =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = { navigationRouter.back() }
|
||||
),
|
||||
negative = ButtonState(
|
||||
negative =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_report),
|
||||
onClick = { sendReportClick(args.exception) }
|
||||
),
|
||||
onBack = ::onBack,
|
||||
)
|
||||
|
||||
private fun sendReportClick(args: ErrorArgs.ShieldingError) = viewModelScope.launch {
|
||||
private fun sendReportClick(args: ErrorArgs.ShieldingError) =
|
||||
viewModelScope.launch {
|
||||
withContext(NonCancellable) {
|
||||
navigationRouter.back()
|
||||
sendEmailUseCase(args.error)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendReportClick(args: ErrorArgs.SyncError) = viewModelScope.launch {
|
||||
private fun sendReportClick(args: ErrorArgs.SyncError) =
|
||||
viewModelScope.launch {
|
||||
withContext(NonCancellable) {
|
||||
navigationRouter.back()
|
||||
sendEmailUseCase(args.synchronizerError)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendReportClick(exception: Exception) = viewModelScope.launch {
|
||||
private fun sendReportClick(exception: Exception) =
|
||||
viewModelScope.launch {
|
||||
withContext(NonCancellable) {
|
||||
navigationRouter.back()
|
||||
sendEmailUseCase(exception)
|
||||
|
|
|
@ -77,7 +77,8 @@ private fun CurrencyConversionOptInPreview() =
|
|||
ZcashTheme {
|
||||
BlankSurface {
|
||||
ExchangeRateOptInView(
|
||||
state = ExchangeRateOptInState(
|
||||
state =
|
||||
ExchangeRateOptInState(
|
||||
onEnableClick = {},
|
||||
onBack = {},
|
||||
onSkipClick = {},
|
||||
|
|
|
@ -10,7 +10,8 @@ class ExchangeRateOptInViewModel(
|
|||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val navigationRouter: NavigationRouter
|
||||
) : ViewModel() {
|
||||
val state: StateFlow<ExchangeRateOptInState> = MutableStateFlow(
|
||||
val state: StateFlow<ExchangeRateOptInState> =
|
||||
MutableStateFlow(
|
||||
ExchangeRateOptInState(
|
||||
onBack = ::dismissOptInExchangeRateUsd,
|
||||
onEnableClick = ::optInExchangeRateUsd,
|
||||
|
|
|
@ -187,7 +187,8 @@ private fun SettingsExchangeRateOptInPreview() =
|
|||
ZcashTheme {
|
||||
BlankSurface {
|
||||
ExchangeRateSettingsView(
|
||||
state = ExchangeRateSettingsState(
|
||||
state =
|
||||
ExchangeRateSettingsState(
|
||||
isOptedIn = true,
|
||||
onSaveClick = {},
|
||||
onDismiss = {}
|
||||
|
|
|
@ -15,12 +15,11 @@ class ExchangeRateSettingsViewModel(
|
|||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
) : ViewModel() {
|
||||
|
||||
val state = exchangeRateRepository.state
|
||||
val state =
|
||||
exchangeRateRepository.state
|
||||
.map {
|
||||
createState(it)
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = createState(exchangeRateRepository.state.value)
|
||||
|
|
|
@ -18,7 +18,8 @@ import org.koin.core.parameter.parametersOf
|
|||
@Composable
|
||||
internal fun AndroidHome() {
|
||||
val topAppBarViewModel = koinActivityViewModel<ZashiTopAppBarViewModel>()
|
||||
val balanceWidgetViewModel = koinViewModel<BalanceWidgetViewModel> {
|
||||
val balanceWidgetViewModel =
|
||||
koinViewModel<BalanceWidgetViewModel> {
|
||||
parametersOf(
|
||||
BalanceWidgetArgs(
|
||||
isBalanceButtonEnabled = false,
|
||||
|
|
|
@ -47,10 +47,10 @@ import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportMessage
|
|||
import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.shieldfunds.ShieldFundsMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.shieldfunds.ShieldFundsMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingMessageState
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -243,6 +243,7 @@ private fun <T> animationSpec(delay: Duration? = null): TweenSpec<T> {
|
|||
)
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun <T> elevationAnimationSpec(delay: Duration? = null): TweenSpec<T> {
|
||||
val delayMs = delay?.inWholeMilliseconds?.toInt() ?: 0
|
||||
return tween(
|
||||
|
|
|
@ -107,8 +107,7 @@ private fun Container(
|
|||
0f to ZashiLightColors.Utility.Purple.utilityPurple500,
|
||||
1f to ZashiLightColors.Utility.Purple.utilityPurple900,
|
||||
)
|
||||
)
|
||||
.clickable(onClick = onClick)
|
||||
).clickable(onClick = onClick)
|
||||
.padding(contentPadding),
|
||||
) {
|
||||
Row(
|
||||
|
|
|
@ -32,8 +32,8 @@ import co.electriccoin.zcash.ui.design.util.scaffoldPadding
|
|||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
|
||||
import co.electriccoin.zcash.ui.fixture.ZashiMainTopAppBarStateFixture
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidget
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetStateFixture
|
||||
|
|
|
@ -28,8 +28,8 @@ import co.electriccoin.zcash.ui.screen.home.currency.EnableCurrencyConversionMes
|
|||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportOptIn
|
||||
import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportOptIn
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.shieldfunds.ShieldFundsInfo
|
||||
|
@ -53,6 +53,7 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class HomeViewModel(
|
||||
getHomeMessage: GetHomeMessageUseCase,
|
||||
getVersionInfoProvider: GetVersionInfoProvider,
|
||||
|
@ -63,8 +64,8 @@ class HomeViewModel(
|
|||
private val shieldFunds: ShieldFundsUseCase,
|
||||
private val navigateToError: NavigateToErrorUseCase
|
||||
) : ViewModel() {
|
||||
|
||||
private val messageState = getHomeMessage
|
||||
private val messageState =
|
||||
getHomeMessage
|
||||
.observe()
|
||||
.map { createMessageState(it) }
|
||||
.stateIn(
|
||||
|
@ -155,37 +156,46 @@ class HomeViewModel(
|
|||
message = messageState
|
||||
)
|
||||
|
||||
private fun createMessageState(it: HomeMessageData?) = when (it) {
|
||||
is HomeMessageData.Backup -> WalletBackupMessageState(
|
||||
private fun createMessageState(it: HomeMessageData?) =
|
||||
when (it) {
|
||||
is HomeMessageData.Backup ->
|
||||
WalletBackupMessageState(
|
||||
onClick = ::onWalletBackupMessageClick,
|
||||
onButtonClick = ::onWalletBackupMessageButtonClick,
|
||||
)
|
||||
|
||||
HomeMessageData.Disconnected -> WalletDisconnectedMessageState(
|
||||
HomeMessageData.Disconnected ->
|
||||
WalletDisconnectedMessageState(
|
||||
onClick = ::onWalletDisconnectedMessageClick
|
||||
)
|
||||
|
||||
HomeMessageData.EnableCurrencyConversion -> EnableCurrencyConversionMessageState(
|
||||
HomeMessageData.EnableCurrencyConversion ->
|
||||
EnableCurrencyConversionMessageState(
|
||||
onClick = ::onEnableCurrencyConversionClick,
|
||||
onButtonClick = ::onEnableCurrencyConversionClick
|
||||
)
|
||||
|
||||
is HomeMessageData.Error -> WalletErrorMessageState(
|
||||
is HomeMessageData.Error ->
|
||||
WalletErrorMessageState(
|
||||
onClick = { onWalletErrorMessageClick(it) }
|
||||
)
|
||||
|
||||
is HomeMessageData.Restoring -> WalletRestoringMessageState(
|
||||
is HomeMessageData.Restoring ->
|
||||
WalletRestoringMessageState(
|
||||
progress = it.progress,
|
||||
onClick = ::onWalletRestoringMessageClick
|
||||
)
|
||||
|
||||
is HomeMessageData.Syncing -> WalletSyncingMessageState(
|
||||
is HomeMessageData.Syncing ->
|
||||
WalletSyncingMessageState(
|
||||
progress = it.progress,
|
||||
onClick = ::onWalletSyncingMessageClick
|
||||
)
|
||||
|
||||
is HomeMessageData.ShieldFunds -> ShieldFundsMessageState(
|
||||
subtitle = stringRes(
|
||||
is HomeMessageData.ShieldFunds ->
|
||||
ShieldFundsMessageState(
|
||||
subtitle =
|
||||
stringRes(
|
||||
R.string.home_message_transparent_balance_subtitle,
|
||||
stringRes(it.zatoshi)
|
||||
),
|
||||
|
@ -193,11 +203,13 @@ class HomeViewModel(
|
|||
onButtonClick = ::onShieldFundsMessageButtonClick,
|
||||
)
|
||||
|
||||
HomeMessageData.Updating -> WalletUpdatingMessageState(
|
||||
HomeMessageData.Updating ->
|
||||
WalletUpdatingMessageState(
|
||||
onClick = ::onWalletUpdatingMessageClick
|
||||
)
|
||||
|
||||
HomeMessageData.CrashReport -> CrashReportMessageState(
|
||||
HomeMessageData.CrashReport ->
|
||||
CrashReportMessageState(
|
||||
onClick = ::onCrashReportMessageClick,
|
||||
onButtonClick = ::onCrashReportMessageClick
|
||||
)
|
||||
|
|
|
@ -20,10 +20,8 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.HorizontalSpacer
|
||||
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.Spacer
|
||||
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiIconButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiInfoRow
|
||||
|
|
|
@ -14,7 +14,8 @@ class WalletBackupDetailViewModel(
|
|||
private val navigationRouter: NavigationRouter,
|
||||
private val navigateToWalletBackup: NavigateToWalletBackupUseCase
|
||||
) : ViewModel() {
|
||||
val state = MutableStateFlow(
|
||||
val state =
|
||||
MutableStateFlow(
|
||||
WalletBackupDetailState(
|
||||
onBack = ::onBack,
|
||||
onNextClick = ::onNextClick,
|
||||
|
@ -39,5 +40,3 @@ class WalletBackupDetailViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,11 +42,11 @@ fun WalletBackupInfoView(
|
|||
state = state
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
modifier =
|
||||
Modifier
|
||||
.weight(1f, false)
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(horizontal = 24.dp)
|
||||
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_info_backup),
|
||||
|
@ -118,16 +118,19 @@ private fun Preview() =
|
|||
WalletBackupInfoView(
|
||||
WalletBackupInfoState(
|
||||
onBack = {},
|
||||
secondaryButton = ButtonState(
|
||||
secondaryButton =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_remind_me_later),
|
||||
onClick = {},
|
||||
isEnabled = false
|
||||
),
|
||||
primaryButton = ButtonState(
|
||||
primaryButton =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = {}
|
||||
),
|
||||
checkboxState = CheckboxState(
|
||||
checkboxState =
|
||||
CheckboxState(
|
||||
isChecked = false,
|
||||
onClick = {},
|
||||
text = stringRes(R.string.home_info_backup_checkbox)
|
||||
|
|
|
@ -31,10 +31,10 @@ class WalletBackupInfoViewModel(
|
|||
private val navigationRouter: NavigationRouter,
|
||||
private val remindWalletBackupLater: RemindWalletBackupLaterUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
private val isConsentChecked = MutableStateFlow(false)
|
||||
|
||||
private val lockoutDuration = walletBackupDataSource
|
||||
private val lockoutDuration =
|
||||
walletBackupDataSource
|
||||
.observe()
|
||||
.filterIsInstance<WalletBackupAvailability.Available>()
|
||||
.take(1)
|
||||
|
@ -45,30 +45,33 @@ class WalletBackupInfoViewModel(
|
|||
initialValue = null
|
||||
)
|
||||
|
||||
val state: StateFlow<WalletBackupInfoState?> = combine(
|
||||
val state: StateFlow<WalletBackupInfoState?> =
|
||||
combine(
|
||||
lockoutDuration.filterNotNull(),
|
||||
isConsentChecked,
|
||||
walletBackupConsentStorageProvider.observe().take(1)
|
||||
) { lockout, isConsentChecked, isConsentSaved ->
|
||||
WalletBackupInfoState(
|
||||
onBack = ::onBack,
|
||||
secondaryButton = ButtonState(
|
||||
secondaryButton =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_remind_me_in, stringRes(lockout.res)),
|
||||
onClick = ::onRemindMeLaterClick,
|
||||
isEnabled = isConsentChecked || isConsentSaved
|
||||
),
|
||||
checkboxState = CheckboxState(
|
||||
checkboxState =
|
||||
CheckboxState(
|
||||
isChecked = isConsentChecked,
|
||||
onClick = ::onConsentClick,
|
||||
text = stringRes(R.string.home_info_backup_checkbox)
|
||||
).takeIf { !isConsentSaved },
|
||||
primaryButton = ButtonState(
|
||||
primaryButton =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = ::onPrimaryClick
|
||||
)
|
||||
)
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = null
|
||||
|
|
|
@ -62,7 +62,10 @@ fun CrashReportMessage(
|
|||
)
|
||||
}
|
||||
|
||||
class CrashReportMessageState(val onClick: () -> Unit, val onButtonClick: () -> Unit) : HomeMessageState
|
||||
class CrashReportMessageState(
|
||||
val onClick: () -> Unit,
|
||||
val onButtonClick: () -> Unit
|
||||
) : HomeMessageState
|
||||
|
||||
@PreviewScreens
|
||||
@Composable
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiBaseSettingsOptIn
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiInfoRow
|
||||
|
@ -20,7 +21,6 @@ import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
|||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiBaseSettingsOptIn
|
||||
|
||||
@Composable
|
||||
fun CrashReportOptInView(state: CrashReportOptInState) {
|
||||
|
@ -76,7 +76,8 @@ private fun Preview() =
|
|||
ZcashTheme {
|
||||
BlankSurface {
|
||||
CrashReportOptInView(
|
||||
state = CrashReportOptInState(
|
||||
state =
|
||||
CrashReportOptInState(
|
||||
onOptInClick = {},
|
||||
onBack = {},
|
||||
onOptOutClick = {},
|
||||
|
|
|
@ -10,7 +10,8 @@ class CrashReportOptInViewModel(
|
|||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val navigationRouter: NavigationRouter
|
||||
) : ViewModel() {
|
||||
val state: StateFlow<CrashReportOptInState> = MutableStateFlow(
|
||||
val state: StateFlow<CrashReportOptInState> =
|
||||
MutableStateFlow(
|
||||
CrashReportOptInState(
|
||||
onBack = ::dismissOptInExchangeRateUsd,
|
||||
onOptInClick = ::optInExchangeRateUsd,
|
||||
|
|
|
@ -6,7 +6,6 @@ import cash.z.ecc.android.sdk.model.Zatoshi
|
|||
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupAvailability
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldFundsData
|
||||
import co.electriccoin.zcash.ui.common.repository.ShieldFundsRepository
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSelectedWalletAccountUseCase
|
||||
|
@ -32,8 +31,8 @@ class ShieldFundsInfoViewModel(
|
|||
private val remindShieldFundsLater: RemindShieldFundsLaterUseCase,
|
||||
private val shieldFunds: ShieldFundsUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
private val lockoutDuration = shieldFundsRepository
|
||||
private val lockoutDuration =
|
||||
shieldFundsRepository
|
||||
.availability
|
||||
.filterIsInstance<ShieldFundsData.Available>()
|
||||
.take(1)
|
||||
|
@ -63,8 +62,7 @@ class ShieldFundsInfoViewModel(
|
|||
),
|
||||
transparentAmount = account?.transparent?.balance ?: Zatoshi(0)
|
||||
)
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = null
|
||||
|
@ -76,4 +74,3 @@ class ShieldFundsInfoViewModel(
|
|||
|
||||
private fun onShieldClick() = shieldFunds(closeCurrentScreen = true)
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ fun MainActivity.OnboardingNavigation() {
|
|||
val flexaViewModel = koinViewModel<FlexaViewModel>()
|
||||
val messageAvailabilityDataSource = koinInject<MessageAvailabilityDataSource>()
|
||||
|
||||
|
||||
val navigator: Navigator =
|
||||
remember(
|
||||
navController,
|
||||
|
|
|
@ -17,4 +17,6 @@ fun AndroidRestoreBDDate(args: RestoreBDDate) {
|
|||
}
|
||||
|
||||
@Serializable
|
||||
data class RestoreBDDate(val seed: String)
|
||||
data class RestoreBDDate(
|
||||
val seed: String
|
||||
)
|
||||
|
|
|
@ -31,14 +31,14 @@ class RestoreBDDateViewModel(
|
|||
private val navigationRouter: NavigationRouter,
|
||||
private val context: Context,
|
||||
) : ViewModel() {
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private val selection = MutableStateFlow<YearMonth>(YearMonth.of(2018, 10))
|
||||
|
||||
val state: StateFlow<RestoreBDDateState?> = selection
|
||||
val state: StateFlow<RestoreBDDateState?> =
|
||||
selection
|
||||
.map {
|
||||
createState(it)
|
||||
}
|
||||
.stateIn(
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = null
|
||||
|
@ -59,12 +59,15 @@ class RestoreBDDateViewModel(
|
|||
|
||||
private fun onEstimateClick() {
|
||||
viewModelScope.launch {
|
||||
val instant = selection.value.atDay(1)
|
||||
val instant =
|
||||
selection.value
|
||||
.atDay(1)
|
||||
.atStartOfDay()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toInstant()
|
||||
.toKotlinInstant()
|
||||
val bday = SdkSynchronizer.estimateBirthdayHeight(
|
||||
val bday =
|
||||
SdkSynchronizer.estimateBirthdayHeight(
|
||||
context = context,
|
||||
date = instant,
|
||||
network = ZcashNetwork.fromResources(context)
|
||||
|
|
|
@ -75,8 +75,8 @@ import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
|||
import co.electriccoin.zcash.ui.design.util.scaffoldPadding
|
||||
import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
|
||||
import co.electriccoin.zcash.ui.fixture.ZashiMainTopAppBarStateFixture
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidget
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.send.SendTag
|
||||
import co.electriccoin.zcash.ui.screen.send.model.AmountState
|
||||
import co.electriccoin.zcash.ui.screen.send.model.MemoState
|
||||
|
@ -653,7 +653,8 @@ fun SendFormAmountTextField(
|
|||
)
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
innerModifier = ZashiTextFieldDefaults
|
||||
innerModifier =
|
||||
ZashiTextFieldDefaults
|
||||
.innerModifier
|
||||
.testTag(SendTag.SEND_AMOUNT_FIELD),
|
||||
error = amountError,
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.appbar.ZashiTopAppBarViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.appbar.ZashiTopAppBarViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -17,4 +17,6 @@ internal fun AndroidWalletBackup(args: WalletBackup) {
|
|||
}
|
||||
|
||||
@Serializable
|
||||
data class WalletBackup(val isOpenedFromSeedBackupInfo: Boolean)
|
||||
data class WalletBackup(
|
||||
val isOpenedFromSeedBackupInfo: Boolean
|
||||
)
|
||||
|
|
|
@ -291,7 +291,8 @@ private fun RevealedPreview() =
|
|||
isRevealed = true,
|
||||
tooltip = SeedSecretStateTooltip(title = stringRes(""), message = stringRes("")),
|
||||
) {},
|
||||
secondaryButton = ButtonState(
|
||||
secondaryButton =
|
||||
ButtonState(
|
||||
text = stringRes("Text"),
|
||||
icon = R.drawable.ic_seed_show,
|
||||
onClick = {},
|
||||
|
@ -331,7 +332,8 @@ private fun HiddenPreview() =
|
|||
isRevealed = false,
|
||||
tooltip = SeedSecretStateTooltip(title = stringRes(""), message = stringRes("")),
|
||||
) {},
|
||||
secondaryButton = ButtonState(
|
||||
secondaryButton =
|
||||
ButtonState(
|
||||
text = stringRes("Text"),
|
||||
icon = R.drawable.ic_seed_show,
|
||||
onClick = {},
|
||||
|
|
|
@ -34,8 +34,8 @@ class WalletBackupViewModel(
|
|||
private val onUserSavedWalletBackup: OnUserSavedWalletBackupUseCase,
|
||||
private val remindWalletBackupLater: RemindWalletBackupLaterUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
private val lockoutDuration = walletBackupDataSource
|
||||
private val lockoutDuration =
|
||||
walletBackupDataSource
|
||||
.observe()
|
||||
.filterIsInstance<WalletBackupAvailability.Available>()
|
||||
.take(1)
|
||||
|
@ -48,7 +48,8 @@ class WalletBackupViewModel(
|
|||
|
||||
private val isRevealed = MutableStateFlow(false)
|
||||
|
||||
private val isRemindMeLaterButtonVisible = isRevealed
|
||||
private val isRemindMeLaterButtonVisible =
|
||||
isRevealed
|
||||
.map { isRevealed ->
|
||||
isRevealed && args.isOpenedFromSeedBackupInfo
|
||||
}
|
||||
|
@ -63,8 +64,10 @@ class WalletBackupViewModel(
|
|||
lockoutDuration
|
||||
) { isRevealed, isRemindMeLaterButtonVisible, wallet, lockoutDuration ->
|
||||
WalletBackupState(
|
||||
secondaryButton = ButtonState(
|
||||
text = if (lockoutDuration != null) {
|
||||
secondaryButton =
|
||||
ButtonState(
|
||||
text =
|
||||
if (lockoutDuration != null) {
|
||||
stringRes(R.string.general_remind_me_in, stringRes(lockoutDuration.res))
|
||||
} else {
|
||||
stringRes(R.string.general_remind_me_later)
|
||||
|
@ -80,7 +83,8 @@ class WalletBackupViewModel(
|
|||
isRevealed -> stringRes(R.string.seed_recovery_hide_button)
|
||||
else -> stringRes(R.string.seed_recovery_reveal_button)
|
||||
},
|
||||
onClick = if (isRevealed && args.isOpenedFromSeedBackupInfo) {
|
||||
onClick =
|
||||
if (isRevealed && args.isOpenedFromSeedBackupInfo) {
|
||||
{ onWalletBackupSavedClick() }
|
||||
} else {
|
||||
{ onRevealClick() }
|
||||
|
@ -144,4 +148,3 @@ class WalletBackupViewModel(
|
|||
|
||||
private fun onBack() = navigationRouter.back()
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ import co.electriccoin.zcash.ui.screen.balances.BalanceTag
|
|||
import co.electriccoin.zcash.ui.screen.home.HomeTags
|
||||
import co.electriccoin.zcash.ui.screen.restore.height.RestoreBDHeightTags
|
||||
import co.electriccoin.zcash.ui.screen.restore.seed.RestoreSeedTag
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackup
|
||||
import co.electriccoin.zcash.ui.screen.send.SendTag
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackup
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
Loading…
Reference in New Issue