Messages and balances hotfixes
This commit is contained in:
parent
0ea9c7ef51
commit
e80f583d54
|
@ -38,3 +38,7 @@ data class ZecAmountPair(
|
|||
val main: String,
|
||||
val suffix: String
|
||||
)
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
val Zatoshi.Companion.typicalFee: Zatoshi
|
||||
get() = Zatoshi(100000)
|
||||
|
|
|
@ -19,7 +19,6 @@ import co.electriccoin.zcash.ui.common.usecase.GetCoinbaseStatusUseCase
|
|||
import co.electriccoin.zcash.ui.common.usecase.GetConfigurationUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetContactByAddressUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentFilteredTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetExchangeRateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetFlexaStatusUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetHomeMessageUseCase
|
||||
|
@ -34,6 +33,7 @@ import co.electriccoin.zcash.ui.common.usecase.GetSynchronizerUseCase
|
|||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionDetailByIdUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionFiltersUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionMetadataUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransparentAddressUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletAccountsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
|
@ -142,7 +142,7 @@ val useCaseModule =
|
|||
factoryOf(::GetSelectedWalletAccountUseCase)
|
||||
singleOf(::ObserveClearSendUseCase)
|
||||
singleOf(::PrefillSendUseCase)
|
||||
factoryOf(::GetCurrentTransactionsUseCase)
|
||||
factoryOf(::GetTransactionsUseCase)
|
||||
factoryOf(::GetCurrentFilteredTransactionsUseCase) onClose ::closeableCallback
|
||||
factoryOf(::CreateProposalUseCase)
|
||||
factoryOf(::OnZip321ScannedUseCase)
|
||||
|
|
|
@ -9,7 +9,7 @@ import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.AddressBookViewMode
|
|||
import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.SelectRecipientViewModel
|
||||
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsViewModel
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidgetViewModel
|
||||
import co.electriccoin.zcash.ui.screen.balances.action.BalanceActionViewModel
|
||||
import co.electriccoin.zcash.ui.screen.balances.spendable.SpendableBalanceViewModel
|
||||
import co.electriccoin.zcash.ui.screen.chooseserver.ChooseServerViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.AddContactViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.UpdateContactViewModel
|
||||
|
@ -23,6 +23,7 @@ import co.electriccoin.zcash.ui.screen.home.HomeViewModel
|
|||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupDetailViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.reporting.CrashReportOptInViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.shieldfunds.ShieldFundsInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.integrations.IntegrationsViewModel
|
||||
import co.electriccoin.zcash.ui.screen.qrcode.viewmodel.QrCodeViewModel
|
||||
|
@ -156,6 +157,7 @@ val viewModelModule =
|
|||
viewModelOf(::ExchangeRateSettingsViewModel)
|
||||
viewModelOf(::WalletBackupDetailViewModel)
|
||||
viewModelOf(::ErrorViewModel)
|
||||
viewModelOf(::BalanceActionViewModel)
|
||||
viewModelOf(::SpendableBalanceViewModel)
|
||||
viewModelOf(::CrashReportOptInViewModel)
|
||||
viewModelOf(::WalletRestoringInfoViewModel)
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ import co.electriccoin.zcash.ui.screen.addressbook.WrapAddressBook
|
|||
import co.electriccoin.zcash.ui.screen.advancedsettings.WrapAdvancedSettings
|
||||
import co.electriccoin.zcash.ui.screen.authentication.AuthenticationUseCase
|
||||
import co.electriccoin.zcash.ui.screen.authentication.WrapAuthentication
|
||||
import co.electriccoin.zcash.ui.screen.balances.action.AndroidBalanceAction
|
||||
import co.electriccoin.zcash.ui.screen.balances.action.BalanceAction
|
||||
import co.electriccoin.zcash.ui.screen.balances.spendable.AndroidSpendableBalance
|
||||
import co.electriccoin.zcash.ui.screen.balances.spendable.SpendableBalance
|
||||
import co.electriccoin.zcash.ui.screen.chooseserver.WrapChooseServer
|
||||
import co.electriccoin.zcash.ui.screen.connectkeystone.AndroidConnectKeystone
|
||||
import co.electriccoin.zcash.ui.screen.connectkeystone.ConnectKeystone
|
||||
|
@ -497,14 +497,14 @@ internal fun MainActivity.Navigation() {
|
|||
) {
|
||||
AndroidErrorBottomSheet()
|
||||
}
|
||||
dialog<BalanceAction>(
|
||||
dialog<SpendableBalance>(
|
||||
dialogProperties =
|
||||
DialogProperties(
|
||||
dismissOnBackPress = false,
|
||||
dismissOnClickOutside = false
|
||||
)
|
||||
) {
|
||||
AndroidBalanceAction()
|
||||
AndroidSpendableBalance()
|
||||
}
|
||||
composable<CrashReportOptIn> {
|
||||
AndroidCrashReportOptIn()
|
||||
|
|
|
@ -57,6 +57,18 @@ sealed interface WalletAccount : Comparable<WalletAccount> {
|
|||
val isShieldingAvailable: Boolean
|
||||
get() = totalTransparentBalance > Zatoshi(100000L)
|
||||
|
||||
val isAllShielded: Boolean
|
||||
get() {
|
||||
val isAllShielded = totalBalance == spendableShieldedBalance
|
||||
val isAllShieldedWithTransparentDustLeft =
|
||||
totalBalance > spendableShieldedBalance &&
|
||||
spendableShieldedBalance == totalShieldedBalance &&
|
||||
totalTransparentBalance > Zatoshi(0) &&
|
||||
!isShieldingAvailable
|
||||
|
||||
return isAllShielded || isAllShieldedWithTransparentDustLeft
|
||||
}
|
||||
|
||||
fun canSpend(amount: Zatoshi): Boolean = spendableShieldedBalance >= amount
|
||||
}
|
||||
|
||||
|
|
|
@ -48,8 +48,7 @@ class SynchronizerProviderImpl(
|
|||
emit(synchronizer)
|
||||
}
|
||||
}
|
||||
}
|
||||
.flowOn(Dispatchers.IO)
|
||||
}.flowOn(Dispatchers.IO)
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.Lazily,
|
||||
|
|
|
@ -415,3 +415,6 @@ sealed interface ShieldTransaction : Transaction {
|
|||
override val overview: TransactionOverview,
|
||||
) : ShieldTransaction
|
||||
}
|
||||
|
||||
val Transaction.isPending: Boolean
|
||||
get() = this is SendTransaction.Pending || this is ShieldTransaction.Pending || this is ReceiveTransaction.Pending
|
||||
|
|
|
@ -15,12 +15,10 @@ import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
|||
import co.electriccoin.zcash.preference.StandardPreferenceProvider
|
||||
import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletSnapshotDataSource
|
||||
import co.electriccoin.zcash.ui.common.model.FastestServersState
|
||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletAccount
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||
import co.electriccoin.zcash.ui.common.provider.GetDefaultServersProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.PersistableWalletProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
|
@ -67,7 +65,6 @@ interface WalletRepository {
|
|||
|
||||
val allAccounts: Flow<List<WalletAccount>?>
|
||||
val currentAccount: Flow<WalletAccount?>
|
||||
val currentWalletSnapshot: StateFlow<WalletSnapshot?>
|
||||
|
||||
/**
|
||||
* A flow of the wallet block synchronization state.
|
||||
|
@ -105,7 +102,6 @@ class WalletRepositoryImpl(
|
|||
private val encryptedPreferenceProvider: EncryptedPreferenceProvider,
|
||||
private val restoreTimestampDataSource: RestoreTimestampDataSource,
|
||||
private val walletRestoringStateProvider: WalletRestoringStateProvider,
|
||||
private val walletSnapshotDataSource: WalletSnapshotDataSource,
|
||||
) : WalletRepository {
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
|
@ -185,8 +181,6 @@ class WalletRepositoryImpl(
|
|||
initialValue = FastestServersState(servers = emptyList(), isLoading = true)
|
||||
)
|
||||
|
||||
override val currentWalletSnapshot: StateFlow<WalletSnapshot?> = walletSnapshotDataSource.observe()
|
||||
|
||||
/**
|
||||
* A flow of the wallet block synchronization state.
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.flatMapLatest
|
|||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
|
||||
class GetCurrentTransactionsUseCase(
|
||||
class GetTransactionsUseCase(
|
||||
private val transactionRepository: TransactionRepository,
|
||||
private val metadataRepository: MetadataRepository,
|
||||
) {
|
|
@ -11,7 +11,7 @@ import co.electriccoin.zcash.ui.common.model.WalletAccount
|
|||
import co.electriccoin.zcash.ui.common.repository.ExchangeRateRepository
|
||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.balances.action.BalanceAction
|
||||
import co.electriccoin.zcash.ui.screen.balances.spendable.SpendableBalance
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
|
@ -50,13 +50,7 @@ class BalanceWidgetViewModel(
|
|||
when {
|
||||
!args.isBalanceButtonEnabled -> null
|
||||
account == null -> null
|
||||
account.totalBalance == account.spendableShieldedBalance -> null
|
||||
account.totalBalance > account.spendableShieldedBalance &&
|
||||
account.spendableShieldedBalance == account.totalShieldedBalance &&
|
||||
account.totalTransparentBalance > Zatoshi(0) &&
|
||||
!account.isShieldingAvailable ->
|
||||
null
|
||||
|
||||
account.isAllShielded -> null
|
||||
account.totalBalance > account.spendableShieldedBalance &&
|
||||
!account.isShieldedPending &&
|
||||
account.totalShieldedBalance > Zatoshi(0) &&
|
||||
|
@ -94,7 +88,7 @@ class BalanceWidgetViewModel(
|
|||
showDust = args.showDust
|
||||
)
|
||||
|
||||
private fun onBalanceButtonClick() = navigationRouter.forward(BalanceAction)
|
||||
private fun onBalanceButtonClick() = navigationRouter.forward(SpendableBalance)
|
||||
}
|
||||
|
||||
data class BalanceWidgetArgs(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.balances.action
|
||||
package co.electriccoin.zcash.ui.screen.balances.spendable
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -9,11 +9,11 @@ import org.koin.androidx.compose.koinViewModel
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AndroidBalanceAction() {
|
||||
val vm = koinViewModel<BalanceActionViewModel>()
|
||||
fun AndroidSpendableBalance() {
|
||||
val vm = koinViewModel<SpendableBalanceViewModel>()
|
||||
val state by vm.state.collectAsStateWithLifecycle()
|
||||
BalanceActionView(state)
|
||||
SpendableBalanceView(state)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data object BalanceAction
|
||||
data object SpendableBalance
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.balances.action
|
||||
package co.electriccoin.zcash.ui.screen.balances.spendable
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
|
@ -8,24 +8,24 @@ import co.electriccoin.zcash.ui.design.util.ImageResource
|
|||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
|
||||
@Immutable
|
||||
data class BalanceActionState(
|
||||
data class SpendableBalanceState(
|
||||
val title: StringResource,
|
||||
val message: StringResource,
|
||||
val rows: List<BalanceActionRowState>,
|
||||
val shieldButton: BalanceShieldButtonState?,
|
||||
val rows: List<SpendableBalanceRowState>,
|
||||
val shieldButton: SpendableBalanceShieldButtonState?,
|
||||
val positive: ButtonState,
|
||||
override val onBack: () -> Unit,
|
||||
) : ModalBottomSheetState
|
||||
|
||||
@Immutable
|
||||
data class BalanceActionRowState(
|
||||
data class SpendableBalanceRowState(
|
||||
val title: StringResource,
|
||||
val icon: ImageResource,
|
||||
val value: StringResource
|
||||
)
|
||||
|
||||
@Immutable
|
||||
data class BalanceShieldButtonState(
|
||||
data class SpendableBalanceShieldButtonState(
|
||||
val amount: Zatoshi,
|
||||
val onShieldClick: () -> Unit,
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.balances.action
|
||||
package co.electriccoin.zcash.ui.screen.balances.spendable
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -42,8 +42,8 @@ import co.electriccoin.zcash.ui.design.util.stringRes
|
|||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun BalanceActionView(
|
||||
state: BalanceActionState?,
|
||||
fun SpendableBalanceView(
|
||||
state: SpendableBalanceState?,
|
||||
sheetState: SheetState = rememberScreenModalBottomSheetState(),
|
||||
) {
|
||||
ZashiScreenModalBottomSheet(
|
||||
|
@ -56,7 +56,7 @@ fun BalanceActionView(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun BottomSheetContent(state: BalanceActionState, modifier: Modifier = Modifier) {
|
||||
fun BottomSheetContent(state: SpendableBalanceState, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier =
|
||||
modifier
|
||||
|
@ -97,7 +97,7 @@ fun BottomSheetContent(state: BalanceActionState, modifier: Modifier = Modifier)
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun BalanceActionRow(state: BalanceActionRowState) {
|
||||
private fun BalanceActionRow(state: SpendableBalanceRowState) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
|
@ -137,7 +137,7 @@ private fun BalanceActionRow(state: BalanceActionRowState) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun BalanceShieldButton(state: BalanceShieldButtonState) {
|
||||
private fun BalanceShieldButton(state: SpendableBalanceShieldButtonState) {
|
||||
ZashiCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentPadding =
|
||||
|
@ -193,9 +193,9 @@ private fun BalanceShieldButton(state: BalanceShieldButtonState) {
|
|||
@Composable
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
BalanceActionView(
|
||||
SpendableBalanceView(
|
||||
state =
|
||||
BalanceActionState(
|
||||
SpendableBalanceState(
|
||||
title = stringRes("Title"),
|
||||
message = stringRes("Subtitle"),
|
||||
positive =
|
||||
|
@ -205,19 +205,19 @@ private fun Preview() =
|
|||
onBack = {},
|
||||
rows =
|
||||
listOf(
|
||||
BalanceActionRowState(
|
||||
SpendableBalanceRowState(
|
||||
title = stringRes("Row"),
|
||||
icon = loadingImageRes(),
|
||||
value = stringRes("Value")
|
||||
),
|
||||
BalanceActionRowState(
|
||||
SpendableBalanceRowState(
|
||||
title = stringRes("Row"),
|
||||
icon = imageRes(R.drawable.ic_balance_shield),
|
||||
value = stringRes("Value")
|
||||
)
|
||||
),
|
||||
shieldButton =
|
||||
BalanceShieldButtonState(
|
||||
SpendableBalanceShieldButtonState(
|
||||
amount = Zatoshi(10000),
|
||||
onShieldClick = {}
|
||||
)
|
|
@ -1,12 +1,17 @@
|
|||
package co.electriccoin.zcash.ui.screen.balances.action
|
||||
package co.electriccoin.zcash.ui.screen.balances.spendable
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||
import cash.z.ecc.sdk.extension.typicalFee
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
||||
import co.electriccoin.zcash.ui.common.model.WalletAccount
|
||||
import co.electriccoin.zcash.ui.common.repository.isPending
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ListTransactionData
|
||||
import co.electriccoin.zcash.ui.common.usecase.ShieldFundsUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
|
@ -15,35 +20,41 @@ import co.electriccoin.zcash.ui.design.util.loadingImageRes
|
|||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class BalanceActionViewModel(
|
||||
class SpendableBalanceViewModel(
|
||||
accountDataSource: AccountDataSource,
|
||||
getTransactions: GetTransactionsUseCase,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val shieldFunds: ShieldFundsUseCase,
|
||||
) : ViewModel() {
|
||||
val state =
|
||||
accountDataSource.selectedAccount
|
||||
.mapNotNull {
|
||||
createState(it)
|
||||
}.stateIn(
|
||||
combine(
|
||||
accountDataSource.selectedAccount,
|
||||
getTransactions.observe()
|
||||
) { account, transactions ->
|
||||
createState(account, transactions)
|
||||
}.filterNotNull()
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue =
|
||||
createState(
|
||||
accountDataSource.allAccounts.value
|
||||
.orEmpty()
|
||||
.firstOrNull { it.isSelected }
|
||||
account =
|
||||
accountDataSource.allAccounts.value
|
||||
.orEmpty()
|
||||
.firstOrNull { it.isSelected },
|
||||
transactions = null
|
||||
)
|
||||
)
|
||||
|
||||
private fun createState(account: WalletAccount?): BalanceActionState? {
|
||||
private fun createState(account: WalletAccount?, transactions: List<ListTransactionData>?): SpendableBalanceState? {
|
||||
if (account == null) return null
|
||||
|
||||
return BalanceActionState(
|
||||
return SpendableBalanceState(
|
||||
title = stringRes(R.string.balance_action_title),
|
||||
message = createMessage(account),
|
||||
message = createMessage(account, transactions),
|
||||
positive = createPositiveButton(account),
|
||||
onBack = ::onBack,
|
||||
rows = createInfoRows(account),
|
||||
|
@ -51,19 +62,26 @@ class BalanceActionViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createMessage(account: WalletAccount): StringResource {
|
||||
private fun createMessage(account: WalletAccount, transactions: List<ListTransactionData>?): StringResource {
|
||||
val pending =
|
||||
when {
|
||||
account.totalShieldedBalance == account.spendableShieldedBalance ->
|
||||
stringRes(R.string.balance_action_all_shielded)
|
||||
account.isAllShielded -> stringRes(R.string.balance_action_all_shielded)
|
||||
|
||||
account.totalShieldedBalance > account.spendableShieldedBalance ->
|
||||
stringRes(R.string.balance_action_pending)
|
||||
account.totalBalance > account.spendableShieldedBalance ->
|
||||
if (transactions.orEmpty().any { it.transaction.isPending }) {
|
||||
stringRes(R.string.balance_action_pending)
|
||||
} else {
|
||||
stringRes(R.string.balance_action_syncing)
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
val shielding = stringRes(R.string.balance_action_shield_message).takeIf { account.isShieldingAvailable }
|
||||
val shielding =
|
||||
stringRes(
|
||||
R.string.balance_action_shield_message,
|
||||
stringRes(Zatoshi.typicalFee)
|
||||
).takeIf { account.isShieldingAvailable }
|
||||
|
||||
return if (pending != null && shielding != null) {
|
||||
pending + stringRes("\n\n") + shielding
|
||||
|
@ -85,21 +103,21 @@ class BalanceActionViewModel(
|
|||
|
||||
private fun createInfoRows(account: WalletAccount) =
|
||||
listOfNotNull(
|
||||
BalanceActionRowState(
|
||||
SpendableBalanceRowState(
|
||||
title = stringRes(R.string.balance_action_info_shielded),
|
||||
icon = imageRes(R.drawable.ic_balance_shield),
|
||||
value = stringRes(R.string.general_zec, stringRes(account.spendableShieldedBalance))
|
||||
),
|
||||
when {
|
||||
account.totalShieldedBalance > account.spendableShieldedBalance && account.isShieldedPending ->
|
||||
BalanceActionRowState(
|
||||
SpendableBalanceRowState(
|
||||
title = stringRes(R.string.balance_action_info_pending),
|
||||
icon = loadingImageRes(),
|
||||
value = stringRes(R.string.general_zec, stringRes(account.pendingShieldedBalance))
|
||||
)
|
||||
|
||||
account.totalShieldedBalance > account.spendableShieldedBalance ->
|
||||
BalanceActionRowState(
|
||||
SpendableBalanceRowState(
|
||||
title = stringRes(R.string.balance_action_info_pending),
|
||||
icon = loadingImageRes(),
|
||||
value =
|
||||
|
@ -113,8 +131,8 @@ class BalanceActionViewModel(
|
|||
},
|
||||
)
|
||||
|
||||
private fun createShieldButtonState(account: WalletAccount): BalanceShieldButtonState? =
|
||||
BalanceShieldButtonState(
|
||||
private fun createShieldButtonState(account: WalletAccount): SpendableBalanceShieldButtonState? =
|
||||
SpendableBalanceShieldButtonState(
|
||||
amount = account.transparent.balance,
|
||||
onShieldClick = ::onShieldClick
|
||||
).takeIf { account.isShieldingAvailable }
|
|
@ -7,11 +7,12 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.Spacer
|
||||
|
@ -24,28 +25,28 @@ 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.util.getValue
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.compose.koinInject
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AndroidWalletRestoringInfo() {
|
||||
val navigationRouter = koinInject<NavigationRouter>()
|
||||
Content(
|
||||
onBack = { navigationRouter.back() }
|
||||
)
|
||||
val viewModel = koinViewModel<WalletRestoringInfoViewModel>()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
Content(state)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun Content(
|
||||
onBack: () -> Unit,
|
||||
state: WalletRestoringInfoState,
|
||||
sheetState: SheetState = rememberScreenModalBottomSheetState(),
|
||||
) {
|
||||
ZashiScreenModalBottomSheet(
|
||||
sheetState = sheetState,
|
||||
onDismissRequest = onBack
|
||||
onDismissRequest = state.onBack
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
|
@ -70,17 +71,17 @@ private fun Content(
|
|||
stringResource(R.string.home_info_restoring_bullet_2),
|
||||
color = ZashiColors.Text.textTertiary
|
||||
)
|
||||
Spacer(32.dp)
|
||||
ZashiInfoText(
|
||||
stringResource(R.string.home_info_restoring_note),
|
||||
)
|
||||
state.info?.let {
|
||||
Spacer(32.dp)
|
||||
ZashiInfoText(it.getValue())
|
||||
}
|
||||
Spacer(24.dp)
|
||||
ZashiButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = onBack
|
||||
onClick = state.onBack
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -93,7 +94,11 @@ private fun Content(
|
|||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
Content(
|
||||
onBack = {},
|
||||
state =
|
||||
WalletRestoringInfoState(
|
||||
onBack = {},
|
||||
info = stringRes(R.string.home_info_restoring_message)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.restoring
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import co.electriccoin.zcash.ui.design.component.ModalBottomSheetState
|
||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||
|
||||
@Immutable
|
||||
data class WalletRestoringInfoState(
|
||||
val info: StringResource?,
|
||||
override val onBack: () -> Unit
|
||||
) : ModalBottomSheetState
|
|
@ -0,0 +1,37 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.restoring
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.WalletSnapshotDataSource
|
||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class WalletRestoringInfoViewModel(
|
||||
walletSnapshotDataSource: WalletSnapshotDataSource,
|
||||
private val navigationRouter: NavigationRouter
|
||||
) : ViewModel() {
|
||||
val state =
|
||||
walletSnapshotDataSource
|
||||
.observe()
|
||||
.map { createState(it) }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = createState(walletSnapshotDataSource.observe().value)
|
||||
)
|
||||
|
||||
private fun createState(snapshot: WalletSnapshot?) =
|
||||
WalletRestoringInfoState(
|
||||
onBack = ::onBack,
|
||||
info = stringRes(R.string.home_info_restoring_note).takeIf { snapshot?.isSpendable == false }
|
||||
)
|
||||
|
||||
private fun onBack() = navigationRouter.back()
|
||||
}
|
|
@ -17,6 +17,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.sdk.extension.typicalFee
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.Spacer
|
||||
|
@ -72,7 +73,10 @@ private fun Content(state: ShieldFundsInfoState) {
|
|||
)
|
||||
Spacer(24.dp)
|
||||
Text(
|
||||
stringResource(R.string.home_info_transparent_message),
|
||||
stringRes(
|
||||
R.string.home_info_transparent_message,
|
||||
stringRes(Zatoshi.typicalFee)
|
||||
).getValue(),
|
||||
color = ZashiColors.Text.textTertiary,
|
||||
style = ZashiTypography.textMd
|
||||
)
|
||||
|
|
|
@ -68,11 +68,12 @@ fun ReceiveShielded(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
TransactionDetailInfoRowState(
|
||||
title = if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
title =
|
||||
if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
message = state.completedTimestamp,
|
||||
shape =
|
||||
if (state.note != null) {
|
||||
|
|
|
@ -54,11 +54,12 @@ fun ReceiveTransparent(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
TransactionDetailInfoRowState(
|
||||
title = if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
title =
|
||||
if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
message = state.completedTimestamp,
|
||||
shape =
|
||||
if (state.note != null) {
|
||||
|
|
|
@ -118,11 +118,12 @@ fun SendShielded(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
TransactionDetailInfoRowState(
|
||||
title = if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
title =
|
||||
if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
message = state.completedTimestamp,
|
||||
shape =
|
||||
if (state.note == null) {
|
||||
|
|
|
@ -115,11 +115,12 @@ fun SendTransparent(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
TransactionDetailInfoRowState(
|
||||
title = if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
title =
|
||||
if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
message = state.completedTimestamp,
|
||||
shape =
|
||||
if (state.note != null) {
|
||||
|
|
|
@ -54,11 +54,12 @@ fun Shielding(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
TransactionDetailInfoRowState(
|
||||
title = if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
title =
|
||||
if (state.isPending) {
|
||||
stringRes(R.string.transaction_detail_info_transaction_status)
|
||||
} else {
|
||||
stringRes(R.string.transaction_detail_info_transaction_completed)
|
||||
},
|
||||
message = state.completedTimestamp,
|
||||
shape = TransactionDetailInfoShape.MIDDLE,
|
||||
)
|
||||
|
|
|
@ -10,7 +10,7 @@ import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
|||
import co.electriccoin.zcash.ui.common.mapper.TransactionHistoryMapper
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.repository.Transaction
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
@ -23,7 +23,7 @@ import kotlinx.coroutines.flow.combine
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class TransactionHistoryWidgetViewModel(
|
||||
getCurrentTransactions: GetCurrentTransactionsUseCase,
|
||||
getTransactions: GetTransactionsUseCase,
|
||||
getWalletRestoringState: GetWalletRestoringStateUseCase,
|
||||
private val transactionHistoryMapper: TransactionHistoryMapper,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
|
@ -31,7 +31,7 @@ class TransactionHistoryWidgetViewModel(
|
|||
) : ViewModel() {
|
||||
val state =
|
||||
combine(
|
||||
getCurrentTransactions.observe(),
|
||||
getTransactions.observe(),
|
||||
getWalletRestoringState.observe(),
|
||||
) { transactions, restoringState ->
|
||||
when {
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<string name="home_info_transparent_subtitle">To protect user privacy, Zashi doesn\'t support spending transparent
|
||||
ZEC. Tap the \"Shield\" button below to make your transparent funds spendable and your total Zashi balance private. </string>
|
||||
<string name="home_info_transparent_message">This will create a shielding in-wallet transaction, consolidating your
|
||||
transparent and shielded funds. (Typical fee: .001 ZEC)</string>
|
||||
transparent and shielded funds. (Typical fee: %s ZEC)</string>
|
||||
<string name="home_info_transparent_subheader">Transparent</string>
|
||||
<string name="home_info_disconnected_title">Wallet Disconnected</string>
|
||||
<string name="home_info_disconnected_subtitle">You appear to be offline. Please restore your internet connection
|
||||
|
@ -74,7 +74,8 @@
|
|||
<string name="balance_action_title">Spendable Balance</string>
|
||||
<string name="balance_action_all_shielded">All your funds are shielded and spendable.</string>
|
||||
<string name="balance_action_pending">Pending transactions are getting mined and confirmed.</string>
|
||||
<string name="balance_action_shield_message">Shield your transparent ZEC to make it spendable and private. Doing so will create a shielding in-wallet transaction, consolidating your transparent and shielded funds. (Typical fee: .001 ZEC)</string>
|
||||
<string name="balance_action_info_shielded">Shielded ZEC (Spendable)</string>
|
||||
<string name="balance_action_syncing">Zashi is scanning the blockchain to make sure your balances are displayed correctly.</string>
|
||||
<string name="balance_action_shield_message">Shield your transparent ZEC to make it spendable and private. Doing so will create a shielding in-wallet transaction, consolidating your transparent and shielded funds. (Typical fee: %s ZEC)</string>
|
||||
<string name="balance_action_info_shielded">Shielded (Spendable)</string>
|
||||
<string name="balance_action_info_pending">Pending</string>
|
||||
</resources>
|
|
@ -43,7 +43,7 @@
|
|||
<string name="home_info_transparent_subtitle">To protect user privacy, Zashi doesn\'t support spending transparent
|
||||
ZEC. Tap the \"Shield\" button below to make your transparent funds spendable and your total Zashi balance private. </string>
|
||||
<string name="home_info_transparent_message">This will create a shielding in-wallet transaction, consolidating your
|
||||
transparent and shielded funds. (Typical fee: .001 ZEC)</string>
|
||||
transparent and shielded funds. (Typical fee: %s ZEC)</string>
|
||||
<string name="home_info_transparent_subheader">Transparent</string>
|
||||
<string name="home_info_disconnected_title">Wallet Disconnected</string>
|
||||
<string name="home_info_disconnected_subtitle">You appear to be offline. Please restore your internet connection
|
||||
|
@ -74,7 +74,8 @@
|
|||
<string name="balance_action_title">Spendable Balance</string>
|
||||
<string name="balance_action_all_shielded">All your funds are shielded and spendable.</string>
|
||||
<string name="balance_action_pending">Pending transactions are getting mined and confirmed.</string>
|
||||
<string name="balance_action_shield_message">Shield your transparent ZEC to make it spendable and private. Doing so will create a shielding in-wallet transaction, consolidating your transparent and shielded funds. (Typical fee: .001 ZEC)</string>
|
||||
<string name="balance_action_info_shielded">Shielded ZEC (Spendable)</string>
|
||||
<string name="balance_action_syncing">Zashi is scanning the blockchain to make sure your balances are displayed correctly.</string>
|
||||
<string name="balance_action_shield_message">Shield your transparent ZEC to make it spendable and private. Doing so will create a shielding in-wallet transaction, consolidating your transparent and shielded funds. (Typical fee: %s ZEC)</string>
|
||||
<string name="balance_action_info_shielded">Shielded (Spendable)</string>
|
||||
<string name="balance_action_info_pending">Pending</string>
|
||||
</resources>
|
Loading…
Reference in New Issue