Extend shielding state (#1322)
- This adds `ShieldState.Shielded` that helps us keep the correct UI state of the Transparent funds widget after the user starts shielding action - This also brings little UI improvement in PrimaryButton sizing
This commit is contained in:
parent
8c027003cc
commit
b34d086cc0
|
@ -86,7 +86,7 @@ fun PrimaryButton(
|
||||||
horizontal = ZcashTheme.dimens.spacingNone,
|
horizontal = ZcashTheme.dimens.spacingNone,
|
||||||
vertical = ZcashTheme.dimens.spacingSmall
|
vertical = ZcashTheme.dimens.spacingSmall
|
||||||
),
|
),
|
||||||
contentPaddingValues: PaddingValues = PaddingValues(all = 15.dp)
|
contentPaddingValues: PaddingValues = PaddingValues(all = 15.5.dp)
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
shape = RectangleShape,
|
shape = RectangleShape,
|
||||||
|
|
|
@ -8,12 +8,14 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cash.z.ecc.android.sdk.SdkSynchronizer
|
import cash.z.ecc.android.sdk.SdkSynchronizer
|
||||||
import cash.z.ecc.android.sdk.Synchronizer
|
import cash.z.ecc.android.sdk.Synchronizer
|
||||||
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
|
import cash.z.ecc.android.sdk.model.UnifiedSpendingKey
|
||||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||||
import co.electriccoin.zcash.spackle.Twig
|
import co.electriccoin.zcash.spackle.Twig
|
||||||
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.CheckUpdateViewModel
|
||||||
|
@ -85,6 +87,8 @@ internal fun WrapBalances(
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
// To show information about the app update, if available
|
// To show information about the app update, if available
|
||||||
val isUpdateAvailable =
|
val isUpdateAvailable =
|
||||||
checkUpdateViewModel.updateInfo.collectAsStateWithLifecycle().value.let {
|
checkUpdateViewModel.updateInfo.collectAsStateWithLifecycle().value.let {
|
||||||
|
@ -94,15 +98,10 @@ internal fun WrapBalances(
|
||||||
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
||||||
|
|
||||||
val (shieldState, setShieldState) =
|
val (shieldState, setShieldState) =
|
||||||
rememberSaveable(stateSaver = ShieldState.Saver) {
|
rememberSaveable(stateSaver = ShieldState.Saver) { mutableStateOf(ShieldState.None) }
|
||||||
mutableStateOf(
|
|
||||||
if (walletSnapshot?.hasTransparentFunds == true) {
|
// Keep the state always up-to-date with the latest transparent balance
|
||||||
ShieldState.Available
|
setShieldState(updateTransparentBalanceState(shieldState, walletSnapshot))
|
||||||
} else {
|
|
||||||
ShieldState.None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val (isShowingErrorDialog, setShowErrorDialog) = rememberSaveable { mutableStateOf(false) }
|
val (isShowingErrorDialog, setShowErrorDialog) = rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
|
@ -145,10 +144,12 @@ internal fun WrapBalances(
|
||||||
transparentReceiver = null
|
transparentReceiver = null
|
||||||
)
|
)
|
||||||
}.onSuccess { newProposal ->
|
}.onSuccess { newProposal ->
|
||||||
Twig.debug { "Shielding proposal result: ${newProposal?.toPrettyString()}" }
|
Twig.info { "Shielding proposal result: ${newProposal?.toPrettyString()}" }
|
||||||
|
|
||||||
if (newProposal == null) {
|
if (newProposal == null) {
|
||||||
showShieldingError(null)
|
showShieldingError(
|
||||||
|
context.getString(R.string.balances_shielding_dialog_error_below_threshold)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val result =
|
val result =
|
||||||
createTransactionsViewModel.runCreateTransactions(
|
createTransactionsViewModel.runCreateTransactions(
|
||||||
|
@ -159,7 +160,7 @@ internal fun WrapBalances(
|
||||||
when (result) {
|
when (result) {
|
||||||
SubmitResult.Success -> {
|
SubmitResult.Success -> {
|
||||||
Twig.info { "Shielding transaction done successfully" }
|
Twig.info { "Shielding transaction done successfully" }
|
||||||
setShieldState(ShieldState.None)
|
setShieldState(ShieldState.Shielded)
|
||||||
// Triggering transaction history refresh to be notified about the newly created
|
// Triggering transaction history refresh to be notified about the newly created
|
||||||
// transaction asap
|
// transaction asap
|
||||||
(synchronizer as SdkSynchronizer).refreshTransactions()
|
(synchronizer as SdkSynchronizer).refreshTransactions()
|
||||||
|
@ -188,3 +189,21 @@ internal fun WrapBalances(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateTransparentBalanceState(
|
||||||
|
currentShieldState: ShieldState,
|
||||||
|
walletSnapshot: WalletSnapshot?
|
||||||
|
): ShieldState {
|
||||||
|
return when {
|
||||||
|
(walletSnapshot == null) -> {
|
||||||
|
currentShieldState
|
||||||
|
}
|
||||||
|
(
|
||||||
|
walletSnapshot.transparentBalance >= Zatoshi(DEFAULT_SHIELDING_THRESHOLD) &&
|
||||||
|
currentShieldState.isEnabled()
|
||||||
|
) -> ShieldState.Available
|
||||||
|
else -> {
|
||||||
|
currentShieldState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,12 +9,17 @@ sealed class ShieldState {
|
||||||
|
|
||||||
data object Running : ShieldState()
|
data object Running : ShieldState()
|
||||||
|
|
||||||
|
data object Shielded : ShieldState()
|
||||||
|
|
||||||
data class Failed(val error: String) : ShieldState()
|
data class Failed(val error: String) : ShieldState()
|
||||||
|
|
||||||
|
fun isEnabled() = this != Running && this !is Failed && this != Shielded
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TYPE_NONE = "none" // $NON-NLS
|
private const val TYPE_NONE = "none" // $NON-NLS
|
||||||
private const val TYPE_AVAILABLE = "available" // $NON-NLS
|
private const val TYPE_AVAILABLE = "available" // $NON-NLS
|
||||||
private const val TYPE_RUNNING = "running" // $NON-NLS
|
private const val TYPE_RUNNING = "running" // $NON-NLS
|
||||||
|
private const val TYPE_SHIELDED = "shielded" // $NON-NLS
|
||||||
private const val TYPE_FAILED = "failed" // $NON-NLS
|
private const val TYPE_FAILED = "failed" // $NON-NLS
|
||||||
private const val KEY_TYPE = "type" // $NON-NLS
|
private const val KEY_TYPE = "type" // $NON-NLS
|
||||||
|
|
||||||
|
@ -34,6 +39,7 @@ sealed class ShieldState {
|
||||||
TYPE_NONE -> None
|
TYPE_NONE -> None
|
||||||
TYPE_AVAILABLE -> Available
|
TYPE_AVAILABLE -> Available
|
||||||
TYPE_RUNNING -> Running
|
TYPE_RUNNING -> Running
|
||||||
|
TYPE_SHIELDED -> Shielded
|
||||||
TYPE_FAILED -> Failed((it[KEY_ERROR] as String))
|
TYPE_FAILED -> Failed((it[KEY_ERROR] as String))
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
@ -48,6 +54,7 @@ sealed class ShieldState {
|
||||||
None -> saverMap[KEY_TYPE] = TYPE_NONE
|
None -> saverMap[KEY_TYPE] = TYPE_NONE
|
||||||
Available -> saverMap[KEY_TYPE] = TYPE_AVAILABLE
|
Available -> saverMap[KEY_TYPE] = TYPE_AVAILABLE
|
||||||
Running -> saverMap[KEY_TYPE] = TYPE_RUNNING
|
Running -> saverMap[KEY_TYPE] = TYPE_RUNNING
|
||||||
|
Shielded -> saverMap[KEY_TYPE] = TYPE_SHIELDED
|
||||||
is Failed -> {
|
is Failed -> {
|
||||||
saverMap[KEY_TYPE] = TYPE_FAILED
|
saverMap[KEY_TYPE] = TYPE_FAILED
|
||||||
saverMap[KEY_ERROR] = this.error
|
saverMap[KEY_ERROR] = this.error
|
||||||
|
|
|
@ -33,4 +33,5 @@
|
||||||
<string name="balances_shielding_dialog_error_title">Failed to shield funds</string>
|
<string name="balances_shielding_dialog_error_title">Failed to shield funds</string>
|
||||||
<string name="balances_shielding_dialog_error_text">Error: The attempt to shield the transparent funds failed. Try it again, please.</string>
|
<string name="balances_shielding_dialog_error_text">Error: The attempt to shield the transparent funds failed. Try it again, please.</string>
|
||||||
<string name="balances_shielding_dialog_error_btn">OK</string>
|
<string name="balances_shielding_dialog_error_btn">OK</string>
|
||||||
|
<string name="balances_shielding_dialog_error_below_threshold">The current transparent balance is zero or below the allowed shielding limit.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue