[#1201] Enhance SendStage.SendFailure with error
* [#1201] Enhance SendStage.SendFailure with error - Closes #1201 - The changes also contain custom saver for SendStage - The error is printed on the SendFailure screen as a simple text for now - Changelog updated
This commit is contained in:
parent
7e27bdddff
commit
b68d93b137
|
@ -13,6 +13,8 @@ directly impact users rather than highlighting other key architectural updates.*
|
||||||
- The current balance UI on top of the Account screen has been reworked. It now displays the currently available
|
- The current balance UI on top of the Account screen has been reworked. It now displays the currently available
|
||||||
balance as well.
|
balance as well.
|
||||||
- The same current balance UI was also incorporated into the Send Form screen.
|
- The same current balance UI was also incorporated into the Send Form screen.
|
||||||
|
- The Send Error screen now contains a simple text with the reason for failure. The Send screen UI refactoring is
|
||||||
|
still in progress.
|
||||||
|
|
||||||
## [0.2.0 (530)] - 2024-01-16
|
## [0.2.0 (530)] - 2024-01-16
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ class SendViewTestSetup(
|
||||||
@Suppress("TestFunctionName")
|
@Suppress("TestFunctionName")
|
||||||
fun DefaultContent() {
|
fun DefaultContent() {
|
||||||
val (sendStage, setSendStage) =
|
val (sendStage, setSendStage) =
|
||||||
rememberSaveable { mutableStateOf(initialState) }
|
rememberSaveable(stateSaver = SendStage.Saver) { mutableStateOf(initialState) }
|
||||||
|
|
||||||
lastSendStage = sendStage
|
lastSendStage = sendStage
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class SendViewTestSetup(
|
||||||
SendStage.Form -> {}
|
SendStage.Form -> {}
|
||||||
SendStage.Confirmation -> setSendStage(SendStage.Form)
|
SendStage.Confirmation -> setSendStage(SendStage.Form)
|
||||||
SendStage.Sending -> {}
|
SendStage.Sending -> {}
|
||||||
SendStage.SendFailure -> setSendStage(SendStage.Form)
|
is SendStage.SendFailure -> setSendStage(SendStage.Form)
|
||||||
SendStage.SendSuccessful -> {}
|
SendStage.SendSuccessful -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ class SendViewAndroidTest : UiTestPrerequisites() {
|
||||||
fun back_on_send_failure_with_system_navigation() {
|
fun back_on_send_failure_with_system_navigation() {
|
||||||
val testSetup =
|
val testSetup =
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
SendStage.SendFailure,
|
SendStage.SendFailure("Test error message"),
|
||||||
runBlocking { ZecSendFixture.new() }
|
runBlocking { ZecSendFixture.new() }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -378,7 +378,7 @@ class SendViewTest : UiTestPrerequisites() {
|
||||||
fun back_on_send_failure() {
|
fun back_on_send_failure() {
|
||||||
val testSetup =
|
val testSetup =
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
SendStage.SendFailure,
|
SendStage.SendFailure("Test error message"),
|
||||||
runBlocking { ZecSendFixture.new() }
|
runBlocking { ZecSendFixture.new() }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ class SendViewTest : UiTestPrerequisites() {
|
||||||
fun close_on_send_failure() {
|
fun close_on_send_failure() {
|
||||||
val testSetup =
|
val testSetup =
|
||||||
newTestSetup(
|
newTestSetup(
|
||||||
SendStage.SendFailure,
|
SendStage.SendFailure("Test error message"),
|
||||||
runBlocking { ZecSendFixture.new() }
|
runBlocking { ZecSendFixture.new() }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,8 @@ internal fun WrapSend(
|
||||||
// 1. Use a different UI flow entirely
|
// 1. Use a different UI flow entirely
|
||||||
// 2. Show a pre-filled Send form
|
// 2. Show a pre-filled Send form
|
||||||
// 3. Go directly to the Confirmation screen
|
// 3. Go directly to the Confirmation screen
|
||||||
val (sendStage, setSendStage) = rememberSaveable { mutableStateOf(SendStage.Form) }
|
val (sendStage, setSendStage) =
|
||||||
|
rememberSaveable(stateSaver = SendStage.Saver) { mutableStateOf(SendStage.Form) }
|
||||||
|
|
||||||
val (zecSend, setZecSend) = rememberSaveable(stateSaver = ZecSend.Saver) { mutableStateOf(null) }
|
val (zecSend, setZecSend) = rememberSaveable(stateSaver = ZecSend.Saver) { mutableStateOf(null) }
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ internal fun WrapSend(
|
||||||
SendStage.Form -> goBack()
|
SendStage.Form -> goBack()
|
||||||
SendStage.Confirmation -> setSendStage(SendStage.Form)
|
SendStage.Confirmation -> setSendStage(SendStage.Form)
|
||||||
SendStage.Sending -> { /* no action - wait until the sending is done */ }
|
SendStage.Sending -> { /* no action - wait until the sending is done */ }
|
||||||
SendStage.SendFailure -> setSendStage(SendStage.Form)
|
is SendStage.SendFailure -> setSendStage(SendStage.Form)
|
||||||
SendStage.SendSuccessful -> {
|
SendStage.SendSuccessful -> {
|
||||||
setZecSend(null)
|
setZecSend(null)
|
||||||
setSendStage(SendStage.Form)
|
setSendStage(SendStage.Form)
|
||||||
|
@ -127,7 +128,7 @@ internal fun WrapSend(
|
||||||
}
|
}
|
||||||
.onFailure {
|
.onFailure {
|
||||||
Twig.debug { "Transaction submission failed with: $it." }
|
Twig.debug { "Transaction submission failed with: $it." }
|
||||||
setSendStage(SendStage.SendFailure)
|
setSendStage(SendStage.SendFailure(it.localizedMessage ?: ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,64 @@
|
||||||
package co.electriccoin.zcash.ui.screen.send.model
|
package co.electriccoin.zcash.ui.screen.send.model
|
||||||
|
|
||||||
enum class SendStage {
|
import androidx.compose.runtime.saveable.mapSaver
|
||||||
Form,
|
|
||||||
Confirmation,
|
sealed class SendStage {
|
||||||
Sending,
|
data object Form : SendStage()
|
||||||
SendFailure,
|
|
||||||
SendSuccessful
|
data object Confirmation : SendStage()
|
||||||
|
|
||||||
|
data object Sending : SendStage()
|
||||||
|
|
||||||
|
data class SendFailure(val error: String) : SendStage()
|
||||||
|
|
||||||
|
data object SendSuccessful : SendStage()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TYPE_FORM = "form" // $NON-NLS
|
||||||
|
private const val TYPE_CONFIRMATION = "confirmation" // $NON-NLS
|
||||||
|
private const val TYPE_SENDING = "sending" // $NON-NLS
|
||||||
|
private const val TYPE_FAILURE = "failure" // $NON-NLS
|
||||||
|
private const val TYPE_SUCCESSFUL = "successful" // $NON-NLS
|
||||||
|
private const val KEY_TYPE = "type" // $NON-NLS
|
||||||
|
private const val KEY_ERROR = "error" // $NON-NLS
|
||||||
|
|
||||||
|
internal val Saver
|
||||||
|
get() =
|
||||||
|
run {
|
||||||
|
mapSaver<SendStage>(
|
||||||
|
save = { it.toSaverMap() },
|
||||||
|
restore = {
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
val sendStageString = (it[KEY_TYPE] as String)
|
||||||
|
when (sendStageString) {
|
||||||
|
TYPE_FORM -> Form
|
||||||
|
TYPE_CONFIRMATION -> Confirmation
|
||||||
|
TYPE_SENDING -> Sending
|
||||||
|
TYPE_FAILURE -> SendFailure((it[KEY_ERROR] as String))
|
||||||
|
TYPE_SUCCESSFUL -> SendSuccessful
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SendStage.toSaverMap(): HashMap<String, String> {
|
||||||
|
val saverMap = HashMap<String, String>()
|
||||||
|
when (this) {
|
||||||
|
Form -> saverMap[KEY_TYPE] = TYPE_FORM
|
||||||
|
Confirmation -> saverMap[KEY_TYPE] = TYPE_CONFIRMATION
|
||||||
|
is SendFailure -> {
|
||||||
|
saverMap[KEY_TYPE] = TYPE_FAILURE
|
||||||
|
saverMap[KEY_ERROR] = this.error
|
||||||
|
}
|
||||||
|
SendSuccessful -> saverMap[KEY_TYPE] = TYPE_SUCCESSFUL
|
||||||
|
Sending -> saverMap[KEY_TYPE] = TYPE_SENDING
|
||||||
|
}
|
||||||
|
|
||||||
|
return saverMap
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,8 @@ private fun PreviewSendFailure() {
|
||||||
amount = ZatoshiFixture.new(),
|
amount = ZatoshiFixture.new(),
|
||||||
memo = MemoFixture.new()
|
memo = MemoFixture.new()
|
||||||
),
|
),
|
||||||
onDone = {}
|
onDone = {},
|
||||||
|
reason = "Insufficient balance"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +263,6 @@ private fun SendMainContent(
|
||||||
hasCameraFeature = hasCameraFeature,
|
hasCameraFeature = hasCameraFeature,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
// TestSend(modifier)
|
|
||||||
}
|
}
|
||||||
(sendStage == SendStage.Confirmation) -> {
|
(sendStage == SendStage.Confirmation) -> {
|
||||||
SendConfirmation(
|
SendConfirmation(
|
||||||
|
@ -287,9 +287,10 @@ private fun SendMainContent(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(sendStage == SendStage.SendFailure) -> {
|
(sendStage is SendStage.SendFailure) -> {
|
||||||
SendFailure(
|
SendFailure(
|
||||||
zecSend = zecSend,
|
zecSend = zecSend,
|
||||||
|
reason = sendStage.error,
|
||||||
onDone = onBack,
|
onDone = onBack,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
|
@ -681,7 +682,8 @@ private fun SendSuccessful(
|
||||||
private fun SendFailure(
|
private fun SendFailure(
|
||||||
zecSend: ZecSend,
|
zecSend: ZecSend,
|
||||||
onDone: () -> Unit,
|
onDone: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
reason: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
@ -709,6 +711,20 @@ private fun SendFailure(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Spacer(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(dimens.spacingDefault)
|
||||||
|
)
|
||||||
|
|
||||||
|
Body(
|
||||||
|
stringResource(
|
||||||
|
R.string.send_failure_reason,
|
||||||
|
reason,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(
|
Spacer(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
|
|
@ -18,7 +18,10 @@
|
||||||
<string name="send_in_progress_wait">Please wait</string>
|
<string name="send_in_progress_wait">Please wait</string>
|
||||||
|
|
||||||
<string name="send_failure_title">Sending failure</string>
|
<string name="send_failure_title">Sending failure</string>
|
||||||
<string name="send_failure_amount_address_memo" formatted="true">Sending failed for: <xliff:g id="amount" example="12.345">%1$s</xliff:g> ZEC to <xliff:g id="address" example="zs1g7cqw … mvyzgm">%2$s</xliff:g> with a memo: <xliff:g id="memo" example="for Veronika">%3$s</xliff:g></string>
|
<string name="send_failure_amount_address_memo" formatted="true">Sending failed for:\n<xliff:g id="amount"
|
||||||
|
example="12.345">%1$s</xliff:g> ZEC to <xliff:g id="address" example="zs1g7cqw … mvyzgm">%2$s</xliff:g> with a memo: <xliff:g id="memo" example="for Veronika">%3$s</xliff:g></string>
|
||||||
|
<string name="send_failure_reason" formatted="true">Sending failed with:\n<xliff:g
|
||||||
|
id="reason" example="Insufficient balance">%1$s</xliff:g></string>
|
||||||
<string name="send_failure_button">Back</string>
|
<string name="send_failure_button">Back</string>
|
||||||
|
|
||||||
<string name="send_successful_title">Sending successful</string>
|
<string name="send_successful_title">Sending successful</string>
|
||||||
|
|
Loading…
Reference in New Issue