QR code image logic refactoring (#1732)
* QR code image logic refactor The QR code image logic of the `QrCode` and `Request` screens has been refactored to work upon the newer `ZashiQr` component * Refactor values into state * Changelog update
This commit is contained in:
parent
db983c692f
commit
603178fd67
|
@ -6,6 +6,10 @@ and this application adheres to [Semantic Versioning](https://semver.org/spec/v2
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The QR code image logic of the `QrCode`, `Request`, and `SignTransaction` screens has been refactored to work
|
||||||
|
with the newer `ZashiQr` component
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- The Disconnected popup trigger when the app is backgrounded has been fixed
|
- The Disconnected popup trigger when the app is backgrounded has been fixed
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,21 @@ package co.electriccoin.zcash.ui.design.component
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||||
|
@ -19,31 +24,44 @@ import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
|
||||||
import co.electriccoin.zcash.ui.design.util.AndroidQrCodeImageGenerator
|
import co.electriccoin.zcash.ui.design.util.AndroidQrCodeImageGenerator
|
||||||
import co.electriccoin.zcash.ui.design.util.JvmQrCodeGenerator
|
import co.electriccoin.zcash.ui.design.util.JvmQrCodeGenerator
|
||||||
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
||||||
|
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||||
|
import co.electriccoin.zcash.ui.design.util.getValue
|
||||||
import co.electriccoin.zcash.ui.design.util.orDark
|
import co.electriccoin.zcash.ui.design.util.orDark
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ZashiQr(
|
fun ZashiQr(
|
||||||
qrData: String,
|
state: QrState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
qrSize: Dp = ZashiQrDefaults.width,
|
qrSize: Dp = ZashiQrDefaults.width,
|
||||||
colors: QrCodeColors = QrCodeDefaults.colors()
|
colors: QrCodeColors = QrCodeDefaults.colors(),
|
||||||
) {
|
) {
|
||||||
val qrSizePx = with(LocalDensity.current) { qrSize.roundToPx() }
|
val qrSizePx = with(LocalDensity.current) { qrSize.roundToPx() }
|
||||||
val bitmap = getQrCode(qrData, qrSizePx, colors)
|
val bitmap = getQrCode(state.qrData, qrSizePx, colors)
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl),
|
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl),
|
||||||
border = BorderStroke(width = 1.dp, color = ZashiColors.Surfaces.strokePrimary),
|
border = BorderStroke(width = 1.dp, color = ZashiColors.Surfaces.strokePrimary),
|
||||||
color = ZashiColors.Surfaces.bgPrimary
|
color = ZashiColors.Surfaces.bgPrimary,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(all = 12.dp)
|
modifier = Modifier.padding(all = 12.dp)
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
bitmap = bitmap,
|
bitmap = bitmap,
|
||||||
contentDescription = null,
|
contentDescription = state.contentDescription?.getValue(),
|
||||||
|
Modifier.clickable { state.onClick() }
|
||||||
)
|
)
|
||||||
|
if (state.centerImageResId != null) {
|
||||||
|
Image(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.size(64.dp)
|
||||||
|
.align(Alignment.Center),
|
||||||
|
imageVector = ImageVector.vectorResource(state.centerImageResId),
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,3 +93,10 @@ object QrCodeDefaults {
|
||||||
foreground = foreground
|
foreground = foreground
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class QrState(
|
||||||
|
val qrData: String,
|
||||||
|
val contentDescription: StringResource? = null,
|
||||||
|
val onClick: () -> Unit = {},
|
||||||
|
val centerImageResId: Int? = null,
|
||||||
|
)
|
||||||
|
|
|
@ -541,20 +541,7 @@ fun NavHostController.popBackStackJustOnce(currentRouteToBePopped: String) {
|
||||||
object NavigationArguments {
|
object NavigationArguments {
|
||||||
const val SEND_SCAN_RECIPIENT_ADDRESS = "send_scan_recipient_address"
|
const val SEND_SCAN_RECIPIENT_ADDRESS = "send_scan_recipient_address"
|
||||||
const val SEND_SCAN_ZIP_321_URI = "send_scan_zip_321_uri"
|
const val SEND_SCAN_ZIP_321_URI = "send_scan_zip_321_uri"
|
||||||
|
|
||||||
const val SEND_CONFIRM_RECIPIENT_ADDRESS = "send_confirm_recipient_address"
|
|
||||||
const val SEND_CONFIRM_AMOUNT = "send_confirm_amount"
|
|
||||||
const val SEND_CONFIRM_MEMO = "send_confirm_memo"
|
|
||||||
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"
|
||||||
|
|
||||||
const val PAYMENT_REQUEST_ADDRESS = "payment_request_address"
|
|
||||||
const val PAYMENT_REQUEST_AMOUNT = "payment_request_amount"
|
|
||||||
const val PAYMENT_REQUEST_MEMO = "payment_request_memo"
|
|
||||||
const val PAYMENT_REQUEST_PROPOSAL = "payment_request_proposal"
|
|
||||||
const val PAYMENT_REQUEST_URI = "payment_request_uri"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object NavigationTargets {
|
object NavigationTargets {
|
||||||
|
|
|
@ -5,7 +5,6 @@ package co.electriccoin.zcash.ui.screen.exchangerate.widget
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.MutableTransitionState
|
import androidx.compose.animation.core.MutableTransitionState
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.basicMarquee
|
import androidx.compose.foundation.basicMarquee
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -93,7 +92,6 @@ fun StyledExchangeBalance(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("LongParameterList", "LongMethod")
|
@Suppress("LongParameterList", "LongMethod")
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ExchangeAvailableRateLabelInternal(
|
private fun ExchangeAvailableRateLabelInternal(
|
||||||
style: TextStyle,
|
style: TextStyle,
|
||||||
|
|
|
@ -2,8 +2,10 @@ package co.electriccoin.zcash.ui.screen.qrcode.model
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddress
|
import cash.z.ecc.android.sdk.model.WalletAddress
|
||||||
|
import co.electriccoin.zcash.ui.design.component.QrState
|
||||||
|
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||||
|
|
||||||
internal sealed class QrCodeState {
|
sealed class QrCodeState {
|
||||||
data object Loading : QrCodeState()
|
data object Loading : QrCodeState()
|
||||||
|
|
||||||
data class Prepared(
|
data class Prepared(
|
||||||
|
@ -11,8 +13,19 @@ internal sealed class QrCodeState {
|
||||||
val walletAddress: WalletAddress,
|
val walletAddress: WalletAddress,
|
||||||
val onAddressCopy: (String) -> Unit,
|
val onAddressCopy: (String) -> Unit,
|
||||||
val onQrCodeShare: (ImageBitmap) -> Unit,
|
val onQrCodeShare: (ImageBitmap) -> Unit,
|
||||||
|
val onQrCodeClick: () -> Unit,
|
||||||
val onBack: () -> Unit,
|
val onBack: () -> Unit,
|
||||||
) : QrCodeState()
|
) : QrCodeState() {
|
||||||
|
fun toQrState(
|
||||||
|
contentDescription: StringResource? = null,
|
||||||
|
centerImageResId: Int? = null
|
||||||
|
) = QrState(
|
||||||
|
qrData = walletAddress.address,
|
||||||
|
onClick = onQrCodeClick,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
centerImageResId = centerImageResId
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class QrCodeType {
|
enum class QrCodeType {
|
||||||
|
|
|
@ -3,15 +3,10 @@
|
||||||
package co.electriccoin.zcash.ui.screen.qrcode.view
|
package co.electriccoin.zcash.ui.screen.qrcode.view
|
||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.BorderStroke
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
@ -21,7 +16,6 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
|
@ -33,7 +27,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.ImageBitmap
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
@ -55,15 +49,16 @@ import co.electriccoin.zcash.ui.design.component.ZashiBadgeColors
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiBottomBar
|
import co.electriccoin.zcash.ui.design.component.ZashiBottomBar
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
||||||
|
import co.electriccoin.zcash.ui.design.component.ZashiQr
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
|
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
|
||||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||||
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||||
import co.electriccoin.zcash.ui.design.util.AndroidQrCodeImageGenerator
|
import co.electriccoin.zcash.ui.design.util.AndroidQrCodeImageGenerator
|
||||||
import co.electriccoin.zcash.ui.design.util.JvmQrCodeGenerator
|
import co.electriccoin.zcash.ui.design.util.JvmQrCodeGenerator
|
||||||
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
||||||
|
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||||
import co.electriccoin.zcash.ui.screen.qrcode.model.QrCodeState
|
import co.electriccoin.zcash.ui.screen.qrcode.model.QrCodeState
|
||||||
import co.electriccoin.zcash.ui.screen.qrcode.model.QrCodeType
|
import co.electriccoin.zcash.ui.screen.qrcode.model.QrCodeType
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
@ -91,6 +86,7 @@ private fun ZashiPreview() =
|
||||||
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
||||||
onAddressCopy = {},
|
onAddressCopy = {},
|
||||||
onQrCodeShare = {},
|
onQrCodeShare = {},
|
||||||
|
onQrCodeClick = {},
|
||||||
onBack = {},
|
onBack = {},
|
||||||
),
|
),
|
||||||
snackbarHostState = SnackbarHostState(),
|
snackbarHostState = SnackbarHostState(),
|
||||||
|
@ -109,6 +105,7 @@ private fun KeystonePreview() =
|
||||||
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
walletAddress = runBlocking { WalletAddressFixture.unified() },
|
||||||
onAddressCopy = {},
|
onAddressCopy = {},
|
||||||
onQrCodeShare = {},
|
onQrCodeShare = {},
|
||||||
|
onQrCodeClick = {},
|
||||||
onBack = {},
|
onBack = {},
|
||||||
),
|
),
|
||||||
snackbarHostState = SnackbarHostState(),
|
snackbarHostState = SnackbarHostState(),
|
||||||
|
@ -154,10 +151,7 @@ internal fun QrCodeView(
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
QrCodeContents(
|
QrCodeContents(
|
||||||
qrCodeType = state.qrCodeType,
|
state = state,
|
||||||
walletAddress = state.walletAddress,
|
|
||||||
onAddressCopy = state.onAddressCopy,
|
|
||||||
onQrCodeShare = state.onQrCodeShare,
|
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.padding(
|
Modifier.padding(
|
||||||
top = paddingValues.calculateTopPadding(),
|
top = paddingValues.calculateTopPadding(),
|
||||||
|
@ -239,10 +233,7 @@ private fun QrCodeBottomBar(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun QrCodeContents(
|
private fun QrCodeContents(
|
||||||
qrCodeType: QrCodeType,
|
state: QrCodeState.Prepared,
|
||||||
walletAddress: WalletAddress,
|
|
||||||
onAddressCopy: (String) -> Unit,
|
|
||||||
onQrCodeShare: (ImageBitmap) -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
|
@ -254,16 +245,16 @@ private fun QrCodeContents(
|
||||||
) {
|
) {
|
||||||
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
|
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
|
||||||
|
|
||||||
when (walletAddress) {
|
when (state.walletAddress) {
|
||||||
// We use the same design for the Sapling address for the Testnet app variant
|
// We use the same design for the Sapling address for the Testnet app variant
|
||||||
is WalletAddress.Unified, is WalletAddress.Sapling -> {
|
is WalletAddress.Unified, is WalletAddress.Sapling -> {
|
||||||
UnifiedQrCodePanel(qrCodeType, walletAddress, onAddressCopy, onQrCodeShare)
|
UnifiedQrCodePanel(state)
|
||||||
}
|
}
|
||||||
is WalletAddress.Transparent -> {
|
is WalletAddress.Transparent -> {
|
||||||
TransparentQrCodePanel(qrCodeType, walletAddress, onAddressCopy, onQrCodeShare)
|
TransparentQrCodePanel(state)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
error("Unsupported address type: $walletAddress")
|
error("Unsupported address type: ${state.walletAddress}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,10 +263,7 @@ private fun QrCodeContents(
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
fun UnifiedQrCodePanel(
|
fun UnifiedQrCodePanel(
|
||||||
qrCodeType: QrCodeType,
|
state: QrCodeState.Prepared,
|
||||||
walletAddress: WalletAddress,
|
|
||||||
onAddressCopy: (String) -> Unit,
|
|
||||||
onQrCodeShare: (ImageBitmap) -> Unit,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
var expandedAddress by rememberSaveable { mutableStateOf(false) }
|
var expandedAddress by rememberSaveable { mutableStateOf(false) }
|
||||||
|
@ -284,15 +272,13 @@ fun UnifiedQrCodePanel(
|
||||||
modifier =
|
modifier =
|
||||||
modifier
|
modifier
|
||||||
.padding(vertical = ZcashTheme.dimens.spacingDefault),
|
.padding(vertical = ZcashTheme.dimens.spacingDefault),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = CenterHorizontally
|
||||||
) {
|
) {
|
||||||
QrCode(
|
QrCode(
|
||||||
walletAddress = walletAddress,
|
preparedState = state,
|
||||||
onQrImageShare = onQrCodeShare,
|
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = 24.dp),
|
.padding(horizontal = 24.dp),
|
||||||
qrCodeType = qrCodeType,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
||||||
|
@ -312,18 +298,18 @@ fun UnifiedQrCodePanel(
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text =
|
text =
|
||||||
when (walletAddress) {
|
when (state.walletAddress) {
|
||||||
is WalletAddress.Unified ->
|
is WalletAddress.Unified ->
|
||||||
when (qrCodeType) {
|
when (state.qrCodeType) {
|
||||||
QrCodeType.ZASHI -> stringResource(R.string.qr_code_wallet_address_shielded)
|
QrCodeType.ZASHI -> stringResource(R.string.qr_code_wallet_address_shielded)
|
||||||
QrCodeType.KEYSTONE -> stringResource(R.string.qr_code_wallet_address_shielded_keystone)
|
QrCodeType.KEYSTONE -> stringResource(R.string.qr_code_wallet_address_shielded_keystone)
|
||||||
}
|
}
|
||||||
is WalletAddress.Sapling ->
|
is WalletAddress.Sapling ->
|
||||||
when (qrCodeType) {
|
when (state.qrCodeType) {
|
||||||
QrCodeType.ZASHI -> stringResource(id = R.string.qr_code_wallet_address_sapling)
|
QrCodeType.ZASHI -> stringResource(id = R.string.qr_code_wallet_address_sapling)
|
||||||
QrCodeType.KEYSTONE -> stringResource(id = R.string.qr_code_wallet_address_sapling_keystone)
|
QrCodeType.KEYSTONE -> stringResource(id = R.string.qr_code_wallet_address_sapling_keystone)
|
||||||
}
|
}
|
||||||
else -> error("Unsupported address type: $walletAddress")
|
else -> error("Unsupported address type: ${state.walletAddress}")
|
||||||
},
|
},
|
||||||
color = ZashiColors.Text.textPrimary,
|
color = ZashiColors.Text.textPrimary,
|
||||||
style = ZashiTypography.textXl,
|
style = ZashiTypography.textXl,
|
||||||
|
@ -335,7 +321,7 @@ fun UnifiedQrCodePanel(
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
Text(
|
Text(
|
||||||
text = walletAddress.address,
|
text = state.walletAddress.address,
|
||||||
color = ZashiColors.Text.textTertiary,
|
color = ZashiColors.Text.textTertiary,
|
||||||
style = ZashiTypography.textSm,
|
style = ZashiTypography.textSm,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
@ -353,7 +339,7 @@ fun UnifiedQrCodePanel(
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
onClick = { expandedAddress = !expandedAddress },
|
onClick = { expandedAddress = !expandedAddress },
|
||||||
onLongClick = { onAddressCopy(walletAddress.address) }
|
onLongClick = { state.onAddressCopy(state.walletAddress.address) }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -362,10 +348,7 @@ fun UnifiedQrCodePanel(
|
||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
fun TransparentQrCodePanel(
|
fun TransparentQrCodePanel(
|
||||||
qrCodeType: QrCodeType,
|
state: QrCodeState.Prepared,
|
||||||
walletAddress: WalletAddress,
|
|
||||||
onAddressCopy: (String) -> Unit,
|
|
||||||
onQrCodeShare: (ImageBitmap) -> Unit,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
var expandedAddress by rememberSaveable { mutableStateOf(false) }
|
var expandedAddress by rememberSaveable { mutableStateOf(false) }
|
||||||
|
@ -374,15 +357,13 @@ fun TransparentQrCodePanel(
|
||||||
modifier =
|
modifier =
|
||||||
modifier
|
modifier
|
||||||
.padding(vertical = ZcashTheme.dimens.spacingDefault),
|
.padding(vertical = ZcashTheme.dimens.spacingDefault),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = CenterHorizontally
|
||||||
) {
|
) {
|
||||||
QrCode(
|
QrCode(
|
||||||
walletAddress = walletAddress,
|
preparedState = state,
|
||||||
onQrImageShare = onQrCodeShare,
|
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = 24.dp),
|
.padding(horizontal = 24.dp),
|
||||||
qrCodeType = qrCodeType,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingUpLarge))
|
||||||
|
@ -412,7 +393,7 @@ fun TransparentQrCodePanel(
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
Text(
|
Text(
|
||||||
text = walletAddress.address,
|
text = state.walletAddress.address,
|
||||||
color = ZashiColors.Text.textTertiary,
|
color = ZashiColors.Text.textTertiary,
|
||||||
style = ZashiTypography.textSm,
|
style = ZashiTypography.textSm,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
@ -430,7 +411,7 @@ fun TransparentQrCodePanel(
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
onClick = { expandedAddress = !expandedAddress },
|
onClick = { expandedAddress = !expandedAddress },
|
||||||
onLongClick = { onAddressCopy(walletAddress.address) }
|
onLongClick = { state.onAddressCopy(state.walletAddress.address) }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -438,51 +419,28 @@ fun TransparentQrCodePanel(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.QrCode(
|
private fun ColumnScope.QrCode(
|
||||||
qrCodeType: QrCodeType,
|
preparedState: QrCodeState.Prepared,
|
||||||
walletAddress: WalletAddress,
|
|
||||||
onQrImageShare: (ImageBitmap) -> Unit,
|
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val sizePixels = with(LocalDensity.current) { DEFAULT_QR_CODE_SIZE.toPx() }.roundToInt()
|
ZashiQr(
|
||||||
val colors = QrCodeDefaults.colors()
|
state =
|
||||||
val qrCodeImage =
|
preparedState.toQrState(
|
||||||
remember {
|
contentDescription =
|
||||||
qrCodeForAddress(
|
stringRes(
|
||||||
address = walletAddress.address,
|
when (preparedState.walletAddress) {
|
||||||
size = sizePixels,
|
is WalletAddress.Unified -> R.string.qr_code_unified_content_description
|
||||||
colors = colors
|
is WalletAddress.Sapling -> R.string.qr_code_sapling_content_description
|
||||||
)
|
is WalletAddress.Transparent -> R.string.qr_code_transparent_content_description
|
||||||
}
|
else -> error("Unsupported address type: ${preparedState.walletAddress}")
|
||||||
|
}
|
||||||
QrCode(
|
),
|
||||||
qrCodeImage = qrCodeImage,
|
centerImageResId =
|
||||||
onQrImageBitmapShare = onQrImageShare,
|
when (preparedState.qrCodeType) {
|
||||||
contentDescription =
|
QrCodeType.ZASHI -> R.drawable.logo_zec_fill_stroke
|
||||||
stringResource(
|
QrCodeType.KEYSTONE -> co.electriccoin.zcash.ui.design.R.drawable.ic_item_keystone_qr
|
||||||
when (walletAddress) {
|
}
|
||||||
is WalletAddress.Unified -> R.string.qr_code_unified_content_description
|
|
||||||
is WalletAddress.Sapling -> R.string.qr_code_sapling_content_description
|
|
||||||
is WalletAddress.Transparent -> R.string.qr_code_transparent_content_description
|
|
||||||
else -> error("Unsupported address type: $walletAddress")
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
modifier =
|
modifier = modifier.align(CenterHorizontally),
|
||||||
modifier
|
|
||||||
.align(Alignment.CenterHorizontally)
|
|
||||||
.border(
|
|
||||||
border =
|
|
||||||
BorderStroke(
|
|
||||||
width = 1.dp,
|
|
||||||
color = ZashiColors.Surfaces.strokePrimary
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl)
|
|
||||||
)
|
|
||||||
.background(
|
|
||||||
color = ZashiColors.Surfaces.bgPrimary,
|
|
||||||
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl)
|
|
||||||
)
|
|
||||||
.padding(all = 12.dp),
|
|
||||||
qrCodeType = qrCodeType
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,45 +460,4 @@ private fun qrCodeForAddress(
|
||||||
return AndroidQrCodeImageGenerator.generate(qrCodePixelArray, size, colors)
|
return AndroidQrCodeImageGenerator.generate(qrCodePixelArray, size, colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun QrCode(
|
|
||||||
qrCodeType: QrCodeType,
|
|
||||||
contentDescription: String,
|
|
||||||
qrCodeImage: ImageBitmap,
|
|
||||||
onQrImageBitmapShare: (ImageBitmap) -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.clickable(
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
onClick = { onQrImageBitmapShare(qrCodeImage) },
|
|
||||||
)
|
|
||||||
.then(modifier)
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
bitmap = qrCodeImage,
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
)
|
|
||||||
|
|
||||||
Image(
|
|
||||||
modifier = Modifier.size(64.dp),
|
|
||||||
painter =
|
|
||||||
when (qrCodeType) {
|
|
||||||
QrCodeType.ZASHI -> painterResource(id = R.drawable.logo_zec_fill_stroke)
|
|
||||||
QrCodeType.KEYSTONE ->
|
|
||||||
painterResource(
|
|
||||||
id =
|
|
||||||
co.electriccoin.zcash.ui.design.R.drawable
|
|
||||||
.ic_item_keystone_qr
|
|
||||||
)
|
|
||||||
},
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val DEFAULT_QR_CODE_SIZE = 320.dp
|
private val DEFAULT_QR_CODE_SIZE = 320.dp
|
||||||
|
|
|
@ -57,6 +57,10 @@ class QrCodeViewModel(
|
||||||
walletAddress = walletAddress,
|
walletAddress = walletAddress,
|
||||||
onAddressCopy = { address -> onAddressCopyClick(address) },
|
onAddressCopy = { address -> onAddressCopyClick(address) },
|
||||||
onQrCodeShare = { onQrCodeShareClick(it, versionInfo) },
|
onQrCodeShare = { onQrCodeShareClick(it, versionInfo) },
|
||||||
|
onQrCodeClick = {
|
||||||
|
// TODO [#1731]: Allow QR codes colors switching
|
||||||
|
// TODO [#1731]: https://github.com/Electric-Coin-Company/zashi-android/issues/1731
|
||||||
|
},
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
qrCodeType =
|
qrCodeType =
|
||||||
when (account) {
|
when (account) {
|
||||||
|
|
|
@ -5,7 +5,9 @@ import cash.z.ecc.android.sdk.model.MonetarySeparators
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddress
|
import cash.z.ecc.android.sdk.model.WalletAddress
|
||||||
import cash.z.ecc.sdk.type.ZcashCurrency
|
import cash.z.ecc.sdk.type.ZcashCurrency
|
||||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||||
|
import co.electriccoin.zcash.ui.design.component.QrState
|
||||||
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
import co.electriccoin.zcash.ui.design.util.QrCodeColors
|
||||||
|
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||||
|
|
||||||
internal sealed class RequestState {
|
internal sealed class RequestState {
|
||||||
data object Loading : RequestState()
|
data object Loading : RequestState()
|
||||||
|
@ -37,10 +39,21 @@ internal sealed class RequestState {
|
||||||
val icon: Int,
|
val icon: Int,
|
||||||
val request: Request,
|
val request: Request,
|
||||||
val walletAddress: WalletAddress,
|
val walletAddress: WalletAddress,
|
||||||
|
val onQrCodeClick: () -> Unit,
|
||||||
val onQrCodeShare: (ImageBitmap) -> Unit,
|
val onQrCodeShare: (ImageBitmap) -> Unit,
|
||||||
val onQrCodeGenerate: (pixels: Int, colors: QrCodeColors) -> Unit,
|
val onQrCodeGenerate: (pixels: Int, colors: QrCodeColors) -> Unit,
|
||||||
override val onBack: () -> Unit,
|
override val onBack: () -> Unit,
|
||||||
val onClose: () -> Unit,
|
val onClose: () -> Unit,
|
||||||
val zcashCurrency: ZcashCurrency,
|
val zcashCurrency: ZcashCurrency,
|
||||||
) : Prepared(onBack)
|
) : Prepared(onBack) {
|
||||||
|
fun toQrState(
|
||||||
|
contentDescription: StringResource? = null,
|
||||||
|
centerImageResId: Int? = null,
|
||||||
|
) = QrState(
|
||||||
|
qrData = walletAddress.address,
|
||||||
|
onClick = onQrCodeClick,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
centerImageResId = centerImageResId
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
package co.electriccoin.zcash.ui.screen.request.view
|
package co.electriccoin.zcash.ui.screen.request.view
|
||||||
|
|
||||||
import androidx.compose.foundation.BorderStroke
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
|
@ -32,16 +22,14 @@ import androidx.compose.ui.text.withStyle
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cash.z.ecc.android.sdk.model.WalletAddress
|
import cash.z.ecc.android.sdk.model.WalletAddress
|
||||||
import co.electriccoin.zcash.ui.R
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
|
||||||
import co.electriccoin.zcash.ui.design.component.QrCodeDefaults
|
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiBadge
|
import co.electriccoin.zcash.ui.design.component.ZashiBadge
|
||||||
import co.electriccoin.zcash.ui.design.component.ZashiBadgeColors
|
import co.electriccoin.zcash.ui.design.component.ZashiBadgeColors
|
||||||
|
import co.electriccoin.zcash.ui.design.component.ZashiQr
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||||
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||||
|
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||||
import co.electriccoin.zcash.ui.screen.request.model.RequestState
|
import co.electriccoin.zcash.ui.screen.request.model.RequestState
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun RequestQrCodeView(
|
internal fun RequestQrCodeView(
|
||||||
|
@ -96,7 +84,7 @@ internal fun RequestQrCodeView(
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingBig))
|
||||||
|
|
||||||
QrCode(
|
QrCode(
|
||||||
state = state,
|
requestState = state,
|
||||||
modifier = Modifier.padding(horizontal = 24.dp),
|
modifier = Modifier.padding(horizontal = 24.dp),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -106,71 +94,19 @@ internal fun RequestQrCodeView(
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.QrCode(
|
private fun ColumnScope.QrCode(
|
||||||
state: RequestState.QrCode,
|
requestState: RequestState.QrCode,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val sizePixels = with(LocalDensity.current) { DEFAULT_QR_CODE_SIZE.toPx() }.roundToInt()
|
ZashiQr(
|
||||||
|
state =
|
||||||
if (state.request.qrCodeState.bitmap == null) {
|
requestState.toQrState(
|
||||||
val colors = QrCodeDefaults.colors()
|
contentDescription = stringRes(R.string.request_qr_code_content_description),
|
||||||
state.onQrCodeGenerate(sizePixels, colors)
|
centerImageResId = requestState.icon
|
||||||
}
|
),
|
||||||
|
modifier = modifier.align(CenterHorizontally),
|
||||||
QrCode(
|
|
||||||
state = state,
|
|
||||||
contentDescription = stringResource(id = R.string.request_qr_code_content_description),
|
|
||||||
modifier =
|
|
||||||
modifier
|
|
||||||
.align(Alignment.CenterHorizontally)
|
|
||||||
.border(
|
|
||||||
border =
|
|
||||||
BorderStroke(
|
|
||||||
width = 1.dp,
|
|
||||||
color = ZashiColors.Surfaces.strokePrimary
|
|
||||||
),
|
|
||||||
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl)
|
|
||||||
)
|
|
||||||
.background(
|
|
||||||
color = ZashiColors.Surfaces.bgPrimary,
|
|
||||||
shape = RoundedCornerShape(ZashiDimensions.Radius.radius4xl)
|
|
||||||
)
|
|
||||||
.padding(all = 12.dp)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun QrCode(
|
|
||||||
state: RequestState.QrCode,
|
|
||||||
contentDescription: String,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.clickable(
|
|
||||||
indication = null,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
onClick = { state.request.qrCodeState.bitmap?.let { state.onQrCodeShare(it) } },
|
|
||||||
)
|
|
||||||
.then(modifier)
|
|
||||||
) {
|
|
||||||
if (state.request.qrCodeState.bitmap == null) {
|
|
||||||
CircularScreenProgressIndicator()
|
|
||||||
} else {
|
|
||||||
Image(
|
|
||||||
bitmap = state.request.qrCodeState.bitmap,
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
)
|
|
||||||
Image(
|
|
||||||
modifier = Modifier.size(64.dp),
|
|
||||||
painter = painterResource(id = state.icon),
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RequestQrCodeZecAmountView(
|
private fun RequestQrCodeZecAmountView(
|
||||||
state: RequestState.QrCode,
|
state: RequestState.QrCode,
|
||||||
|
@ -196,5 +132,3 @@ private fun RequestQrCodeZecAmountView(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DEFAULT_QR_CODE_SIZE = 320.dp
|
|
||||||
|
|
|
@ -144,6 +144,10 @@ class RequestViewModel(
|
||||||
colors = colors,
|
colors = colors,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onQrCodeClick = {
|
||||||
|
// TODO [#1731]: Allow QR codes colors switching
|
||||||
|
// TODO [#1731]: https://github.com/Electric-Coin-Company/zashi-android/issues/1731
|
||||||
|
},
|
||||||
onQrCodeShare = { onRequestQrCodeShare(it, shareImageBitmap) },
|
onQrCodeShare = { onRequestQrCodeShare(it, shareImageBitmap) },
|
||||||
onBack = ::onBack,
|
onBack = ::onBack,
|
||||||
onClose = ::onClose,
|
onClose = ::onClose,
|
||||||
|
|
|
@ -2,17 +2,32 @@ package co.electriccoin.zcash.ui.screen.signkeystonetransaction.state
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||||
|
import co.electriccoin.zcash.ui.design.component.QrState
|
||||||
import co.electriccoin.zcash.ui.design.util.StringResource
|
import co.electriccoin.zcash.ui.design.util.StringResource
|
||||||
|
|
||||||
data class SignKeystoneTransactionState(
|
data class SignKeystoneTransactionState(
|
||||||
val onBack: () -> Unit,
|
val onBack: () -> Unit,
|
||||||
|
val onQrCodeClick: () -> Unit,
|
||||||
val accountInfo: ZashiAccountInfoListItemState,
|
val accountInfo: ZashiAccountInfoListItemState,
|
||||||
val qrData: String?,
|
val qrData: String?,
|
||||||
val generateNextQrCode: () -> Unit,
|
val generateNextQrCode: () -> Unit,
|
||||||
val shareButton: ButtonState?,
|
val shareButton: ButtonState?,
|
||||||
val positiveButton: ButtonState,
|
val positiveButton: ButtonState,
|
||||||
val negativeButton: ButtonState,
|
val negativeButton: ButtonState,
|
||||||
)
|
) {
|
||||||
|
fun toQrState(
|
||||||
|
contentDescription: StringResource? = null,
|
||||||
|
centerImageResId: Int? = null,
|
||||||
|
): QrState {
|
||||||
|
requireNotNull(qrData) { "The QR code data needs to be set at this point" }
|
||||||
|
return QrState(
|
||||||
|
qrData = qrData,
|
||||||
|
onClick = onQrCodeClick,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
centerImageResId = centerImageResId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data class ZashiAccountInfoListItemState(
|
data class ZashiAccountInfoListItemState(
|
||||||
@DrawableRes val icon: Int,
|
@DrawableRes val icon: Int,
|
||||||
|
|
|
@ -124,14 +124,17 @@ private fun ZashiAccountInfoListItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ColumnScope.QrContent(state: SignKeystoneTransactionState) {
|
private fun ColumnScope.QrContent(ksState: SignKeystoneTransactionState) {
|
||||||
state.qrData?.let {
|
ksState.qrData?.let {
|
||||||
ZashiQr(qrData = it, modifier = Modifier.align(CenterHorizontally))
|
ZashiQr(
|
||||||
|
state = ksState.toQrState(),
|
||||||
|
modifier = Modifier.align(CenterHorizontally)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
LaunchedEffect(state.qrData) {
|
LaunchedEffect(ksState.qrData) {
|
||||||
if (state.qrData != null) {
|
if (ksState.qrData != null) {
|
||||||
delay(100.milliseconds)
|
delay(100.milliseconds)
|
||||||
state.generateNextQrCode()
|
ksState.generateNextQrCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +185,7 @@ private fun Preview() =
|
||||||
positiveButton = ButtonState(stringRes("Get Signature")),
|
positiveButton = ButtonState(stringRes("Get Signature")),
|
||||||
negativeButton = ButtonState(stringRes("Reject")),
|
negativeButton = ButtonState(stringRes("Reject")),
|
||||||
onBack = {},
|
onBack = {},
|
||||||
|
onQrCodeClick = {},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -205,6 +209,7 @@ private fun DebugPreview() =
|
||||||
positiveButton = ButtonState(stringRes("Get Signature")),
|
positiveButton = ButtonState(stringRes("Get Signature")),
|
||||||
negativeButton = ButtonState(stringRes("Reject")),
|
negativeButton = ButtonState(stringRes("Reject")),
|
||||||
onBack = {},
|
onBack = {},
|
||||||
|
onQrCodeClick = {},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,11 @@ class SignKeystoneTransactionViewModel(
|
||||||
text = stringRes("Share PCZT"),
|
text = stringRes("Share PCZT"),
|
||||||
onClick = ::onSharePCZTClick
|
onClick = ::onSharePCZTClick
|
||||||
).takeIf { BuildConfig.DEBUG },
|
).takeIf { BuildConfig.DEBUG },
|
||||||
onBack = ::onBack
|
onBack = ::onBack,
|
||||||
|
onQrCodeClick = {
|
||||||
|
// TODO [#1731]: Allow QR codes colors switching
|
||||||
|
// TODO [#1731]: https://github.com/Electric-Coin-Company/zashi-android/issues/1731
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), null)
|
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), null)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue