2023-02-28 05:54:07 -08:00
|
|
|
package co.electriccoin.zcash.ui.screen.receive.view
|
2022-01-13 09:49:08 -08:00
|
|
|
|
|
|
|
import androidx.compose.foundation.Image
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.foundation.clickable
|
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.foundation.layout.Column
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.foundation.layout.Row
|
2023-04-04 05:21:18 -07:00
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
2023-04-04 05:21:18 -07:00
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
import androidx.compose.foundation.layout.padding
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.foundation.layout.wrapContentSize
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.foundation.rememberScrollState
|
|
|
|
import androidx.compose.foundation.verticalScroll
|
|
|
|
import androidx.compose.material.icons.Icons
|
2023-12-07 07:35:27 -08:00
|
|
|
import androidx.compose.material.icons.filled.BrightnessHigh
|
|
|
|
import androidx.compose.material.icons.filled.BrightnessLow
|
2022-02-21 06:33:40 -08:00
|
|
|
import androidx.compose.material3.Icon
|
|
|
|
import androidx.compose.material3.IconButton
|
2023-12-21 07:15:20 -08:00
|
|
|
import androidx.compose.material3.Scaffold
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.material3.SnackbarHost
|
|
|
|
import androidx.compose.material3.SnackbarHostState
|
2022-02-21 06:33:40 -08:00
|
|
|
import androidx.compose.material3.Text
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.runtime.Composable
|
2023-12-07 07:35:27 -08:00
|
|
|
import androidx.compose.runtime.mutableStateOf
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.runtime.remember
|
2023-12-07 07:35:27 -08:00
|
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.ui.Alignment
|
|
|
|
import androidx.compose.ui.Modifier
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.ui.graphics.ImageBitmap
|
|
|
|
import androidx.compose.ui.graphics.vector.ImageVector
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.ui.platform.LocalDensity
|
2023-12-18 05:31:25 -08:00
|
|
|
import androidx.compose.ui.platform.testTag
|
|
|
|
import androidx.compose.ui.res.painterResource
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.ui.res.stringResource
|
2024-01-15 08:32:15 -08:00
|
|
|
import androidx.compose.ui.res.vectorResource
|
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
2022-01-13 09:49:08 -08:00
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
import androidx.compose.ui.unit.dp
|
2024-01-15 08:32:15 -08:00
|
|
|
import cash.z.ecc.android.sdk.fixture.WalletAddressesFixture
|
2023-02-17 03:05:23 -08:00
|
|
|
import cash.z.ecc.android.sdk.model.WalletAddress
|
2024-01-15 08:32:15 -08:00
|
|
|
import cash.z.ecc.android.sdk.model.WalletAddresses
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.R
|
2022-09-29 06:13:54 -07:00
|
|
|
import co.electriccoin.zcash.ui.common.BrightenScreen
|
2022-10-13 06:13:41 -07:00
|
|
|
import co.electriccoin.zcash.ui.common.DisableScreenTimeout
|
2024-01-15 08:32:15 -08:00
|
|
|
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
2023-12-18 05:31:25 -08:00
|
|
|
import co.electriccoin.zcash.ui.common.test.CommonTag
|
2024-01-15 08:32:15 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
2024-01-15 08:32:15 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.Reference
|
2023-12-07 07:35:27 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
2024-01-15 08:32:15 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.component.SubHeader
|
2022-03-08 11:05:03 -08:00
|
|
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
2024-01-15 08:32:15 -08:00
|
|
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
2023-02-28 05:54:07 -08:00
|
|
|
import co.electriccoin.zcash.ui.screen.receive.util.AndroidQrCodeImageGenerator
|
|
|
|
import co.electriccoin.zcash.ui.screen.receive.util.JvmQrCodeGenerator
|
2022-01-13 09:49:08 -08:00
|
|
|
import kotlinx.coroutines.runBlocking
|
|
|
|
import kotlin.math.roundToInt
|
|
|
|
|
2023-06-18 23:59:00 -07:00
|
|
|
@Preview("Receive")
|
2022-01-13 09:49:08 -08:00
|
|
|
@Composable
|
2023-06-18 23:59:00 -07:00
|
|
|
private fun ComposablePreview() {
|
2023-10-19 06:00:47 -07:00
|
|
|
ZcashTheme(forceDarkMode = false) {
|
2022-01-13 09:49:08 -08:00
|
|
|
GradientSurface {
|
2023-02-28 05:54:07 -08:00
|
|
|
Receive(
|
2024-01-15 08:32:15 -08:00
|
|
|
walletAddress = runBlocking { WalletAddressesFixture.new() },
|
|
|
|
snackbarHostState = SnackbarHostState(),
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings = {},
|
2023-12-07 07:35:27 -08:00
|
|
|
onAdjustBrightness = {},
|
2024-01-15 08:32:15 -08:00
|
|
|
onAddrCopyToClipboard = {},
|
|
|
|
onQrImageShare = {},
|
|
|
|
versionInfo = VersionInfoFixture.new()
|
2022-01-13 09:49:08 -08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
@Suppress("LongParameterList")
|
2022-01-13 09:49:08 -08:00
|
|
|
@Composable
|
2023-02-28 05:54:07 -08:00
|
|
|
fun Receive(
|
2024-01-15 08:32:15 -08:00
|
|
|
walletAddress: WalletAddresses?,
|
|
|
|
snackbarHostState: SnackbarHostState,
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings: () -> Unit,
|
2023-12-07 07:35:27 -08:00
|
|
|
onAdjustBrightness: (Boolean) -> Unit,
|
2024-01-15 08:32:15 -08:00
|
|
|
onAddrCopyToClipboard: (String) -> Unit,
|
|
|
|
onQrImageShare: (ImageBitmap) -> Unit,
|
|
|
|
versionInfo: VersionInfo,
|
2022-01-13 09:49:08 -08:00
|
|
|
) {
|
2023-12-07 07:35:27 -08:00
|
|
|
val (brightness, setBrightness) = rememberSaveable { mutableStateOf(false) }
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
Scaffold(
|
|
|
|
topBar = {
|
|
|
|
ReceiveTopAppBar(
|
|
|
|
adjustBrightness = brightness,
|
|
|
|
onSettings = onSettings,
|
|
|
|
onBrightness = {
|
|
|
|
onAdjustBrightness(!brightness)
|
|
|
|
setBrightness(!brightness)
|
|
|
|
},
|
|
|
|
versionInfo = versionInfo,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
snackbarHost = { SnackbarHost(snackbarHostState) },
|
|
|
|
) { paddingValues ->
|
|
|
|
if (null == walletAddress) {
|
|
|
|
CircularScreenProgressIndicator()
|
|
|
|
} else {
|
|
|
|
ReceiveContents(
|
|
|
|
walletAddress = walletAddress,
|
|
|
|
onAddressCopyToClipboard = onAddrCopyToClipboard,
|
|
|
|
onQrImageShare = onQrImageShare,
|
|
|
|
adjustBrightness = brightness,
|
|
|
|
versionInfo = versionInfo,
|
|
|
|
modifier =
|
|
|
|
Modifier.padding(
|
|
|
|
top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault,
|
|
|
|
bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault,
|
|
|
|
start = ZcashTheme.dimens.screenHorizontalSpacingRegular,
|
|
|
|
end = ZcashTheme.dimens.screenHorizontalSpacingRegular
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
2022-01-13 09:49:08 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2023-12-07 07:35:27 -08:00
|
|
|
private fun ReceiveTopAppBar(
|
|
|
|
adjustBrightness: Boolean,
|
2023-12-18 05:31:25 -08:00
|
|
|
onSettings: () -> Unit,
|
2024-01-15 08:32:15 -08:00
|
|
|
onBrightness: () -> Unit,
|
|
|
|
versionInfo: VersionInfo
|
2023-12-07 07:35:27 -08:00
|
|
|
) {
|
|
|
|
SmallTopAppBar(
|
|
|
|
titleText = stringResource(id = R.string.receive_title),
|
|
|
|
regularActions = {
|
2024-01-15 08:32:15 -08:00
|
|
|
if (versionInfo.isDebuggable) {
|
|
|
|
IconButton(
|
|
|
|
onClick = onBrightness
|
|
|
|
) {
|
|
|
|
Icon(
|
|
|
|
imageVector =
|
|
|
|
if (adjustBrightness) {
|
|
|
|
Icons.Default.BrightnessLow
|
|
|
|
} else {
|
|
|
|
Icons.Default.BrightnessHigh
|
|
|
|
},
|
|
|
|
contentDescription = stringResource(R.string.receive_brightness_content_description)
|
|
|
|
)
|
|
|
|
}
|
2022-01-13 09:49:08 -08:00
|
|
|
}
|
2023-12-18 05:31:25 -08:00
|
|
|
},
|
|
|
|
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-01-13 09:49:08 -08:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
@Suppress("LongParameterList")
|
2022-01-13 09:49:08 -08:00
|
|
|
@Composable
|
2023-02-28 05:54:07 -08:00
|
|
|
private fun ReceiveContents(
|
2024-01-15 08:32:15 -08:00
|
|
|
walletAddress: WalletAddresses,
|
|
|
|
onAddressCopyToClipboard: (String) -> Unit,
|
|
|
|
onQrImageShare: (ImageBitmap) -> Unit,
|
2023-12-07 07:35:27 -08:00
|
|
|
adjustBrightness: Boolean,
|
2024-01-15 08:32:15 -08:00
|
|
|
versionInfo: VersionInfo,
|
2023-12-07 07:35:27 -08:00
|
|
|
modifier: Modifier = Modifier,
|
2022-01-13 09:49:08 -08:00
|
|
|
) {
|
2023-10-04 07:01:40 -07:00
|
|
|
Column(
|
2023-12-21 07:15:20 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.fillMaxHeight()
|
|
|
|
.verticalScroll(rememberScrollState())
|
|
|
|
.then(modifier),
|
2023-10-04 07:01:40 -07:00
|
|
|
horizontalAlignment = Alignment.CenterHorizontally
|
|
|
|
) {
|
2024-01-15 08:32:15 -08:00
|
|
|
if (adjustBrightness) {
|
|
|
|
BrightenScreen()
|
|
|
|
DisableScreenTimeout()
|
|
|
|
}
|
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
|
|
|
|
|
|
|
Address(
|
|
|
|
walletAddress = walletAddress.unified,
|
|
|
|
onAddressCopyToClipboard = onAddressCopyToClipboard,
|
|
|
|
onQrImageShare = onQrImageShare,
|
|
|
|
)
|
|
|
|
|
|
|
|
if (versionInfo.isTestnet) {
|
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingHuge))
|
|
|
|
|
|
|
|
Address(
|
|
|
|
walletAddress = walletAddress.sapling,
|
|
|
|
onAddressCopyToClipboard = onAddressCopyToClipboard,
|
|
|
|
onQrImageShare = onQrImageShare,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingHuge))
|
|
|
|
|
|
|
|
Address(
|
|
|
|
walletAddress = walletAddress.transparent,
|
|
|
|
onAddressCopyToClipboard = onAddressCopyToClipboard,
|
|
|
|
onQrImageShare = onQrImageShare,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private val DEFAULT_QR_CODE_SIZE = 320.dp
|
|
|
|
|
|
|
|
@Suppress("LongMethod")
|
|
|
|
@Composable
|
|
|
|
private fun Address(
|
|
|
|
walletAddress: WalletAddress,
|
|
|
|
onAddressCopyToClipboard: (String) -> Unit,
|
|
|
|
onQrImageShare: (ImageBitmap) -> Unit,
|
|
|
|
modifier: Modifier = Modifier,
|
|
|
|
) {
|
|
|
|
Column(modifier = modifier) {
|
|
|
|
SubHeader(
|
|
|
|
text =
|
|
|
|
stringResource(
|
|
|
|
id =
|
|
|
|
when (walletAddress) {
|
|
|
|
is WalletAddress.Unified -> R.string.receive_wallet_address_unified
|
|
|
|
is WalletAddress.Sapling -> R.string.receive_wallet_address_sapling
|
|
|
|
is WalletAddress.Transparent -> R.string.receive_wallet_address_transparent
|
|
|
|
}
|
|
|
|
),
|
2023-12-07 07:35:27 -08:00
|
|
|
modifier = Modifier.align(Alignment.CenterHorizontally)
|
|
|
|
)
|
2023-04-04 05:21:18 -07:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
|
|
|
|
|
|
|
val sizePixels = with(LocalDensity.current) { DEFAULT_QR_CODE_SIZE.toPx() }.roundToInt()
|
|
|
|
val qrCodeImage =
|
|
|
|
remember {
|
|
|
|
qrCodeForAddress(
|
|
|
|
address = walletAddress.address,
|
|
|
|
size = sizePixels
|
|
|
|
)
|
|
|
|
}
|
2023-04-04 05:21:18 -07:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
QrCode(
|
|
|
|
qrCodeImage = qrCodeImage,
|
|
|
|
onQrImageBitmapShare = onQrImageShare,
|
|
|
|
contentDescription =
|
|
|
|
stringResource(
|
|
|
|
id =
|
|
|
|
when (walletAddress) {
|
|
|
|
is WalletAddress.Unified -> R.string.receive_unified_content_description
|
|
|
|
is WalletAddress.Sapling -> R.string.receive_sapling_content_description
|
|
|
|
is WalletAddress.Transparent -> R.string.receive_transparent_content_description
|
|
|
|
}
|
|
|
|
),
|
|
|
|
modifier = Modifier.align(Alignment.CenterHorizontally),
|
2023-04-04 05:21:18 -07:00
|
|
|
)
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
2023-04-04 05:21:18 -07:00
|
|
|
|
2022-01-13 09:49:08 -08:00
|
|
|
// TODO [#163]: Ellipsize center of the string
|
2023-11-23 01:00:13 -08:00
|
|
|
// TODO [#163]: https://github.com/Electric-Coin-Company/zashi-android/issues/163
|
2022-01-13 09:49:08 -08:00
|
|
|
Text(
|
|
|
|
text = walletAddress.address,
|
2024-01-15 08:32:15 -08:00
|
|
|
style = ZcashTheme.typography.primary.bodyLarge,
|
|
|
|
color = ZcashTheme.colors.textDescription,
|
|
|
|
textAlign = TextAlign.Center,
|
2023-12-11 01:20:32 -08:00
|
|
|
modifier =
|
|
|
|
Modifier
|
2024-01-15 08:32:15 -08:00
|
|
|
.align(Alignment.CenterHorizontally)
|
|
|
|
.clickable { onAddressCopyToClipboard(walletAddress.address) }
|
|
|
|
.padding(horizontal = ZcashTheme.dimens.spacingLarge)
|
|
|
|
.fillMaxWidth(),
|
2023-04-04 05:21:18 -07:00
|
|
|
)
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
2023-11-23 02:37:02 -08:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
Row(
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
horizontalArrangement = Arrangement.Center
|
|
|
|
) {
|
|
|
|
Reference(
|
|
|
|
text = stringResource(id = R.string.receive_copy),
|
|
|
|
onClick = { onAddressCopyToClipboard(walletAddress.address) },
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
imageVector = ImageVector.vectorResource(R.drawable.copy),
|
|
|
|
imageContentDescription = null,
|
|
|
|
modifier = Modifier.wrapContentSize(),
|
|
|
|
)
|
|
|
|
Reference(
|
|
|
|
text = stringResource(id = R.string.receive_share),
|
|
|
|
onClick = { onQrImageShare(qrCodeImage) },
|
|
|
|
textAlign = TextAlign.Center,
|
|
|
|
imageVector = ImageVector.vectorResource(R.drawable.share),
|
|
|
|
imageContentDescription = null,
|
|
|
|
modifier = Modifier.wrapContentSize(),
|
|
|
|
)
|
|
|
|
}
|
2022-01-13 09:49:08 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
private fun qrCodeForAddress(
|
|
|
|
address: String,
|
|
|
|
size: Int,
|
|
|
|
): ImageBitmap {
|
|
|
|
// In the future, use actual/expect to switch QR code generator implementations for multiplatform
|
2022-01-13 09:49:08 -08:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
// Note that our implementation has an extra array copy to BooleanArray, which is a cross-platform
|
|
|
|
// representation. This should have minimal performance impact since the QR code is relatively
|
|
|
|
// small and we only generate QR codes infrequently.
|
2022-01-13 09:49:08 -08:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
val qrCodePixelArray = JvmQrCodeGenerator.generate(address, size)
|
2022-01-13 09:49:08 -08:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
return AndroidQrCodeImageGenerator.generate(qrCodePixelArray, size)
|
|
|
|
}
|
2022-01-13 09:49:08 -08:00
|
|
|
|
2024-01-15 08:32:15 -08:00
|
|
|
@Composable
|
|
|
|
private fun QrCode(
|
|
|
|
contentDescription: String,
|
|
|
|
qrCodeImage: ImageBitmap,
|
|
|
|
onQrImageBitmapShare: (ImageBitmap) -> Unit,
|
|
|
|
modifier: Modifier = Modifier,
|
|
|
|
) {
|
|
|
|
Image(
|
|
|
|
bitmap = qrCodeImage,
|
|
|
|
contentDescription = contentDescription,
|
|
|
|
modifier =
|
|
|
|
Modifier
|
|
|
|
.clickable { onQrImageBitmapShare(qrCodeImage) }
|
|
|
|
.then(modifier)
|
|
|
|
)
|
2022-01-13 09:49:08 -08:00
|
|
|
}
|