2023-10-04 07:01:40 -07:00
|
|
|
@file:Suppress("TooManyFunctions")
|
|
|
|
|
2022-03-08 11:05:03 -08:00
|
|
|
package co.electriccoin.zcash.ui.screen.send.view
|
2022-03-01 05:11:23 -08:00
|
|
|
|
|
|
|
import androidx.compose.foundation.layout.Column
|
2023-04-04 05:21:18 -07:00
|
|
|
import androidx.compose.foundation.layout.PaddingValues
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
2023-03-16 07:36:06 -07:00
|
|
|
import androidx.compose.foundation.layout.height
|
2022-06-09 09:31:44 -07:00
|
|
|
import androidx.compose.foundation.layout.padding
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.foundation.layout.size
|
2023-03-16 07:36:06 -07:00
|
|
|
import androidx.compose.foundation.rememberScrollState
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
2023-03-16 07:36:06 -07:00
|
|
|
import androidx.compose.foundation.verticalScroll
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.material.icons.Icons
|
2023-03-30 00:58:20 -07:00
|
|
|
import androidx.compose.material.icons.outlined.QrCodeScanner
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.material3.Icon
|
|
|
|
import androidx.compose.material3.IconButton
|
|
|
|
import androidx.compose.material3.Scaffold
|
|
|
|
import androidx.compose.material3.Text
|
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
import androidx.compose.runtime.getValue
|
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
|
|
import androidx.compose.runtime.setValue
|
2023-10-04 07:01:40 -07:00
|
|
|
import androidx.compose.ui.Alignment
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.ui.Modifier
|
2022-04-01 07:28:16 -07:00
|
|
|
import androidx.compose.ui.platform.LocalContext
|
2023-12-18 05:31:25 -08:00
|
|
|
import androidx.compose.ui.platform.testTag
|
|
|
|
import androidx.compose.ui.res.painterResource
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
import androidx.compose.ui.text.input.KeyboardType
|
2023-03-16 07:36:06 -07:00
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
2022-03-01 05:11:23 -08:00
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
2023-10-04 07:01:40 -07:00
|
|
|
import cash.z.ecc.android.sdk.fixture.WalletAddressFixture
|
2023-02-17 03:05:23 -08:00
|
|
|
import cash.z.ecc.android.sdk.model.Memo
|
|
|
|
import cash.z.ecc.android.sdk.model.MonetarySeparators
|
2022-06-23 04:31:16 -07:00
|
|
|
import cash.z.ecc.android.sdk.model.Zatoshi
|
2023-02-17 03:05:23 -08:00
|
|
|
import cash.z.ecc.android.sdk.model.ZecSend
|
|
|
|
import cash.z.ecc.android.sdk.model.ZecSendExt
|
|
|
|
import cash.z.ecc.android.sdk.model.ZecString
|
|
|
|
import cash.z.ecc.android.sdk.model.ZecStringExt
|
|
|
|
import cash.z.ecc.android.sdk.model.toZecString
|
2023-10-04 07:01:40 -07:00
|
|
|
import cash.z.ecc.sdk.fixture.MemoFixture
|
2022-03-01 05:11:23 -08:00
|
|
|
import cash.z.ecc.sdk.fixture.ZatoshiFixture
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.R
|
2023-12-18 05:31:25 -08:00
|
|
|
import co.electriccoin.zcash.ui.common.test.CommonTag
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
2023-03-16 07:36:06 -07:00
|
|
|
import co.electriccoin.zcash.ui.design.component.Body
|
|
|
|
import co.electriccoin.zcash.ui.design.component.FormTextField
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
2023-03-16 07:36:06 -07:00
|
|
|
import co.electriccoin.zcash.ui.design.component.Header
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
2023-12-18 05:31:25 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
2023-03-16 07:36:06 -07:00
|
|
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme.dimens
|
2023-12-18 05:31:25 -08:00
|
|
|
import co.electriccoin.zcash.ui.screen.send.SendTag
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.screen.send.ext.ABBREVIATION_INDEX
|
|
|
|
import co.electriccoin.zcash.ui.screen.send.ext.abbreviated
|
2023-03-26 23:25:36 -07:00
|
|
|
import co.electriccoin.zcash.ui.screen.send.ext.valueOrEmptyChar
|
2023-03-30 00:58:20 -07:00
|
|
|
import co.electriccoin.zcash.ui.screen.send.model.SendArgumentsWrapper
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.screen.send.model.SendStage
|
2023-10-04 07:01:40 -07:00
|
|
|
import kotlinx.coroutines.runBlocking
|
2022-03-01 05:11:23 -08:00
|
|
|
|
|
|
|
@Composable
|
2023-10-04 07:01:40 -07:00
|
|
|
@Preview("SendForm")
|
|
|
|
private fun PreviewSendForm() {
|
2023-10-19 06:00:47 -07:00
|
|
|
ZcashTheme(forceDarkMode = false) {
|
2022-03-01 05:11:23 -08:00
|
|
|
GradientSurface {
|
|
|
|
Send(
|
|
|
|
mySpendableBalance = ZatoshiFixture.new(),
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper = null,
|
2023-03-26 23:25:36 -07:00
|
|
|
sendStage = SendStage.Form,
|
|
|
|
onSendStageChange = {},
|
|
|
|
zecSend = null,
|
|
|
|
onZecSendChange = {},
|
|
|
|
onCreateAndSend = {},
|
2023-03-30 00:58:20 -07:00
|
|
|
onQrScannerOpen = {},
|
|
|
|
onBack = {},
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings = {},
|
2023-03-30 00:58:20 -07:00
|
|
|
hasCameraFeature = true
|
2022-03-01 05:11:23 -08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-04 07:01:40 -07:00
|
|
|
@Composable
|
|
|
|
@Preview("SendSuccessful")
|
|
|
|
private fun PreviewSendSuccessful() {
|
2023-10-19 06:00:47 -07:00
|
|
|
ZcashTheme(forceDarkMode = false) {
|
2023-10-04 07:01:40 -07:00
|
|
|
GradientSurface {
|
|
|
|
SendSuccessful(
|
2023-12-11 01:20:32 -08:00
|
|
|
zecSend =
|
|
|
|
ZecSend(
|
|
|
|
destination = runBlocking { WalletAddressFixture.sapling() },
|
|
|
|
amount = ZatoshiFixture.new(),
|
|
|
|
memo = MemoFixture.new()
|
|
|
|
),
|
2023-10-04 07:01:40 -07:00
|
|
|
onDone = {}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
@Preview("SendFailure")
|
|
|
|
private fun PreviewSendFailure() {
|
2023-10-19 06:00:47 -07:00
|
|
|
ZcashTheme(forceDarkMode = false) {
|
2023-10-04 07:01:40 -07:00
|
|
|
GradientSurface {
|
|
|
|
SendFailure(
|
2023-12-11 01:20:32 -08:00
|
|
|
zecSend =
|
|
|
|
ZecSend(
|
|
|
|
destination = runBlocking { WalletAddressFixture.sapling() },
|
|
|
|
amount = ZatoshiFixture.new(),
|
|
|
|
memo = MemoFixture.new()
|
|
|
|
),
|
2023-10-04 07:01:40 -07:00
|
|
|
onDone = {}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
@Preview("SendConfirmation")
|
|
|
|
private fun PreviewSendConfirmation() {
|
2023-10-19 06:00:47 -07:00
|
|
|
ZcashTheme(forceDarkMode = false) {
|
2023-10-04 07:01:40 -07:00
|
|
|
GradientSurface {
|
2023-12-18 05:31:25 -08:00
|
|
|
SendConfirmation(
|
2023-12-11 01:20:32 -08:00
|
|
|
zecSend =
|
|
|
|
ZecSend(
|
|
|
|
destination = runBlocking { WalletAddressFixture.sapling() },
|
|
|
|
amount = ZatoshiFixture.new(),
|
|
|
|
memo = MemoFixture.new()
|
|
|
|
),
|
2023-10-04 07:01:40 -07:00
|
|
|
onConfirmation = {}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-26 23:25:36 -07:00
|
|
|
@Suppress("LongParameterList")
|
2022-03-01 05:11:23 -08:00
|
|
|
@Composable
|
|
|
|
fun Send(
|
|
|
|
mySpendableBalance: Zatoshi,
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper: SendArgumentsWrapper?,
|
2023-03-26 23:25:36 -07:00
|
|
|
sendStage: SendStage,
|
|
|
|
onSendStageChange: (SendStage) -> Unit,
|
|
|
|
zecSend: ZecSend?,
|
|
|
|
onZecSendChange: (ZecSend) -> Unit,
|
|
|
|
onBack: () -> Unit,
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings: () -> Unit,
|
2023-03-30 00:58:20 -07:00
|
|
|
onCreateAndSend: (ZecSend) -> Unit,
|
|
|
|
onQrScannerOpen: () -> Unit,
|
|
|
|
hasCameraFeature: Boolean
|
2022-03-01 05:11:23 -08:00
|
|
|
) {
|
|
|
|
Scaffold(topBar = {
|
2023-03-26 23:25:36 -07:00
|
|
|
SendTopAppBar(
|
|
|
|
onBack = onBack,
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings = onSettings,
|
|
|
|
showBackNavigationButton = (sendStage != SendStage.Sending && sendStage != SendStage.Form)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
2022-06-09 09:31:44 -07:00
|
|
|
}) { paddingValues ->
|
2022-03-01 05:11:23 -08:00
|
|
|
SendMainContent(
|
2023-03-16 07:36:06 -07:00
|
|
|
myBalance = mySpendableBalance,
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper = sendArgumentsWrapper,
|
2023-03-26 23:25:36 -07:00
|
|
|
onBack = onBack,
|
2023-03-16 07:36:06 -07:00
|
|
|
sendStage = sendStage,
|
2023-03-26 23:25:36 -07:00
|
|
|
onSendStageChange = onSendStageChange,
|
|
|
|
zecSend = zecSend,
|
|
|
|
onZecSendChange = onZecSendChange,
|
|
|
|
onSendSubmit = onCreateAndSend,
|
2023-03-30 00:58:20 -07:00
|
|
|
onQrScannerOpen = onQrScannerOpen,
|
|
|
|
hasCameraFeature = hasCameraFeature,
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.verticalScroll(
|
|
|
|
rememberScrollState()
|
|
|
|
)
|
|
|
|
.padding(
|
|
|
|
top = paddingValues.calculateTopPadding() + dimens.spacingDefault,
|
|
|
|
bottom = paddingValues.calculateBottomPadding() + dimens.spacingHuge,
|
|
|
|
start = dimens.screenHorizontalSpacing,
|
|
|
|
end = dimens.screenHorizontalSpacing
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2023-03-26 23:25:36 -07:00
|
|
|
private fun SendTopAppBar(
|
|
|
|
onBack: () -> Unit,
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings: () -> Unit,
|
2023-03-26 23:25:36 -07:00
|
|
|
showBackNavigationButton: Boolean = true
|
|
|
|
) {
|
2023-12-18 05:31:25 -08:00
|
|
|
SmallTopAppBar(
|
|
|
|
titleText = stringResource(id = R.string.send_title),
|
|
|
|
onBack = onBack,
|
|
|
|
backText =
|
|
|
|
if (showBackNavigationButton) {
|
|
|
|
stringResource(id = R.string.send_back)
|
|
|
|
} else {
|
|
|
|
null
|
|
|
|
},
|
|
|
|
backContentDescriptionText = stringResource(id = R.string.send_back_content_description),
|
|
|
|
hamburgerMenuActions = {
|
|
|
|
IconButton(
|
|
|
|
onClick = onSettings,
|
|
|
|
modifier = Modifier.testTag(CommonTag.SETTINGS_TOP_BAR_BUTTON)
|
|
|
|
) {
|
|
|
|
Icon(
|
|
|
|
painter = painterResource(id = co.electriccoin.zcash.ui.design.R.drawable.hamburger_menu_icon),
|
|
|
|
contentDescription = stringResource(id = R.string.settings_menu_content_description)
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
2023-12-18 05:31:25 -08:00
|
|
|
}
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
|
|
|
|
2022-12-02 01:54:06 -08:00
|
|
|
@Suppress("LongParameterList")
|
2022-03-01 05:11:23 -08:00
|
|
|
@Composable
|
|
|
|
private fun SendMainContent(
|
|
|
|
myBalance: Zatoshi,
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper: SendArgumentsWrapper?,
|
2023-03-26 23:25:36 -07:00
|
|
|
zecSend: ZecSend?,
|
|
|
|
onZecSendChange: (ZecSend) -> Unit,
|
|
|
|
onBack: () -> Unit,
|
2022-03-01 05:11:23 -08:00
|
|
|
sendStage: SendStage,
|
2023-03-26 23:25:36 -07:00
|
|
|
onSendStageChange: (SendStage) -> Unit,
|
|
|
|
onSendSubmit: (ZecSend) -> Unit,
|
2023-03-30 00:58:20 -07:00
|
|
|
onQrScannerOpen: () -> Unit,
|
|
|
|
hasCameraFeature: Boolean,
|
2023-03-16 07:36:06 -07:00
|
|
|
modifier: Modifier = Modifier
|
2022-03-01 05:11:23 -08:00
|
|
|
) {
|
2023-03-26 23:25:36 -07:00
|
|
|
when {
|
|
|
|
(sendStage == SendStage.Form || null == zecSend) -> {
|
|
|
|
SendForm(
|
|
|
|
myBalance = myBalance,
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper = sendArgumentsWrapper,
|
2023-03-26 23:25:36 -07:00
|
|
|
previousZecSend = zecSend,
|
|
|
|
onCreateZecSend = {
|
|
|
|
onSendStageChange(SendStage.Confirmation)
|
|
|
|
onZecSendChange(it)
|
|
|
|
},
|
2023-03-30 00:58:20 -07:00
|
|
|
onQrScannerOpen = onQrScannerOpen,
|
|
|
|
hasCameraFeature = hasCameraFeature,
|
2023-03-26 23:25:36 -07:00
|
|
|
modifier = modifier
|
|
|
|
)
|
|
|
|
}
|
|
|
|
(sendStage == SendStage.Confirmation) -> {
|
2023-12-18 05:31:25 -08:00
|
|
|
SendConfirmation(
|
2023-03-26 23:25:36 -07:00
|
|
|
zecSend = zecSend,
|
|
|
|
onConfirmation = {
|
|
|
|
onSendStageChange(SendStage.Sending)
|
|
|
|
onSendSubmit(zecSend)
|
|
|
|
},
|
|
|
|
modifier = modifier
|
|
|
|
)
|
|
|
|
}
|
|
|
|
(sendStage == SendStage.Sending) -> {
|
|
|
|
Sending(
|
|
|
|
zecSend = zecSend,
|
|
|
|
modifier = modifier
|
|
|
|
)
|
|
|
|
}
|
|
|
|
(sendStage == SendStage.SendSuccessful) -> {
|
|
|
|
SendSuccessful(
|
|
|
|
zecSend = zecSend,
|
2023-11-23 02:37:02 -08:00
|
|
|
onDone = onBack,
|
2023-03-26 23:25:36 -07:00
|
|
|
modifier = modifier,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
(sendStage == SendStage.SendFailure) -> {
|
|
|
|
SendFailure(
|
|
|
|
zecSend = zecSend,
|
2023-11-23 02:37:02 -08:00
|
|
|
onDone = onBack,
|
2023-03-26 23:25:36 -07:00
|
|
|
modifier = modifier,
|
|
|
|
)
|
|
|
|
}
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO [#217]: Need to handle changing of Locale after user input, but before submitting the button.
|
2022-04-01 07:28:16 -07:00
|
|
|
// TODO [#288]: TextField component can't do long-press backspace.
|
|
|
|
// TODO [#294]: DetektAll failed LongMethod
|
2023-03-30 00:58:20 -07:00
|
|
|
@Suppress("LongMethod", "LongParameterList")
|
2022-03-01 05:11:23 -08:00
|
|
|
@Composable
|
|
|
|
private fun SendForm(
|
|
|
|
myBalance: Zatoshi,
|
2023-03-30 00:58:20 -07:00
|
|
|
sendArgumentsWrapper: SendArgumentsWrapper?,
|
2022-03-01 05:11:23 -08:00
|
|
|
previousZecSend: ZecSend?,
|
2023-03-26 23:25:36 -07:00
|
|
|
onCreateZecSend: (ZecSend) -> Unit,
|
2023-03-30 00:58:20 -07:00
|
|
|
onQrScannerOpen: () -> Unit,
|
|
|
|
hasCameraFeature: Boolean,
|
2023-03-16 07:36:06 -07:00
|
|
|
modifier: Modifier = Modifier
|
2022-03-01 05:11:23 -08:00
|
|
|
) {
|
2022-04-01 07:28:16 -07:00
|
|
|
val context = LocalContext.current
|
2022-03-01 05:11:23 -08:00
|
|
|
val monetarySeparators = MonetarySeparators.current()
|
|
|
|
val allowedCharacters = ZecString.allowedCharacters(monetarySeparators)
|
|
|
|
|
2023-03-16 07:36:06 -07:00
|
|
|
// TODO [#809]: Fix ZEC balance on Send screen
|
2023-11-23 01:00:13 -08:00
|
|
|
// TODO [#809]: https://github.com/Electric-Coin-Company/zashi-android/issues/809
|
2022-03-01 05:11:23 -08:00
|
|
|
var amountZecString by rememberSaveable {
|
|
|
|
mutableStateOf(previousZecSend?.amount?.toZecString() ?: "")
|
|
|
|
}
|
|
|
|
var recipientAddressString by rememberSaveable {
|
|
|
|
mutableStateOf(previousZecSend?.destination?.address ?: "")
|
|
|
|
}
|
|
|
|
var memoString by rememberSaveable { mutableStateOf(previousZecSend?.memo?.value ?: "") }
|
|
|
|
|
2022-04-08 05:33:08 -07:00
|
|
|
var validation by rememberSaveable {
|
|
|
|
mutableStateOf<Set<ZecSendExt.ZecSendValidation.Invalid.ValidationError>>(emptySet())
|
|
|
|
}
|
2022-03-01 05:11:23 -08:00
|
|
|
|
2023-04-04 05:21:18 -07:00
|
|
|
// TODO [#826]: SendArgumentsWrapper object properties validation
|
2023-11-23 01:00:13 -08:00
|
|
|
// TODO [#826]: https://github.com/Electric-Coin-Company/zashi-android/issues/826
|
2023-03-30 00:58:20 -07:00
|
|
|
if (sendArgumentsWrapper?.recipientAddress != null) {
|
|
|
|
recipientAddressString = sendArgumentsWrapper.recipientAddress
|
|
|
|
}
|
|
|
|
if (sendArgumentsWrapper?.amount != null) {
|
|
|
|
amountZecString = sendArgumentsWrapper.amount
|
|
|
|
}
|
|
|
|
if (sendArgumentsWrapper?.memo != null) {
|
|
|
|
memoString = sendArgumentsWrapper.memo
|
|
|
|
}
|
|
|
|
|
2023-10-04 07:01:40 -07:00
|
|
|
Column(
|
|
|
|
modifier = modifier,
|
|
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
|
|
) {
|
2023-03-16 07:36:06 -07:00
|
|
|
Header(
|
|
|
|
text = stringResource(id = R.string.send_balance, myBalance.toZecString()),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
Body(
|
|
|
|
text = stringResource(id = R.string.send_balance_subtitle),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(dimens.spacingLarge))
|
2022-03-01 05:11:23 -08:00
|
|
|
|
2023-03-30 00:58:20 -07:00
|
|
|
FormTextField(
|
|
|
|
value = recipientAddressString,
|
|
|
|
onValueChange = { recipientAddressString = it },
|
|
|
|
label = { Text(stringResource(id = R.string.send_to)) },
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
2023-12-11 01:20:32 -08:00
|
|
|
trailingIcon =
|
|
|
|
if (hasCameraFeature) {
|
|
|
|
{
|
|
|
|
IconButton(
|
|
|
|
onClick = onQrScannerOpen,
|
|
|
|
content = {
|
|
|
|
Icon(
|
|
|
|
imageVector = Icons.Outlined.QrCodeScanner,
|
|
|
|
contentDescription = stringResource(R.string.send_scan_content_description)
|
|
|
|
)
|
|
|
|
}
|
2023-03-30 00:58:20 -07:00
|
|
|
)
|
|
|
|
}
|
2023-12-11 01:20:32 -08:00
|
|
|
} else {
|
|
|
|
null
|
|
|
|
}
|
2023-03-30 00:58:20 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(Modifier.size(dimens.spacingSmall))
|
|
|
|
|
2023-03-16 07:36:06 -07:00
|
|
|
FormTextField(
|
2022-03-01 05:11:23 -08:00
|
|
|
value = amountZecString,
|
|
|
|
onValueChange = { newValue ->
|
2022-04-01 07:28:16 -07:00
|
|
|
if (!ZecStringExt.filterContinuous(context, monetarySeparators, newValue)) {
|
2023-03-16 07:36:06 -07:00
|
|
|
return@FormTextField
|
2022-04-01 07:28:16 -07:00
|
|
|
}
|
2022-03-01 05:11:23 -08:00
|
|
|
amountZecString = newValue.filter { allowedCharacters.contains(it) }
|
|
|
|
},
|
|
|
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
2023-03-16 07:36:06 -07:00
|
|
|
label = { Text(stringResource(id = R.string.send_amount)) },
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
2022-03-01 05:11:23 -08:00
|
|
|
)
|
|
|
|
|
2023-03-16 07:36:06 -07:00
|
|
|
Spacer(Modifier.size(dimens.spacingSmall))
|
2022-03-01 05:11:23 -08:00
|
|
|
|
2023-03-16 07:36:06 -07:00
|
|
|
// TODO [#810]: Disable Memo UI field in case of Transparent address
|
2023-11-23 01:00:13 -08:00
|
|
|
// TODO [#810]: https://github.com/Electric-Coin-Company/zashi-android/issues/810
|
2023-03-16 07:36:06 -07:00
|
|
|
FormTextField(
|
|
|
|
value = memoString,
|
|
|
|
onValueChange = {
|
|
|
|
if (Memo.isWithinMaxLength(it)) {
|
|
|
|
memoString = it
|
|
|
|
}
|
|
|
|
},
|
|
|
|
label = { Text(stringResource(id = R.string.send_memo)) },
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
|
2023-04-04 05:21:18 -07:00
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.weight(MINIMAL_WEIGHT)
|
2023-04-04 05:21:18 -07:00
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
|
|
|
|
if (validation.isNotEmpty()) {
|
|
|
|
/*
|
|
|
|
* Note: this is not localized in that it uses the enum constant name and joins the string
|
|
|
|
* without regard for RTL. This will get resolved once we do proper validation for
|
|
|
|
* the fields.
|
|
|
|
*/
|
2023-03-16 07:36:06 -07:00
|
|
|
Text(
|
|
|
|
text = validation.joinToString(", "),
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
|
|
|
|
2023-03-16 07:36:06 -07:00
|
|
|
Spacer(modifier = Modifier.height(dimens.spacingDefault))
|
|
|
|
|
2022-03-01 05:11:23 -08:00
|
|
|
PrimaryButton(
|
|
|
|
onClick = {
|
2023-12-11 01:20:32 -08:00
|
|
|
val zecSendValidation =
|
|
|
|
ZecSendExt.new(
|
|
|
|
context,
|
|
|
|
recipientAddressString,
|
|
|
|
amountZecString,
|
|
|
|
memoString,
|
|
|
|
monetarySeparators
|
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
|
|
|
|
when (zecSendValidation) {
|
2023-03-26 23:25:36 -07:00
|
|
|
is ZecSendExt.ZecSendValidation.Valid -> onCreateZecSend(zecSendValidation.zecSend)
|
2022-04-08 05:33:08 -07:00
|
|
|
is ZecSendExt.ZecSendValidation.Invalid -> validation = zecSendValidation.validationErrors
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
text = stringResource(id = R.string.send_create),
|
|
|
|
// Check for ABBREVIATION_INDEX goes away once proper address validation is in place.
|
|
|
|
// For now, it just prevents a crash on the confirmation screen.
|
2023-04-04 05:21:18 -07:00
|
|
|
enabled = amountZecString.isNotBlank() && recipientAddressString.length > ABBREVIATION_INDEX,
|
2023-12-18 05:31:25 -08:00
|
|
|
outerPaddingValues = PaddingValues(top = dimens.spacingNone),
|
|
|
|
modifier = Modifier.testTag(SendTag.SEND_FORM_BUTTON)
|
2022-03-01 05:11:23 -08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2023-12-18 05:31:25 -08:00
|
|
|
private fun SendConfirmation(
|
2022-06-09 09:31:44 -07:00
|
|
|
zecSend: ZecSend,
|
2023-03-16 07:36:06 -07:00
|
|
|
onConfirmation: () -> Unit,
|
|
|
|
modifier: Modifier = Modifier
|
2022-06-09 09:31:44 -07:00
|
|
|
) {
|
2023-10-04 07:01:40 -07:00
|
|
|
Column(
|
|
|
|
modifier = modifier,
|
|
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
|
|
) {
|
2023-03-26 23:25:36 -07:00
|
|
|
Body(
|
2022-03-01 05:11:23 -08:00
|
|
|
stringResource(
|
2023-03-26 23:25:36 -07:00
|
|
|
R.string.send_confirmation_amount_and_address_format,
|
2022-03-01 05:11:23 -08:00
|
|
|
zecSend.amount.toZecString(),
|
|
|
|
zecSend.destination.abbreviated()
|
|
|
|
)
|
|
|
|
)
|
2023-03-26 23:25:36 -07:00
|
|
|
if (zecSend.memo.value.isNotEmpty()) {
|
|
|
|
Body(
|
|
|
|
stringResource(
|
|
|
|
R.string.send_confirmation_memo_format,
|
|
|
|
zecSend.memo.value
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.weight(MINIMAL_WEIGHT)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
2022-03-01 05:11:23 -08:00
|
|
|
|
2023-03-20 02:17:22 -07:00
|
|
|
PrimaryButton(
|
2023-12-18 05:31:25 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.padding(top = dimens.spacingSmall)
|
|
|
|
.testTag(SendTag.SEND_CONFIRMATION_BUTTON),
|
2022-12-02 01:54:06 -08:00
|
|
|
onClick = onConfirmation,
|
2023-04-04 05:21:18 -07:00
|
|
|
text = stringResource(id = R.string.send_confirmation_button),
|
|
|
|
outerPaddingValues = PaddingValues(top = dimens.spacingSmall)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
2023-10-04 07:01:40 -07:00
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(dimens.spacingDefault))
|
2023-03-26 23:25:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun Sending(
|
|
|
|
zecSend: ZecSend,
|
|
|
|
modifier: Modifier = Modifier
|
|
|
|
) {
|
2023-04-04 05:21:18 -07:00
|
|
|
Column(modifier) {
|
2023-03-26 23:25:36 -07:00
|
|
|
Header(
|
2023-12-11 01:20:32 -08:00
|
|
|
text =
|
|
|
|
stringResource(
|
|
|
|
R.string.send_in_progress_amount_format,
|
|
|
|
zecSend.amount.toZecString()
|
|
|
|
),
|
2023-03-26 23:25:36 -07:00
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
|
|
|
|
Body(
|
|
|
|
text = zecSend.destination.abbreviated(),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
|
|
|
|
if (zecSend.memo.value.isNotEmpty()) {
|
|
|
|
Body(
|
|
|
|
stringResource(
|
|
|
|
R.string.send_in_progress_memo_format,
|
|
|
|
zecSend.memo.value
|
|
|
|
),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.weight(MINIMAL_WEIGHT)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
Body(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.padding(vertical = dimens.spacingSmall)
|
|
|
|
.fillMaxWidth(),
|
2023-03-26 23:25:36 -07:00
|
|
|
text = stringResource(R.string.send_in_progress_wait),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun SendSuccessful(
|
|
|
|
zecSend: ZecSend,
|
|
|
|
onDone: () -> Unit,
|
|
|
|
modifier: Modifier = Modifier
|
|
|
|
) {
|
2023-10-04 07:01:40 -07:00
|
|
|
Column(
|
|
|
|
modifier = modifier,
|
|
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
|
|
) {
|
2023-03-26 23:25:36 -07:00
|
|
|
Header(
|
|
|
|
text = stringResource(R.string.send_successful_title),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxWidth()
|
|
|
|
.height(dimens.spacingDefault)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
Body(
|
|
|
|
stringResource(
|
|
|
|
R.string.send_successful_amount_address_memo,
|
|
|
|
zecSend.amount.toZecString(),
|
|
|
|
zecSend.destination.abbreviated(),
|
|
|
|
zecSend.memo.valueOrEmptyChar()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.weight(MINIMAL_WEIGHT)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
PrimaryButton(
|
2023-12-18 05:31:25 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.padding(top = dimens.spacingSmall)
|
|
|
|
.testTag(SendTag.SEND_SUCCESS_BUTTON),
|
2023-03-26 23:25:36 -07:00
|
|
|
text = stringResource(R.string.send_successful_button),
|
2023-04-04 05:21:18 -07:00
|
|
|
onClick = onDone,
|
|
|
|
outerPaddingValues = PaddingValues(top = dimens.spacingSmall)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
2023-10-04 07:01:40 -07:00
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(dimens.spacingDefault))
|
2023-03-26 23:25:36 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
private fun SendFailure(
|
|
|
|
zecSend: ZecSend,
|
|
|
|
onDone: () -> Unit,
|
|
|
|
modifier: Modifier = Modifier
|
|
|
|
) {
|
2023-10-04 07:01:40 -07:00
|
|
|
Column(
|
|
|
|
modifier = modifier,
|
|
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
|
|
) {
|
2023-03-26 23:25:36 -07:00
|
|
|
Header(
|
|
|
|
text = stringResource(R.string.send_failure_title),
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
modifier = Modifier.fillMaxWidth()
|
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxWidth()
|
|
|
|
.height(dimens.spacingDefault)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
Body(
|
|
|
|
stringResource(
|
|
|
|
R.string.send_failure_amount_address_memo,
|
|
|
|
zecSend.amount.toZecString(),
|
|
|
|
zecSend.destination.abbreviated(),
|
|
|
|
zecSend.memo.valueOrEmptyChar()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
Spacer(
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.weight(MINIMAL_WEIGHT)
|
2023-03-26 23:25:36 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
PrimaryButton(
|
2023-12-18 05:31:25 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.padding(top = dimens.spacingSmall)
|
|
|
|
.testTag(SendTag.SEND_FAILED_BUTTON),
|
2023-03-26 23:25:36 -07:00
|
|
|
text = stringResource(R.string.send_failure_button),
|
2023-04-04 05:21:18 -07:00
|
|
|
onClick = onDone,
|
|
|
|
outerPaddingValues = PaddingValues(top = dimens.spacingSmall)
|
2023-03-01 04:58:47 -08:00
|
|
|
)
|
2023-10-04 07:01:40 -07:00
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(dimens.spacingDefault))
|
2022-03-01 05:11:23 -08:00
|
|
|
}
|
|
|
|
}
|