[#1412] Receive Page split into horizontal pager
* ISSUE-1412 Receive Page split into horizontal pager * ISSUE-1412 Code cleanup * ISSUE-1412 Code cleanup * Resolve code analysis warnings * Improve vertical paddings - So the entire screen is scrollable as expected - This also moves us towards the newly updated screen design --------- Co-authored-by: Milan Cerovsky <milan.cerovsky@leeaf.life> Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
parent
0a35c4fffd
commit
4cdb9f3024
|
@ -0,0 +1,129 @@
|
||||||
|
@file:OptIn(ExperimentalFoundationApi::class)
|
||||||
|
|
||||||
|
package co.electriccoin.zcash.ui.design.component
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.pager.PagerState
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
|
import androidx.compose.material3.TabRow
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun PagerTabsPreview() {
|
||||||
|
ZcashTheme(forceDarkMode = false) {
|
||||||
|
BlankSurface {
|
||||||
|
PagerTabs(
|
||||||
|
pagerState = rememberPagerState { 2 },
|
||||||
|
tabs = persistentListOf("First", "Second"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun PagerTabsDarkPreview() {
|
||||||
|
ZcashTheme(forceDarkMode = true) {
|
||||||
|
BlankSurface {
|
||||||
|
PagerTabs(
|
||||||
|
pagerState = rememberPagerState { 2 },
|
||||||
|
tabs = persistentListOf("First", "Second"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PagerTabs(
|
||||||
|
pagerState: PagerState,
|
||||||
|
tabs: ImmutableList<String>,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
coroutineScope: CoroutineScope = rememberCoroutineScope(),
|
||||||
|
onTabSelected: (index: Int) -> Unit = {},
|
||||||
|
) {
|
||||||
|
TabRow(
|
||||||
|
modifier =
|
||||||
|
modifier
|
||||||
|
.padding(horizontal = ZcashTheme.dimens.screenHorizontalSpacingBig)
|
||||||
|
.border(ZcashTheme.dimens.spacingTiny, ZcashTheme.colors.layoutStroke),
|
||||||
|
selectedTabIndex = pagerState.currentPage,
|
||||||
|
divider = {},
|
||||||
|
indicator = {},
|
||||||
|
) {
|
||||||
|
tabs.forEachIndexed { index, tab ->
|
||||||
|
PagerTab(
|
||||||
|
title = tab,
|
||||||
|
selected = pagerState.currentPage == index,
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
onTabSelected(index)
|
||||||
|
pagerState.animateScrollToPage(index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun PagerTab(
|
||||||
|
title: String,
|
||||||
|
selected: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
) {
|
||||||
|
Tab(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
selected = selected,
|
||||||
|
onClick = onClick,
|
||||||
|
selectedContentColor = Color.Transparent,
|
||||||
|
unselectedContentColor = ZcashTheme.colors.layoutStroke
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(
|
||||||
|
if (selected) Color.Transparent else ZcashTheme.colors.layoutStroke
|
||||||
|
)
|
||||||
|
.padding(vertical = ZcashTheme.dimens.spacingMid, horizontal = ZcashTheme.dimens.spacingXtiny),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = ZcashTheme.dimens.spacingXtiny),
|
||||||
|
text = title,
|
||||||
|
color = if (selected) ZcashTheme.colors.textCommon else MaterialTheme.colorScheme.onPrimary,
|
||||||
|
style = ZcashTheme.extendedTypography.restoringTopAppBarStyle,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
maxLines = 2,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,20 @@
|
||||||
package co.electriccoin.zcash.ui.screen.receive.view
|
package co.electriccoin.zcash.ui.screen.receive.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
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.wrapContentSize
|
import androidx.compose.foundation.layout.wrapContentSize
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
@ -19,6 +23,8 @@ import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
@ -44,34 +50,17 @@ import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||||
import co.electriccoin.zcash.ui.common.test.CommonTag
|
import co.electriccoin.zcash.ui.common.test.CommonTag
|
||||||
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
||||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
|
import co.electriccoin.zcash.ui.design.component.PagerTabs
|
||||||
import co.electriccoin.zcash.ui.design.component.Reference
|
import co.electriccoin.zcash.ui.design.component.Reference
|
||||||
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
import co.electriccoin.zcash.ui.design.component.SmallTopAppBar
|
||||||
import co.electriccoin.zcash.ui.design.component.SubHeader
|
|
||||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||||
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
||||||
import co.electriccoin.zcash.ui.screen.receive.util.AndroidQrCodeImageGenerator
|
import co.electriccoin.zcash.ui.screen.receive.util.AndroidQrCodeImageGenerator
|
||||||
import co.electriccoin.zcash.ui.screen.receive.util.JvmQrCodeGenerator
|
import co.electriccoin.zcash.ui.screen.receive.util.JvmQrCodeGenerator
|
||||||
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Preview("Receive")
|
|
||||||
@Composable
|
|
||||||
private fun ComposablePreview() {
|
|
||||||
ZcashTheme(forceDarkMode = false) {
|
|
||||||
Receive(
|
|
||||||
screenBrightnessState = ScreenBrightnessState.NORMAL,
|
|
||||||
walletAddress = runBlocking { WalletAddressesFixture.new() },
|
|
||||||
snackbarHostState = SnackbarHostState(),
|
|
||||||
onSettings = {},
|
|
||||||
onAdjustBrightness = {},
|
|
||||||
onAddrCopyToClipboard = {},
|
|
||||||
onQrImageShare = {},
|
|
||||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
|
||||||
versionInfo = VersionInfoFixture.new(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
fun Receive(
|
fun Receive(
|
||||||
|
@ -102,18 +91,16 @@ fun Receive(
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
ReceiveContents(
|
ReceiveContents(
|
||||||
walletAddress = walletAddress,
|
walletAddresses = walletAddress,
|
||||||
onAddressCopyToClipboard = onAddrCopyToClipboard,
|
onAddressCopyToClipboard = onAddrCopyToClipboard,
|
||||||
onQrImageShare = onQrImageShare,
|
onQrImageShare = onQrImageShare,
|
||||||
screenBrightnessState = screenBrightnessState,
|
screenBrightnessState = screenBrightnessState,
|
||||||
versionInfo = versionInfo,
|
versionInfo = versionInfo,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier.padding(
|
Modifier.padding(
|
||||||
top = paddingValues.calculateTopPadding() + ZcashTheme.dimens.spacingDefault,
|
top = paddingValues.calculateTopPadding()
|
||||||
bottom = paddingValues.calculateBottomPadding() + ZcashTheme.dimens.spacingDefault,
|
// We intentionally do not set the rest paddings, those are set by the underlying composable
|
||||||
start = ZcashTheme.dimens.screenHorizontalSpacingRegular,
|
),
|
||||||
end = ZcashTheme.dimens.screenHorizontalSpacingRegular
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,154 +147,173 @@ private fun ReceiveTopAppBar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@Composable
|
@Composable
|
||||||
private fun ReceiveContents(
|
private fun ReceiveContents(
|
||||||
walletAddress: WalletAddresses,
|
walletAddresses: WalletAddresses,
|
||||||
onAddressCopyToClipboard: (String) -> Unit,
|
onAddressCopyToClipboard: (String) -> Unit,
|
||||||
onQrImageShare: (ImageBitmap) -> Unit,
|
onQrImageShare: (ImageBitmap) -> Unit,
|
||||||
screenBrightnessState: ScreenBrightnessState,
|
screenBrightnessState: ScreenBrightnessState,
|
||||||
versionInfo: VersionInfo,
|
versionInfo: VersionInfo,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(
|
if (screenBrightnessState == ScreenBrightnessState.FULL) {
|
||||||
modifier =
|
BrightenScreen()
|
||||||
Modifier
|
DisableScreenTimeout()
|
||||||
.fillMaxHeight()
|
}
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
.then(modifier),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
if (screenBrightnessState == ScreenBrightnessState.FULL) {
|
|
||||||
BrightenScreen()
|
|
||||||
DisableScreenTimeout()
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
val state by remember {
|
||||||
|
derivedStateOf {
|
||||||
Address(
|
listOfNotNull(
|
||||||
walletAddress = walletAddress.unified,
|
walletAddresses.unified,
|
||||||
onAddressCopyToClipboard = onAddressCopyToClipboard,
|
walletAddresses.transparent,
|
||||||
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
|
val pagerState = rememberPagerState { state.size }
|
||||||
|
|
||||||
@Suppress("LongMethod")
|
Column(
|
||||||
@Composable
|
modifier = modifier,
|
||||||
private fun Address(
|
) {
|
||||||
walletAddress: WalletAddress,
|
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault))
|
||||||
onAddressCopyToClipboard: (String) -> Unit,
|
|
||||||
onQrImageShare: (ImageBitmap) -> Unit,
|
PagerTabs(
|
||||||
modifier: Modifier = Modifier,
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) {
|
pagerState = pagerState,
|
||||||
Column(modifier = modifier) {
|
tabs =
|
||||||
SubHeader(
|
state.map {
|
||||||
text =
|
stringResource(
|
||||||
stringResource(
|
when (it) {
|
||||||
id =
|
|
||||||
when (walletAddress) {
|
|
||||||
is WalletAddress.Unified -> R.string.receive_wallet_address_unified
|
is WalletAddress.Unified -> R.string.receive_wallet_address_unified
|
||||||
is WalletAddress.Sapling -> R.string.receive_wallet_address_sapling
|
is WalletAddress.Sapling -> R.string.receive_wallet_address_sapling
|
||||||
is WalletAddress.Transparent -> R.string.receive_wallet_address_transparent
|
is WalletAddress.Transparent -> R.string.receive_wallet_address_transparent
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
}.toPersistentList(),
|
||||||
)
|
)
|
||||||
|
HorizontalPager(
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
state = pagerState,
|
||||||
val sizePixels = with(LocalDensity.current) { DEFAULT_QR_CODE_SIZE.toPx() }.roundToInt()
|
userScrollEnabled = false
|
||||||
val qrCodeImage =
|
) { index ->
|
||||||
remember {
|
AddressPage(
|
||||||
qrCodeForAddress(
|
walletAddresses = walletAddresses,
|
||||||
address = walletAddress.address,
|
modifier = Modifier.fillMaxSize(),
|
||||||
size = sizePixels
|
walletAddress = state[index],
|
||||||
)
|
versionInfo = versionInfo,
|
||||||
}
|
onAddressCopyToClipboard = onAddressCopyToClipboard,
|
||||||
|
onQrImageShare = onQrImageShare,
|
||||||
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),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = walletAddress.address,
|
|
||||||
style = ZcashTheme.extendedTypography.addressStyle,
|
|
||||||
color = ZcashTheme.colors.textDescription,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.align(Alignment.CenterHorizontally)
|
|
||||||
.clickable { onAddressCopyToClipboard(walletAddress.address) }
|
|
||||||
.padding(horizontal = ZcashTheme.dimens.spacingLarge)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
|
||||||
|
|
||||||
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()
|
|
||||||
.padding(all = ZcashTheme.dimens.spacingDefault),
|
|
||||||
)
|
|
||||||
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()
|
|
||||||
.padding(all = ZcashTheme.dimens.spacingDefault),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("LongMethod", "LongParameterList")
|
||||||
|
@Composable
|
||||||
|
private fun AddressPage(
|
||||||
|
walletAddresses: WalletAddresses,
|
||||||
|
walletAddress: WalletAddress,
|
||||||
|
versionInfo: VersionInfo,
|
||||||
|
onAddressCopyToClipboard: (String) -> Unit,
|
||||||
|
onQrImageShare: (ImageBitmap) -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
modifier
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(
|
||||||
|
horizontal = ZcashTheme.dimens.screenHorizontalSpacingRegular,
|
||||||
|
vertical = ZcashTheme.dimens.spacingDefault,
|
||||||
|
),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
QrCode(walletAddress, onAddressCopyToClipboard, onQrImageShare)
|
||||||
|
|
||||||
|
if (versionInfo.isTestnet && walletAddress is WalletAddress.Unified) {
|
||||||
|
QrCode(walletAddresses.sapling, onAddressCopyToClipboard, onQrImageShare)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Suppress("LongMethod")
|
||||||
|
private fun ColumnScope.QrCode(
|
||||||
|
walletAddress: WalletAddress,
|
||||||
|
onAddressCopyToClipboard: (String) -> Unit,
|
||||||
|
onQrImageShare: (ImageBitmap) -> Unit,
|
||||||
|
) {
|
||||||
|
val sizePixels = with(LocalDensity.current) { DEFAULT_QR_CODE_SIZE.toPx() }.roundToInt()
|
||||||
|
val qrCodeImage =
|
||||||
|
remember {
|
||||||
|
qrCodeForAddress(
|
||||||
|
address = walletAddress.address,
|
||||||
|
size = sizePixels
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
QrCode(
|
||||||
|
qrCodeImage = qrCodeImage,
|
||||||
|
onQrImageBitmapShare = onQrImageShare,
|
||||||
|
contentDescription =
|
||||||
|
stringResource(
|
||||||
|
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),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = walletAddress.address,
|
||||||
|
style = ZcashTheme.extendedTypography.addressStyle,
|
||||||
|
color = ZcashTheme.colors.textDescription,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.clickable { onAddressCopyToClipboard(walletAddress.address) }
|
||||||
|
.padding(horizontal = ZcashTheme.dimens.spacingLarge)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingSmall))
|
||||||
|
|
||||||
|
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()
|
||||||
|
.padding(all = ZcashTheme.dimens.spacingDefault),
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
.padding(all = ZcashTheme.dimens.spacingDefault),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun qrCodeForAddress(
|
private fun qrCodeForAddress(
|
||||||
address: String,
|
address: String,
|
||||||
size: Int,
|
size: Int,
|
||||||
|
@ -339,3 +345,22 @@ private fun QrCode(
|
||||||
.then(modifier)
|
.then(modifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun ComposablePreview() =
|
||||||
|
ZcashTheme(forceDarkMode = false) {
|
||||||
|
Receive(
|
||||||
|
screenBrightnessState = ScreenBrightnessState.NORMAL,
|
||||||
|
walletAddress = runBlocking { WalletAddressesFixture.new() },
|
||||||
|
snackbarHostState = SnackbarHostState(),
|
||||||
|
onSettings = {},
|
||||||
|
onAdjustBrightness = {},
|
||||||
|
onAddrCopyToClipboard = {},
|
||||||
|
onQrImageShare = {},
|
||||||
|
versionInfo = VersionInfoFixture.new(),
|
||||||
|
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val DEFAULT_QR_CODE_SIZE = 320.dp
|
||||||
|
|
Loading…
Reference in New Issue