[#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:
Honza Rychnovský 2024-01-26 13:59:23 +01:00 committed by GitHub
parent 7e27bdddff
commit b68d93b137
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 19 deletions

View File

@ -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
balance as well.
- 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

View File

@ -71,7 +71,7 @@ class SendViewTestSetup(
@Suppress("TestFunctionName")
fun DefaultContent() {
val (sendStage, setSendStage) =
rememberSaveable { mutableStateOf(initialState) }
rememberSaveable(stateSaver = SendStage.Saver) { mutableStateOf(initialState) }
lastSendStage = sendStage
@ -81,7 +81,7 @@ class SendViewTestSetup(
SendStage.Form -> {}
SendStage.Confirmation -> setSendStage(SendStage.Form)
SendStage.Sending -> {}
SendStage.SendFailure -> setSendStage(SendStage.Form)
is SendStage.SendFailure -> setSendStage(SendStage.Form)
SendStage.SendSuccessful -> {}
}
}

View File

@ -83,7 +83,7 @@ class SendViewAndroidTest : UiTestPrerequisites() {
fun back_on_send_failure_with_system_navigation() {
val testSetup =
newTestSetup(
SendStage.SendFailure,
SendStage.SendFailure("Test error message"),
runBlocking { ZecSendFixture.new() }
)

View File

@ -378,7 +378,7 @@ class SendViewTest : UiTestPrerequisites() {
fun back_on_send_failure() {
val testSetup =
newTestSetup(
SendStage.SendFailure,
SendStage.SendFailure("Test error message"),
runBlocking { ZecSendFixture.new() }
)
@ -396,7 +396,7 @@ class SendViewTest : UiTestPrerequisites() {
fun close_on_send_failure() {
val testSetup =
newTestSetup(
SendStage.SendFailure,
SendStage.SendFailure("Test error message"),
runBlocking { ZecSendFixture.new() }
)

View File

@ -80,7 +80,8 @@ internal fun WrapSend(
// 1. Use a different UI flow entirely
// 2. Show a pre-filled Send form
// 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) }
@ -89,7 +90,7 @@ internal fun WrapSend(
SendStage.Form -> goBack()
SendStage.Confirmation -> setSendStage(SendStage.Form)
SendStage.Sending -> { /* no action - wait until the sending is done */ }
SendStage.SendFailure -> setSendStage(SendStage.Form)
is SendStage.SendFailure -> setSendStage(SendStage.Form)
SendStage.SendSuccessful -> {
setZecSend(null)
setSendStage(SendStage.Form)
@ -127,7 +128,7 @@ internal fun WrapSend(
}
.onFailure {
Twig.debug { "Transaction submission failed with: $it." }
setSendStage(SendStage.SendFailure)
setSendStage(SendStage.SendFailure(it.localizedMessage ?: ""))
}
}
},

View File

@ -1,9 +1,64 @@
package co.electriccoin.zcash.ui.screen.send.model
enum class SendStage {
Form,
Confirmation,
Sending,
SendFailure,
SendSuccessful
import androidx.compose.runtime.saveable.mapSaver
sealed class SendStage {
data object Form : SendStage()
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
}
}
}

View File

@ -130,7 +130,8 @@ private fun PreviewSendFailure() {
amount = ZatoshiFixture.new(),
memo = MemoFixture.new()
),
onDone = {}
onDone = {},
reason = "Insufficient balance"
)
}
}
@ -262,7 +263,6 @@ private fun SendMainContent(
hasCameraFeature = hasCameraFeature,
modifier = modifier
)
// TestSend(modifier)
}
(sendStage == SendStage.Confirmation) -> {
SendConfirmation(
@ -287,9 +287,10 @@ private fun SendMainContent(
modifier = modifier,
)
}
(sendStage == SendStage.SendFailure) -> {
(sendStage is SendStage.SendFailure) -> {
SendFailure(
zecSend = zecSend,
reason = sendStage.error,
onDone = onBack,
modifier = modifier,
)
@ -681,7 +682,8 @@ private fun SendSuccessful(
private fun SendFailure(
zecSend: ZecSend,
onDone: () -> Unit,
modifier: Modifier = Modifier
reason: String,
modifier: Modifier = Modifier,
) {
Column(
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(
modifier =
Modifier

View File

@ -18,7 +18,10 @@
<string name="send_in_progress_wait">Please wait</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_successful_title">Sending successful</string>