parent
8b58233648
commit
809820c1f2
|
@ -1,13 +1,16 @@
|
||||||
package co.electriccoin.zcash.ui
|
package co.electriccoin.zcash.ui
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.NavOptionsBuilder
|
import androidx.navigation.NavOptionsBuilder
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
import cash.z.ecc.android.sdk.model.ZecSend
|
||||||
import co.electriccoin.zcash.ui.NavigationArguments.MULTIPLE_SUBMISSION_CLEAR_FORM
|
import co.electriccoin.zcash.ui.NavigationArguments.MULTIPLE_SUBMISSION_CLEAR_FORM
|
||||||
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_AMOUNT
|
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_AMOUNT
|
||||||
|
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_INITIAL_STAGE
|
||||||
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_MEMO
|
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_MEMO
|
||||||
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_PROPOSAL
|
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_PROPOSAL
|
||||||
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_RECIPIENT_ADDRESS
|
import co.electriccoin.zcash.ui.NavigationArguments.SEND_CONFIRM_RECIPIENT_ADDRESS
|
||||||
|
@ -42,6 +45,7 @@ import co.electriccoin.zcash.ui.screen.send.ext.toSerializableAddress
|
||||||
import co.electriccoin.zcash.ui.screen.send.model.SendArguments
|
import co.electriccoin.zcash.ui.screen.send.model.SendArguments
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.WrapSendConfirmation
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.WrapSendConfirmation
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationArguments
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationArguments
|
||||||
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage
|
||||||
import co.electriccoin.zcash.ui.screen.settings.WrapSettings
|
import co.electriccoin.zcash.ui.screen.settings.WrapSettings
|
||||||
import co.electriccoin.zcash.ui.screen.support.WrapSupport
|
import co.electriccoin.zcash.ui.screen.support.WrapSupport
|
||||||
import co.electriccoin.zcash.ui.screen.update.WrapCheckForUpdate
|
import co.electriccoin.zcash.ui.screen.update.WrapCheckForUpdate
|
||||||
|
@ -75,18 +79,19 @@ internal fun MainActivity.Navigation() {
|
||||||
},
|
},
|
||||||
goSendConfirmation = { zecSend ->
|
goSendConfirmation = { zecSend ->
|
||||||
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
|
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
|
||||||
handle[SEND_CONFIRM_RECIPIENT_ADDRESS] =
|
fillInHandleForConfirmation(handle, zecSend, SendConfirmationStage.Confirmation)
|
||||||
Json.encodeToString(
|
|
||||||
serializer = SerializableAddress.serializer(),
|
|
||||||
value = zecSend.destination.toSerializableAddress()
|
|
||||||
)
|
|
||||||
handle[SEND_CONFIRM_AMOUNT] = zecSend.amount.value
|
|
||||||
handle[SEND_CONFIRM_MEMO] = zecSend.memo.value
|
|
||||||
handle[SEND_CONFIRM_PROPOSAL] = zecSend.proposal?.toByteArray()
|
|
||||||
}
|
}
|
||||||
navController.navigateJustOnce(SEND_CONFIRMATION)
|
navController.navigateJustOnce(SEND_CONFIRMATION)
|
||||||
},
|
},
|
||||||
goSettings = { navController.navigateJustOnce(SETTINGS) },
|
goSettings = { navController.navigateJustOnce(SETTINGS) },
|
||||||
|
goMultiTrxSubmissionFailure = {
|
||||||
|
// Ultimately we could approach reworking the MultipleTrxFailure screen into a separate
|
||||||
|
// navigation endpoint
|
||||||
|
navController.currentBackStackEntry?.savedStateHandle?.let { handle ->
|
||||||
|
fillInHandleForConfirmation(handle, null, SendConfirmationStage.MultipleTrxFailure)
|
||||||
|
}
|
||||||
|
navController.navigateJustOnce(SEND_CONFIRMATION)
|
||||||
|
},
|
||||||
sendArguments =
|
sendArguments =
|
||||||
SendArguments(
|
SendArguments(
|
||||||
recipientAddress =
|
recipientAddress =
|
||||||
|
@ -195,21 +200,31 @@ internal fun MainActivity.Navigation() {
|
||||||
navController.popBackStackJustOnce(SEND_CONFIRMATION)
|
navController.popBackStackJustOnce(SEND_CONFIRMATION)
|
||||||
},
|
},
|
||||||
goHome = { navController.navigateJustOnce(HOME) },
|
goHome = { navController.navigateJustOnce(HOME) },
|
||||||
arguments =
|
arguments = SendConfirmationArguments.fromSavedStateHandle(backStackEntry.savedStateHandle)
|
||||||
SendConfirmationArguments.fromSavedStateHandle(backStackEntry.savedStateHandle).also {
|
|
||||||
// Remove SendConfirmation screen arguments passed from the Send screen if some exist
|
|
||||||
// after we use them
|
|
||||||
backStackEntry.savedStateHandle.remove<String>(SEND_CONFIRM_RECIPIENT_ADDRESS)
|
|
||||||
backStackEntry.savedStateHandle.remove<Long>(SEND_CONFIRM_AMOUNT)
|
|
||||||
backStackEntry.savedStateHandle.remove<String>(SEND_CONFIRM_MEMO)
|
|
||||||
backStackEntry.savedStateHandle.remove<ByteArray>(SEND_CONFIRM_PROPOSAL)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fillInHandleForConfirmation(
|
||||||
|
handle: SavedStateHandle,
|
||||||
|
zecSend: ZecSend?,
|
||||||
|
initialStage: SendConfirmationStage
|
||||||
|
) {
|
||||||
|
if (zecSend != null) {
|
||||||
|
handle[SEND_CONFIRM_RECIPIENT_ADDRESS] =
|
||||||
|
Json.encodeToString(
|
||||||
|
serializer = SerializableAddress.serializer(),
|
||||||
|
value = zecSend.destination.toSerializableAddress()
|
||||||
|
)
|
||||||
|
handle[SEND_CONFIRM_AMOUNT] = zecSend.amount.value
|
||||||
|
handle[SEND_CONFIRM_MEMO] = zecSend.memo.value
|
||||||
|
handle[SEND_CONFIRM_PROPOSAL] = zecSend.proposal?.toByteArray()
|
||||||
|
}
|
||||||
|
handle[SEND_CONFIRM_INITIAL_STAGE] = initialStage.toStringName()
|
||||||
|
}
|
||||||
|
|
||||||
private fun NavHostController.navigateJustOnce(
|
private fun NavHostController.navigateJustOnce(
|
||||||
route: String,
|
route: String,
|
||||||
navOptionsBuilder: (NavOptionsBuilder.() -> Unit)? = null
|
navOptionsBuilder: (NavOptionsBuilder.() -> Unit)? = null
|
||||||
|
@ -245,6 +260,7 @@ object NavigationArguments {
|
||||||
const val SEND_CONFIRM_AMOUNT = "send_confirm_amount"
|
const val SEND_CONFIRM_AMOUNT = "send_confirm_amount"
|
||||||
const val SEND_CONFIRM_MEMO = "send_confirm_memo"
|
const val SEND_CONFIRM_MEMO = "send_confirm_memo"
|
||||||
const val SEND_CONFIRM_PROPOSAL = "send_confirm_proposal"
|
const val SEND_CONFIRM_PROPOSAL = "send_confirm_proposal"
|
||||||
|
const val SEND_CONFIRM_INITIAL_STAGE = "send_confirm_initial_stage"
|
||||||
|
|
||||||
const val MULTIPLE_SUBMISSION_CLEAR_FORM = "multiple_submission_clear_form"
|
const val MULTIPLE_SUBMISSION_CLEAR_FORM = "multiple_submission_clear_form"
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ 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.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
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
|
||||||
|
@ -21,6 +22,8 @@ import co.electriccoin.zcash.ui.configuration.RemoteConfig
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
|
import co.electriccoin.zcash.ui.screen.balances.model.ShieldState
|
||||||
import co.electriccoin.zcash.ui.screen.balances.view.Balances
|
import co.electriccoin.zcash.ui.screen.balances.view.Balances
|
||||||
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
||||||
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.viewmodel.CreateTransactionsViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
import co.electriccoin.zcash.ui.screen.settings.viewmodel.SettingsViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
|
import co.electriccoin.zcash.ui.screen.update.AppUpdateCheckerImp
|
||||||
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
|
import co.electriccoin.zcash.ui.screen.update.model.UpdateState
|
||||||
|
@ -32,9 +35,12 @@ import org.jetbrains.annotations.VisibleForTesting
|
||||||
internal fun WrapBalances(
|
internal fun WrapBalances(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val createTransactionsViewModel by activity.viewModels<CreateTransactionsViewModel>()
|
||||||
|
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
val walletSnapshot = walletViewModel.walletSnapshot.collectAsStateWithLifecycle().value
|
||||||
|
@ -51,8 +57,10 @@ internal fun WrapBalances(
|
||||||
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
val settingsViewModel by activity.viewModels<SettingsViewModel>()
|
||||||
|
|
||||||
WrapBalances(
|
WrapBalances(
|
||||||
goSettings = goSettings,
|
|
||||||
checkUpdateViewModel = checkUpdateViewModel,
|
checkUpdateViewModel = checkUpdateViewModel,
|
||||||
|
createTransactionsViewModel = createTransactionsViewModel,
|
||||||
|
goSettings = goSettings,
|
||||||
|
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
||||||
spendingKey = spendingKey,
|
spendingKey = spendingKey,
|
||||||
settingsViewModel = settingsViewModel,
|
settingsViewModel = settingsViewModel,
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
|
@ -66,8 +74,10 @@ const val DEFAULT_SHIELDING_THRESHOLD = 100000L
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@Suppress("LongParameterList", "LongMethod")
|
@Suppress("LongParameterList", "LongMethod")
|
||||||
internal fun WrapBalances(
|
internal fun WrapBalances(
|
||||||
goSettings: () -> Unit,
|
|
||||||
checkUpdateViewModel: CheckUpdateViewModel,
|
checkUpdateViewModel: CheckUpdateViewModel,
|
||||||
|
createTransactionsViewModel: CreateTransactionsViewModel,
|
||||||
|
goSettings: () -> Unit,
|
||||||
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
settingsViewModel: SettingsViewModel,
|
settingsViewModel: SettingsViewModel,
|
||||||
spendingKey: UnifiedSpendingKey?,
|
spendingKey: UnifiedSpendingKey?,
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
|
@ -98,14 +108,14 @@ internal fun WrapBalances(
|
||||||
|
|
||||||
val (isShowingErrorDialog, setShowErrorDialog) = rememberSaveable { mutableStateOf(false) }
|
val (isShowingErrorDialog, setShowErrorDialog) = rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
suspend fun showShieldingError(error: Throwable?) {
|
suspend fun showShieldingError(errorMessage: String?) {
|
||||||
Twig.error { "Shielding proposal failed with: $error" }
|
Twig.error { "Shielding proposal failed with: $errorMessage" }
|
||||||
|
|
||||||
// Adding the extra delay before notifying UI for a better UX
|
// Adding the extra delay before notifying UI for a better UX
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
delay(1500)
|
delay(1500)
|
||||||
|
|
||||||
setShieldState(ShieldState.Failed(error?.message ?: ""))
|
setShieldState(ShieldState.Failed(errorMessage ?: ""))
|
||||||
setShowErrorDialog(true)
|
setShowErrorDialog(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,26 +153,35 @@ internal fun WrapBalances(
|
||||||
if (newProposal == null) {
|
if (newProposal == null) {
|
||||||
showShieldingError(null)
|
showShieldingError(null)
|
||||||
} else {
|
} else {
|
||||||
// TODO [#1294]: Add Send.Multiple-Trx-Failed screen
|
val result =
|
||||||
// TODO [#1294]: Note that the following processing is not entirely correct and will be
|
createTransactionsViewModel.runCreateTransactions(
|
||||||
// reworked
|
synchronizer = synchronizer,
|
||||||
// TODO [#1294]: https://github.com/Electric-Coin-Company/zashi-android/issues/1294
|
spendingKey = spendingKey,
|
||||||
runCatching {
|
proposal = newProposal
|
||||||
synchronizer.createProposedTransactions(
|
)
|
||||||
proposal = newProposal,
|
when (result) {
|
||||||
usk = spendingKey
|
SubmitResult.Success -> {
|
||||||
).collect {
|
Twig.info { "Shielding transaction done successfully" }
|
||||||
Twig.info { "Printing only for now. Will be reworked. Result: $it" }
|
setShieldState(ShieldState.None)
|
||||||
|
// Triggering transaction history refresh to be notified about the newly created
|
||||||
|
// transaction asap
|
||||||
|
(synchronizer as SdkSynchronizer).refreshTransactions()
|
||||||
|
|
||||||
|
// We could consider notifying UI with a change to emphasize the shielding action
|
||||||
|
// was successful, or we could switch the selected tab to Account
|
||||||
|
}
|
||||||
|
is SubmitResult.SimpleTrxFailure -> {
|
||||||
|
Twig.warn { "Shielding transaction failed" }
|
||||||
|
showShieldingError(result.errorDescription)
|
||||||
|
}
|
||||||
|
is SubmitResult.MultipleTrxFailure -> {
|
||||||
|
Twig.warn { "Shielding failed with multi-transactions-submission-error handling" }
|
||||||
|
goMultiTrxSubmissionFailure()
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
|
||||||
Twig.debug { "Shielding transaction event" }
|
|
||||||
setShieldState(ShieldState.None)
|
|
||||||
}.onFailure {
|
|
||||||
showShieldingError(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
showShieldingError(it)
|
showShieldingError(it.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,6 +29,7 @@ internal fun MainActivity.WrapHome(
|
||||||
onPageChange: (HomeScreenIndex) -> Unit,
|
onPageChange: (HomeScreenIndex) -> Unit,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
goScan: () -> Unit,
|
goScan: () -> Unit,
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
sendArguments: SendArguments
|
sendArguments: SendArguments
|
||||||
|
@ -40,6 +41,7 @@ internal fun MainActivity.WrapHome(
|
||||||
goScan = goScan,
|
goScan = goScan,
|
||||||
goSendConfirmation = goSendConfirmation,
|
goSendConfirmation = goSendConfirmation,
|
||||||
goSettings = goSettings,
|
goSettings = goSettings,
|
||||||
|
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure,
|
||||||
sendArguments = sendArguments
|
sendArguments = sendArguments
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -50,6 +52,7 @@ internal fun WrapHome(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit,
|
goBack: () -> Unit,
|
||||||
goSettings: () -> Unit,
|
goSettings: () -> Unit,
|
||||||
|
goMultiTrxSubmissionFailure: () -> Unit,
|
||||||
goScan: () -> Unit,
|
goScan: () -> Unit,
|
||||||
goSendConfirmation: (ZecSend) -> Unit,
|
goSendConfirmation: (ZecSend) -> Unit,
|
||||||
onPageChange: (HomeScreenIndex) -> Unit,
|
onPageChange: (HomeScreenIndex) -> Unit,
|
||||||
|
@ -127,7 +130,8 @@ internal fun WrapHome(
|
||||||
screenContent = {
|
screenContent = {
|
||||||
WrapBalances(
|
WrapBalances(
|
||||||
activity = activity,
|
activity = activity,
|
||||||
goSettings = goSettings
|
goSettings = goSettings,
|
||||||
|
goMultiTrxSubmissionFailure = goMultiTrxSubmissionFailure
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,7 +33,7 @@ import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationAr
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SendConfirmationStage
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.view.SendConfirmation
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.view.SendConfirmation
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.viewmodel.SendConfirmationViewModel
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.viewmodel.CreateTransactionsViewModel
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.SupportInfo
|
import co.electriccoin.zcash.ui.screen.support.model.SupportInfo
|
||||||
import co.electriccoin.zcash.ui.screen.support.model.SupportInfoType
|
import co.electriccoin.zcash.ui.screen.support.model.SupportInfoType
|
||||||
import co.electriccoin.zcash.ui.screen.support.viewmodel.SupportViewModel
|
import co.electriccoin.zcash.ui.screen.support.viewmodel.SupportViewModel
|
||||||
|
@ -50,7 +50,7 @@ internal fun MainActivity.WrapSendConfirmation(
|
||||||
) {
|
) {
|
||||||
val walletViewModel by viewModels<WalletViewModel>()
|
val walletViewModel by viewModels<WalletViewModel>()
|
||||||
|
|
||||||
val sendViewModel by viewModels<SendConfirmationViewModel>()
|
val createTransactionsViewModel by viewModels<CreateTransactionsViewModel>()
|
||||||
|
|
||||||
val viewModel by viewModels<SupportViewModel>()
|
val viewModel by viewModels<SupportViewModel>()
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ internal fun MainActivity.WrapSendConfirmation(
|
||||||
arguments = arguments,
|
arguments = arguments,
|
||||||
goBack = goBack,
|
goBack = goBack,
|
||||||
goHome = goHome,
|
goHome = goHome,
|
||||||
sendViewModel = sendViewModel,
|
createTransactionsViewModel = createTransactionsViewModel,
|
||||||
spendingKey = spendingKey,
|
spendingKey = spendingKey,
|
||||||
supportMessage = supportMessage,
|
supportMessage = supportMessage,
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
|
@ -80,7 +80,7 @@ internal fun WrapSendConfirmation(
|
||||||
arguments: SendConfirmationArguments,
|
arguments: SendConfirmationArguments,
|
||||||
goBack: (clearForm: Boolean) -> Unit,
|
goBack: (clearForm: Boolean) -> Unit,
|
||||||
goHome: () -> Unit,
|
goHome: () -> Unit,
|
||||||
sendViewModel: SendConfirmationViewModel,
|
createTransactionsViewModel: CreateTransactionsViewModel,
|
||||||
spendingKey: UnifiedSpendingKey?,
|
spendingKey: UnifiedSpendingKey?,
|
||||||
supportMessage: SupportInfo?,
|
supportMessage: SupportInfo?,
|
||||||
synchronizer: Synchronizer?,
|
synchronizer: Synchronizer?,
|
||||||
|
@ -89,17 +89,22 @@ internal fun WrapSendConfirmation(
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
val zecSend by rememberSaveable(stateSaver = ZecSend.Saver) { mutableStateOf(arguments.toZecSend()) }
|
val zecSend by rememberSaveable(stateSaver = ZecSend.Saver) {
|
||||||
|
mutableStateOf(
|
||||||
// Because of the [zecSend] has the same Saver as on the Send screen, we do not expect this to be ever null
|
if (arguments.hasValidZecSend()) {
|
||||||
checkNotNull(zecSend)
|
arguments.toZecSend()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val (stage, setStage) =
|
val (stage, setStage) =
|
||||||
rememberSaveable(stateSaver = SendConfirmationStage.Saver) {
|
rememberSaveable(stateSaver = SendConfirmationStage.Saver) {
|
||||||
mutableStateOf(SendConfirmationStage.Confirmation)
|
mutableStateOf(arguments.initialStage ?: SendConfirmationStage.Confirmation)
|
||||||
}
|
}
|
||||||
|
|
||||||
val submissionResults = sendViewModel.submissions.collectAsState().value.toImmutableList()
|
val submissionResults = createTransactionsViewModel.submissions.collectAsState().value.toImmutableList()
|
||||||
|
|
||||||
val onBackAction = {
|
val onBackAction = {
|
||||||
when (stage) {
|
when (stage) {
|
||||||
|
@ -124,7 +129,7 @@ internal fun WrapSendConfirmation(
|
||||||
SendConfirmation(
|
SendConfirmation(
|
||||||
stage = stage,
|
stage = stage,
|
||||||
onStageChange = setStage,
|
onStageChange = setStage,
|
||||||
zecSend = zecSend!!,
|
zecSend = zecSend,
|
||||||
submissionResults = submissionResults,
|
submissionResults = submissionResults,
|
||||||
snackbarHostState = snackbarHostState,
|
snackbarHostState = snackbarHostState,
|
||||||
onBack = onBackAction,
|
onBack = onBackAction,
|
||||||
|
@ -167,7 +172,7 @@ internal fun WrapSendConfirmation(
|
||||||
checkNotNull(newZecSend.proposal)
|
checkNotNull(newZecSend.proposal)
|
||||||
|
|
||||||
val result =
|
val result =
|
||||||
sendViewModel.runSending(
|
createTransactionsViewModel.runCreateTransactions(
|
||||||
synchronizer = synchronizer,
|
synchronizer = synchronizer,
|
||||||
spendingKey = spendingKey,
|
spendingKey = spendingKey,
|
||||||
proposal = newZecSend.proposal!!
|
proposal = newZecSend.proposal!!
|
||||||
|
|
|
@ -14,6 +14,7 @@ data class SendConfirmationArguments(
|
||||||
val amount: Long?,
|
val amount: Long?,
|
||||||
val memo: String?,
|
val memo: String?,
|
||||||
val proposal: ByteArray?,
|
val proposal: ByteArray?,
|
||||||
|
val initialStage: SendConfirmationStage?,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
internal fun fromSavedStateHandle(savedStateHandle: SavedStateHandle) =
|
internal fun fromSavedStateHandle(savedStateHandle: SavedStateHandle) =
|
||||||
|
@ -25,9 +26,23 @@ data class SendConfirmationArguments(
|
||||||
amount = savedStateHandle.get<Long>(NavigationArguments.SEND_CONFIRM_AMOUNT),
|
amount = savedStateHandle.get<Long>(NavigationArguments.SEND_CONFIRM_AMOUNT),
|
||||||
memo = savedStateHandle.get<String>(NavigationArguments.SEND_CONFIRM_MEMO),
|
memo = savedStateHandle.get<String>(NavigationArguments.SEND_CONFIRM_MEMO),
|
||||||
proposal = savedStateHandle.get<ByteArray>(NavigationArguments.SEND_CONFIRM_PROPOSAL),
|
proposal = savedStateHandle.get<ByteArray>(NavigationArguments.SEND_CONFIRM_PROPOSAL),
|
||||||
)
|
initialStage =
|
||||||
|
SendConfirmationStage
|
||||||
|
.fromStringName(savedStateHandle.get<String>(NavigationArguments.SEND_CONFIRM_INITIAL_STAGE))
|
||||||
|
).also {
|
||||||
|
// Remove SendConfirmation screen arguments passed from the other screens if some exist
|
||||||
|
savedStateHandle.remove<String>(NavigationArguments.SEND_CONFIRM_RECIPIENT_ADDRESS)
|
||||||
|
savedStateHandle.remove<Long>(NavigationArguments.SEND_CONFIRM_AMOUNT)
|
||||||
|
savedStateHandle.remove<String>(NavigationArguments.SEND_CONFIRM_MEMO)
|
||||||
|
savedStateHandle.remove<ByteArray>(NavigationArguments.SEND_CONFIRM_PROPOSAL)
|
||||||
|
savedStateHandle.remove<String>(NavigationArguments.SEND_CONFIRM_INITIAL_STAGE)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun hasValidZecSend() =
|
||||||
|
this.address != null &&
|
||||||
|
this.amount != null
|
||||||
|
|
||||||
internal fun toZecSend() =
|
internal fun toZecSend() =
|
||||||
ZecSend(
|
ZecSend(
|
||||||
destination = address?.toWalletAddress() ?: error("Address null"),
|
destination = address?.toWalletAddress() ?: error("Address null"),
|
||||||
|
|
|
@ -7,12 +7,22 @@ sealed class SendConfirmationStage {
|
||||||
|
|
||||||
data object Sending : SendConfirmationStage()
|
data object Sending : SendConfirmationStage()
|
||||||
|
|
||||||
data class Failure(val error: String) : SendConfirmationStage()
|
data class Failure(val error: String?) : SendConfirmationStage()
|
||||||
|
|
||||||
data object MultipleTrxFailure : SendConfirmationStage()
|
data object MultipleTrxFailure : SendConfirmationStage()
|
||||||
|
|
||||||
data object MultipleTrxFailureReported : SendConfirmationStage()
|
data object MultipleTrxFailureReported : SendConfirmationStage()
|
||||||
|
|
||||||
|
fun toStringName(): String {
|
||||||
|
return when (this) {
|
||||||
|
Confirmation -> TYPE_CONFIRMATION
|
||||||
|
is Failure -> TYPE_FAILURE
|
||||||
|
MultipleTrxFailure -> TYPE_MULTIPLE_TRX_FAILURE
|
||||||
|
MultipleTrxFailureReported -> TYPE_MULTIPLE_TRX_FAILURE_REPORTED
|
||||||
|
Sending -> TYPE_SENDING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TYPE_CONFIRMATION = "confirmation" // $NON-NLS
|
private const val TYPE_CONFIRMATION = "confirmation" // $NON-NLS
|
||||||
private const val TYPE_SENDING = "sending" // $NON-NLS
|
private const val TYPE_SENDING = "sending" // $NON-NLS
|
||||||
|
@ -52,7 +62,7 @@ sealed class SendConfirmationStage {
|
||||||
Sending -> saverMap[KEY_TYPE] = TYPE_SENDING
|
Sending -> saverMap[KEY_TYPE] = TYPE_SENDING
|
||||||
is Failure -> {
|
is Failure -> {
|
||||||
saverMap[KEY_TYPE] = TYPE_FAILURE
|
saverMap[KEY_TYPE] = TYPE_FAILURE
|
||||||
saverMap[KEY_ERROR] = this.error
|
saverMap[KEY_ERROR] = this.error ?: ""
|
||||||
}
|
}
|
||||||
is MultipleTrxFailure -> saverMap[KEY_TYPE] = TYPE_MULTIPLE_TRX_FAILURE
|
is MultipleTrxFailure -> saverMap[KEY_TYPE] = TYPE_MULTIPLE_TRX_FAILURE
|
||||||
is MultipleTrxFailureReported -> saverMap[KEY_TYPE] = TYPE_MULTIPLE_TRX_FAILURE_REPORTED
|
is MultipleTrxFailureReported -> saverMap[KEY_TYPE] = TYPE_MULTIPLE_TRX_FAILURE_REPORTED
|
||||||
|
@ -60,5 +70,17 @@ sealed class SendConfirmationStage {
|
||||||
|
|
||||||
return saverMap
|
return saverMap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fromStringName(stringName: String?): SendConfirmationStage {
|
||||||
|
return when (stringName) {
|
||||||
|
TYPE_CONFIRMATION -> Confirmation
|
||||||
|
TYPE_SENDING -> Sending
|
||||||
|
// Add the String error parameter storing and retrieving
|
||||||
|
TYPE_FAILURE -> Failure(null)
|
||||||
|
TYPE_MULTIPLE_TRX_FAILURE -> MultipleTrxFailure
|
||||||
|
TYPE_MULTIPLE_TRX_FAILURE_REPORTED -> MultipleTrxFailureReported
|
||||||
|
else -> Confirmation
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ fun SendConfirmation(
|
||||||
snackbarHostState: SnackbarHostState,
|
snackbarHostState: SnackbarHostState,
|
||||||
stage: SendConfirmationStage,
|
stage: SendConfirmationStage,
|
||||||
submissionResults: ImmutableList<TransactionSubmitResult>,
|
submissionResults: ImmutableList<TransactionSubmitResult>,
|
||||||
zecSend: ZecSend,
|
zecSend: ZecSend?,
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { SendConfirmationTopAppBar(onBack, stage) },
|
topBar = { SendConfirmationTopAppBar(onBack, stage) },
|
||||||
|
@ -197,11 +197,14 @@ private fun SendConfirmationMainContent(
|
||||||
onStageChange: (SendConfirmationStage) -> Unit,
|
onStageChange: (SendConfirmationStage) -> Unit,
|
||||||
stage: SendConfirmationStage,
|
stage: SendConfirmationStage,
|
||||||
submissionResults: ImmutableList<TransactionSubmitResult>,
|
submissionResults: ImmutableList<TransactionSubmitResult>,
|
||||||
zecSend: ZecSend,
|
zecSend: ZecSend?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
when (stage) {
|
when (stage) {
|
||||||
SendConfirmationStage.Confirmation, SendConfirmationStage.Sending, is SendConfirmationStage.Failure -> {
|
SendConfirmationStage.Confirmation, SendConfirmationStage.Sending, is SendConfirmationStage.Failure -> {
|
||||||
|
if (zecSend == null) {
|
||||||
|
error("Unexpected ZecSend value: $zecSend")
|
||||||
|
}
|
||||||
SendConfirmationContent(
|
SendConfirmationContent(
|
||||||
zecSend = zecSend,
|
zecSend = zecSend,
|
||||||
onBack = onBack,
|
onBack = onBack,
|
||||||
|
@ -371,7 +374,7 @@ fun SendConfirmationActionButtons(
|
||||||
@Suppress("UNUSED_PARAMETER")
|
@Suppress("UNUSED_PARAMETER")
|
||||||
private fun SendFailure(
|
private fun SendFailure(
|
||||||
onDone: () -> Unit,
|
onDone: () -> Unit,
|
||||||
reason: String,
|
reason: String?,
|
||||||
) {
|
) {
|
||||||
// Once we ensure that the [reason] contains a localized message, we can leverage it for the UI prompt
|
// Once we ensure that the [reason] contains a localized message, we can leverage it for the UI prompt
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ import co.electriccoin.zcash.spackle.Twig
|
||||||
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
import co.electriccoin.zcash.ui.screen.sendconfirmation.model.SubmitResult
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
class SendConfirmationViewModel(application: Application) : AndroidViewModel(application) {
|
class CreateTransactionsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
// Technically this value will not survive process dead, but will survive all possible configuration changes
|
// Technically this value will not survive process dead, but will survive all possible configuration changes
|
||||||
// Possible solution would be storing the value within [SavedStateHandle]
|
// Possible solution would be storing the value within [SavedStateHandle]
|
||||||
val submissions: MutableStateFlow<List<TransactionSubmitResult>> = MutableStateFlow(emptyList())
|
val submissions: MutableStateFlow<List<TransactionSubmitResult>> = MutableStateFlow(emptyList())
|
||||||
|
|
||||||
suspend fun runSending(
|
suspend fun runCreateTransactions(
|
||||||
synchronizer: Synchronizer,
|
synchronizer: Synchronizer,
|
||||||
spendingKey: UnifiedSpendingKey,
|
spendingKey: UnifiedSpendingKey,
|
||||||
proposal: Proposal
|
proposal: Proposal
|
Loading…
Reference in New Issue