Updated on 2026-08-14
This commit is contained in:
parent
34ee61553d
commit
aecd523c70
25 changed files with 1720 additions and 935 deletions
|
|
@ -11,10 +11,12 @@ import com.tangem.core.decompose.context.childByContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.decompose.navigation.inner.InnerRouter
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
import com.tangem.features.tokenreceive.model.TokenReceiveModel
|
||||
import com.tangem.features.tokenreceive.route.TokenReceiveRoutes
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveContentSheet
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveContentSheetLegacy
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -43,13 +45,21 @@ internal class DefaultTokenReceiveComponent @AssistedInject constructor(
|
|||
override fun BottomSheet() {
|
||||
val content by contentStack.subscribeAsState()
|
||||
val currentRoute = content.active.configuration
|
||||
|
||||
TokenReceiveContentSheet(
|
||||
route = currentRoute,
|
||||
onCloseClick = ::dismiss,
|
||||
onBackClick = ::onChildBack,
|
||||
contentStack = content,
|
||||
)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TokenReceiveContentSheet(
|
||||
route = currentRoute,
|
||||
onCloseClick = ::dismiss,
|
||||
onBackClick = ::onChildBack,
|
||||
contentStack = content,
|
||||
)
|
||||
} else {
|
||||
TokenReceiveContentSheetLegacy(
|
||||
route = currentRoute,
|
||||
onCloseClick = ::dismiss,
|
||||
onBackClick = ::onChildBack,
|
||||
contentStack = content,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dismiss() = model.params.onDismiss()
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.model.TokenReceiveAssetsModel
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveAssetsContent
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveAssetsContentLegacy
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
internal class TokenReceiveAssetsComponent(
|
||||
|
|
@ -25,7 +27,11 @@ internal class TokenReceiveAssetsComponent(
|
|||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
TokenReceiveAssetsContent(assetsUM = state)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TokenReceiveAssetsContent(assetsUM = state)
|
||||
} else {
|
||||
TokenReceiveAssetsContentLegacy(assetsUM = state)
|
||||
}
|
||||
}
|
||||
|
||||
internal interface TokenReceiveAssetsModelCallback {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.domain.models.TokenReceiveType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveCopyActionSource
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.model.TokenReceiveQrCodeModel
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveQrCodeContent
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveQrCodeContentLegacy
|
||||
|
||||
internal class TokenReceiveQrCodeComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
|
|
@ -24,7 +26,11 @@ internal class TokenReceiveQrCodeComponent(
|
|||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
TokenReceiveQrCodeContent(qrCodeUM = state)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TokenReceiveQrCodeContent(qrCodeUM = state)
|
||||
} else {
|
||||
TokenReceiveQrCodeContentLegacy(qrCodeUM = state)
|
||||
}
|
||||
}
|
||||
|
||||
internal interface TokenReceiveQrCodeModelCallback {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ import com.tangem.core.decompose.context.AppComponentContext
|
|||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.features.tokenreceive.model.TokenReceiveWarningModel
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveWarningContent
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveWarningContentLegacy
|
||||
|
||||
internal class TokenReceiveWarningComponent(
|
||||
appComponentContext: AppComponentContext,
|
||||
|
|
@ -22,7 +24,11 @@ internal class TokenReceiveWarningComponent(
|
|||
@Composable
|
||||
override fun Content(modifier: Modifier) {
|
||||
val state by model.state.collectAsStateWithLifecycle()
|
||||
TokenReceiveWarningContent(warningUM = state)
|
||||
if (LocalRedesignEnabled.current) {
|
||||
TokenReceiveWarningContent(warningUM = state)
|
||||
} else {
|
||||
TokenReceiveWarningContentLegacy(warningUM = state)
|
||||
}
|
||||
}
|
||||
|
||||
internal interface TokenReceiveWarningModelCallback {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ internal data class ReceiveAddress(
|
|||
sealed interface Type {
|
||||
data object Ens : Type
|
||||
|
||||
@Immutable
|
||||
sealed interface Primary : Type {
|
||||
|
||||
val displayName: TextReference
|
||||
|
|
|
|||
|
|
@ -1,97 +1,379 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.TextAutoSize
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.util.fastFilter
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionBaseButton
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonContent
|
||||
import com.tangem.core.ui.components.buttons.small.TangemIconButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.SpacerW
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.ds.TangemPagerIndicator
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.message.TangemMessage
|
||||
import com.tangem.core.ui.ds2.badge.TangemBadge
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoader
|
||||
import com.tangem.core.ui.ds2.loader.TangemLoaderSize
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.LocalTopSnackbarHostState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_copy_24
|
||||
import com.tangem.core.ui.res.generated.icons.ic_share_android_24
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.ui.state.ReceiveAssetsUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) {
|
||||
val snackbarHostState = remember(::SnackbarHostState)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
if (assetsUM.isEnsResultLoading) {
|
||||
LoadingBlock(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(bottom = 8.dp),
|
||||
)
|
||||
}
|
||||
AddressBlock(assetsUM = assetsUM)
|
||||
SpacerH(16.dp)
|
||||
Info(
|
||||
showMemoDisclaimer = assetsUM.showMemoDisclaimer,
|
||||
notificationConfigs = assetsUM.notificationConfigs,
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ContainerWithSnackbarHost(snackbarHostState = snackbarHostState) {
|
||||
Column(
|
||||
@Composable
|
||||
private fun LoadingBlock(modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors3.bg.opaque.primary),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(bottom = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
.heightIn(min = 68.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
AddressBlock(
|
||||
assetsUM = assetsUM,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
|
||||
if (assetsUM.isEnsResultLoading) {
|
||||
SpacerH8()
|
||||
LoadingBlock(modifier = Modifier.padding(horizontal = 16.dp))
|
||||
}
|
||||
|
||||
SpacerH12()
|
||||
|
||||
Info(
|
||||
showMemoDisclaimer = assetsUM.showMemoDisclaimer,
|
||||
notificationConfigs = assetsUM.notificationConfigs,
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
TangemLoader(
|
||||
color = TangemTheme.colors3.icon.secondary,
|
||||
size = TangemLoaderSize.X28,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddressBlock(assetsUM: ReceiveAssetsUM) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
assetsUM.addresses
|
||||
.fastFilter { it.type is ReceiveAddress.Type.Ens }
|
||||
.fastForEach { address ->
|
||||
key(address.value) {
|
||||
EnsItem(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
onCopyClick = {
|
||||
assetsUM.onCopyClick(address)
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
address = address.value,
|
||||
)
|
||||
SpacerH8()
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryAddressesItems(
|
||||
addresses = assetsUM.addresses.fastFilter { it.type is ReceiveAddress.Type.Primary }.toImmutableList(),
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
onShareClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onShareClick(it)
|
||||
},
|
||||
onCopyClick = { address ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(message = resourceReference(R.string.wallet_notification_address_copied)),
|
||||
)
|
||||
}
|
||||
assetsUM.onCopyClick(address)
|
||||
},
|
||||
onOpenQrCodeClick = { address ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onOpenQrCodeClick(address)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun PrimaryAddressesItems(
|
||||
addresses: ImmutableList<ReceiveAddress>,
|
||||
currencyIconState: CurrencyIconState,
|
||||
onShareClick: (String) -> Unit,
|
||||
onCopyClick: (ReceiveAddress) -> Unit,
|
||||
onOpenQrCodeClick: (String) -> Unit,
|
||||
) {
|
||||
if (addresses.isEmpty()) return
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = 0,
|
||||
initialPageOffsetFraction = 0f,
|
||||
pageCount = addresses::count,
|
||||
)
|
||||
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
pageSpacing = 16.dp,
|
||||
) { page ->
|
||||
val address = addresses[page]
|
||||
AddressItem(
|
||||
currencyIconState = currencyIconState,
|
||||
onOpenQrCodeClick = { onOpenQrCodeClick(address.value) },
|
||||
onCopyClick = { onCopyClick(address) },
|
||||
onShareClick = { onShareClick(address.value) },
|
||||
primaryType = address.type as ReceiveAddress.Type.Primary,
|
||||
address = address.value,
|
||||
isDynamicAddress = address.type is ReceiveAddress.Type.Primary.Dynamic,
|
||||
)
|
||||
}
|
||||
SpacerH(8.dp)
|
||||
if (addresses.size > 1) {
|
||||
TangemPagerIndicator(pagerState = pagerState)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun AddressItem(
|
||||
currencyIconState: CurrencyIconState,
|
||||
onOpenQrCodeClick: () -> Unit,
|
||||
onCopyClick: () -> Unit,
|
||||
onShareClick: () -> Unit,
|
||||
primaryType: ReceiveAddress.Type.Primary,
|
||||
address: String,
|
||||
isDynamicAddress: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clickableSingle(onClick = onOpenQrCodeClick)
|
||||
.padding(horizontal = 12.dp, vertical = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier.size(60.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = true,
|
||||
iconSize = 56.dp,
|
||||
networkBadgeSize = 20.dp,
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
|
||||
if (isDynamicAddress) {
|
||||
DynamicAddressBadge(modifier = Modifier.padding(vertical = 4.dp))
|
||||
SpacerH(12.dp)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = primaryType.displayName.resolveReference(),
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
SpacerH(4.dp)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.heightIn(min = 40.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
text = address,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
SpacerH(8.dp)
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickableSingle(onClick = onOpenQrCodeClick)
|
||||
.padding(10.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_qrcode_new_24),
|
||||
tint = TangemTheme.colors3.icon.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SpacerW(6.dp)
|
||||
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.token_receive_show_qr_code_title),
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(20.dp)
|
||||
|
||||
ButtonsBlock(
|
||||
onCopyClick = onCopyClick,
|
||||
onShareClick = onShareClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ButtonsBlock(onCopyClick: () -> Unit, onShareClick: () -> Unit) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = Modifier.width(IntrinsicSize.Min),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
TangemButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
onCopyClick()
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_copy_24),
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
size = TangemButton.Size.X12,
|
||||
text = TextReference.Res(id = R.string.common_copy),
|
||||
)
|
||||
|
||||
TangemButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onShareClick()
|
||||
},
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_share_android_24),
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
size = TangemButton.Size.X12,
|
||||
text = TextReference.Res(id = R.string.common_share),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EnsItem(onCopyClick: () -> Unit, address: String, modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors3.bg.opaque.primary),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(36.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_ens_36),
|
||||
contentDescription = null,
|
||||
)
|
||||
SpacerW(12.dp)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = address,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
overflow = TextOverflow.MiddleEllipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
|
||||
TangemButton(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
onClick = onCopyClick,
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_share_android_24),
|
||||
size = TangemButton.Size.X9,
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DynamicAddressBadge(modifier: Modifier = Modifier) {
|
||||
TangemBadge(
|
||||
modifier = modifier,
|
||||
text = resourceReference(R.string.dynamic_addresses_receive_badge),
|
||||
iconStart = TangemIconUM.Icon(iconRes = R.drawable.ic_dynamic_addresses_badge_16),
|
||||
status = TangemBadge.Status.Info,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Info(
|
||||
currencyIconState: CurrencyIconState,
|
||||
|
|
@ -110,227 +392,52 @@ private fun Info(
|
|||
.padding(horizontal = 18.dp)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.receive_bottom_sheet_no_memo_required_message),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
color = TangemTheme.colors3.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
notificationConfigs.fastForEach { notificationConfig ->
|
||||
key(notificationConfig.hashCode()) {
|
||||
// TODO remove after new design system
|
||||
if (notificationConfig is NotificationUM.Warning.YieldSupplyIsActive) {
|
||||
YieldSupplyDepositedWarning(
|
||||
currencyIconState = currencyIconState,
|
||||
title = stringResourceSafe(
|
||||
R.string.yield_module_balance_info_sheet_title,
|
||||
notificationConfig.tokenName,
|
||||
TangemMessage(
|
||||
title = resourceReference(
|
||||
id = R.string.yield_module_balance_info_sheet_title,
|
||||
formatArgs = wrappedList(notificationConfig.tokenName),
|
||||
),
|
||||
subtitle = stringResourceSafe(R.string.yield_module_balance_info_sheet_subtitle),
|
||||
)
|
||||
} else {
|
||||
Notification(config = notificationConfig.config)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun YieldSupplyDepositedWarning(
|
||||
currencyIconState: CurrencyIconState,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size44)
|
||||
.fillMaxWidth(),
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
color = TangemTheme.colors.button.disabled,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(22.dp)
|
||||
.width(22.dp),
|
||||
contentAlignment = Alignment.TopStart,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.size(13.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = false,
|
||||
iconSize = 13.dp,
|
||||
)
|
||||
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary, RoundedCornerShape(15.dp))
|
||||
.padding(1.dp)
|
||||
.size(15.dp)
|
||||
.align(Alignment.BottomEnd),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.img_aave_22),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerW(width = TangemTheme.dimens.spacing8)
|
||||
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = title,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
|
||||
SpacerH(height = TangemTheme.dimens.spacing2)
|
||||
|
||||
Text(
|
||||
text = subtitle,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddressBlock(assetsUM: ReceiveAssetsUM, snackbarHostState: SnackbarHostState) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
assetsUM.addresses
|
||||
.fastFilter { it.type is ReceiveAddress.Type.Ens }
|
||||
.fastForEach { address ->
|
||||
key(address.value) {
|
||||
EnsItem(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
onCopyClick = {
|
||||
assetsUM.onCopyClick(address)
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
subtitle = resourceReference(R.string.yield_module_balance_info_sheet_subtitle),
|
||||
leadingContent = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(22.dp)
|
||||
.width(22.dp),
|
||||
contentAlignment = Alignment.TopStart,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.size(13.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = false,
|
||||
iconSize = 13.dp,
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(
|
||||
R.string.wallet_notification_address_copied,
|
||||
),
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary, RoundedCornerShape(15.dp))
|
||||
.padding(1.dp)
|
||||
.size(15.dp)
|
||||
.align(Alignment.BottomEnd),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.img_aave_22),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
address = address.value,
|
||||
)
|
||||
SpacerH8()
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryAddressesItems(
|
||||
addresses = assetsUM.addresses.fastFilter { it.type is ReceiveAddress.Type.Primary }.toImmutableList(),
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
snackbarHostState = snackbarHostState,
|
||||
onShareClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onShareClick(it)
|
||||
},
|
||||
onCopyClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(
|
||||
R.string.wallet_notification_address_copied,
|
||||
),
|
||||
)
|
||||
}
|
||||
assetsUM.onCopyClick(it)
|
||||
},
|
||||
onOpenQrCodeClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onOpenQrCodeClick(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun PrimaryAddressesItems(
|
||||
addresses: ImmutableList<ReceiveAddress>,
|
||||
currencyIconState: CurrencyIconState,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
onShareClick: (String) -> Unit,
|
||||
onCopyClick: (ReceiveAddress) -> Unit,
|
||||
onOpenQrCodeClick: (String) -> Unit,
|
||||
) {
|
||||
if (addresses.isEmpty()) return
|
||||
var selectedAddress by remember { mutableStateOf(addresses.first()) }
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = 0,
|
||||
initialPageOffsetFraction = 0f,
|
||||
pageCount = addresses::count,
|
||||
)
|
||||
LaunchedEffect(key1 = pagerState.currentPage) {
|
||||
selectedAddress = addresses[pagerState.currentPage]
|
||||
}
|
||||
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
pageSpacing = 16.dp,
|
||||
) {
|
||||
AddressItem(
|
||||
currencyIconState = currencyIconState,
|
||||
onOpenQrCodeClick = { onOpenQrCodeClick(selectedAddress.value) },
|
||||
onCopyClick = { onCopyClick(selectedAddress) },
|
||||
onShareClick = { onShareClick(selectedAddress.value) },
|
||||
primaryType = selectedAddress.type as ReceiveAddress.Type.Primary,
|
||||
address = selectedAddress.value,
|
||||
isDynamicAddress = selectedAddress.type is ReceiveAddress.Type.Primary.Dynamic,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(4.dp)
|
||||
|
||||
if (pagerState.pageCount > 1) {
|
||||
val indicatorState = rememberLazyListState()
|
||||
val selectedColor = TangemTheme.colors.icon.primary1
|
||||
val unselectedColor = TangemTheme.colors.icon.informative
|
||||
|
||||
LazyRow(
|
||||
modifier = Modifier.height(20.dp),
|
||||
state = indicatorState,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
repeat(pagerState.pageCount) { iteration ->
|
||||
item(key = iteration) {
|
||||
val color by animateColorAsState(
|
||||
targetValue = if (pagerState.currentPage == iteration) selectedColor else unselectedColor,
|
||||
label = "",
|
||||
},
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp, vertical = 6.dp)
|
||||
.background(color = color, shape = CircleShape)
|
||||
.size(7.dp),
|
||||
} else {
|
||||
TangemMessage(
|
||||
config = notificationConfig.config,
|
||||
contentColor = Color.Transparent,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -338,308 +445,13 @@ private fun PrimaryAddressesItems(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun AddressItem(
|
||||
currencyIconState: CurrencyIconState,
|
||||
onOpenQrCodeClick: () -> Unit,
|
||||
onCopyClick: () -> Unit,
|
||||
onShareClick: () -> Unit,
|
||||
primaryType: ReceiveAddress.Type.Primary,
|
||||
address: String,
|
||||
isDynamicAddress: Boolean,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
onClick = onOpenQrCodeClick,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier.size(56.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = true,
|
||||
iconSize = 56.dp,
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
|
||||
if (isDynamicAddress) {
|
||||
DynamicAddressBadge()
|
||||
SpacerH(8.dp)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = primaryType.displayName.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.heightIn(min = 40.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
text = address,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
SpacerH8()
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable(onClick = onOpenQrCodeClick)
|
||||
.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_qrcode_new_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SpacerW(4.dp)
|
||||
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.token_receive_show_qr_code_title),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(20.dp)
|
||||
|
||||
ButtonsBlock(
|
||||
snackbarHostState = snackbarHostState,
|
||||
onCopyClick = onCopyClick,
|
||||
onShareClick = onShareClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ButtonsBlock(snackbarHostState: SnackbarHostState, onCopyClick: () -> Unit, onShareClick: () -> Unit) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = Modifier.width(IntrinsicSize.Min),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
ActionButtonWithResizableText(
|
||||
modifier = Modifier.weight(1f),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_copy),
|
||||
iconResId = R.drawable.ic_copy_new_24,
|
||||
onClick = {
|
||||
onCopyClick()
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(R.string.wallet_notification_address_copied),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ActionButtonWithResizableText(
|
||||
modifier = Modifier.weight(1f),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onShareClick()
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EnsItem(onCopyClick: () -> Unit, address: String, modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 14.dp, horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(36.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_ens_36),
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SpacerW12()
|
||||
|
||||
EllipsisText(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = address,
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
)
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_share_24,
|
||||
innerPadding = 6.dp,
|
||||
onClick = onCopyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingBlock(modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 64.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = TangemTheme.colors.icon.informative,
|
||||
modifier = Modifier.padding(TangemTheme.dimens.spacing8),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ActionButtonWithResizableText(config: ActionButtonConfig, modifier: Modifier = Modifier) {
|
||||
ActionBaseButton(
|
||||
config = config,
|
||||
shape = RoundedCornerShape(size = TangemTheme.dimens.radius24),
|
||||
content = { contentModifier ->
|
||||
ActionButtonContent(
|
||||
config = config,
|
||||
text = { color ->
|
||||
Text(
|
||||
text = config.text.resolveReference(),
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = 10.sp,
|
||||
maxFontSize = TangemTheme.typography.button.fontSize,
|
||||
),
|
||||
color = color,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
},
|
||||
modifier = contentModifier.padding(horizontal = 16.dp),
|
||||
paddingBetweenIconAndText = 4.dp,
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
color = TangemTheme.colors.button.secondary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DynamicAddressBadge(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
|
||||
shape = RoundedCornerShape(percent = 50),
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(
|
||||
id = R.drawable.ic_dynamic_addresses_badge_16,
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.dynamic_addresses_receive_badge),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_TokenReceiveAssetsContent(
|
||||
@PreviewParameter(TokenReceiveAssetsContentProvider::class) params: ReceiveAssetsUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TangemThemePreviewRedesign {
|
||||
TokenReceiveAssetsContent(assetsUM = params)
|
||||
}
|
||||
}
|
||||
|
||||
private class TokenReceiveAssetsContentProvider : PreviewParameterProvider<ReceiveAssetsUM> {
|
||||
val address = ReceiveAddress(
|
||||
value = "0xe5178c7d4d0e861ed2e9414e045b501226b0de8d",
|
||||
type = ReceiveAddress.Type.Primary.Default(
|
||||
displayName = stringReference("Etherium address"),
|
||||
),
|
||||
)
|
||||
private val config = ReceiveAssetsUM(
|
||||
notificationConfigs =
|
||||
persistentListOf(
|
||||
NotificationUM.Warning(
|
||||
title = stringReference("Send only XLM on the Ethereum network"),
|
||||
subtitle = resourceReference(R.string.receive_bottom_sheet_warning_message_description),
|
||||
),
|
||||
),
|
||||
addresses = persistentListOf(
|
||||
address,
|
||||
address,
|
||||
address.copy(type = ReceiveAddress.Type.Ens, value = "papasha.eth"),
|
||||
),
|
||||
showMemoDisclaimer = false,
|
||||
onCopyClick = {},
|
||||
onOpenQrCodeClick = {},
|
||||
isEnsResultLoading = true,
|
||||
network = "USDT",
|
||||
currencyIconState = CurrencyIconState.Locked,
|
||||
onShareClick = {},
|
||||
)
|
||||
|
||||
override val values: Sequence<ReceiveAssetsUM>
|
||||
get() = sequenceOf(config)
|
||||
}
|
||||
|
|
@ -0,0 +1,672 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.TextAutoSize
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.util.fastFilter
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.atoms.text.EllipsisText
|
||||
import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionBaseButton
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonContent
|
||||
import com.tangem.core.ui.components.buttons.small.TangemIconButton
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.res.*
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.ui.state.ReceiveAssetsUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveAssetsContentLegacy(assetsUM: ReceiveAssetsUM) {
|
||||
val snackbarHostState = remember(::SnackbarHostState)
|
||||
|
||||
ContainerWithSnackbarHost(snackbarHostState = snackbarHostState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(bottom = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
AddressBlock(
|
||||
assetsUM = assetsUM,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
|
||||
if (assetsUM.isEnsResultLoading) {
|
||||
SpacerH8()
|
||||
LoadingBlock(modifier = Modifier.padding(horizontal = 16.dp))
|
||||
}
|
||||
|
||||
SpacerH12()
|
||||
|
||||
Info(
|
||||
showMemoDisclaimer = assetsUM.showMemoDisclaimer,
|
||||
notificationConfigs = assetsUM.notificationConfigs,
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Info(
|
||||
currencyIconState: CurrencyIconState,
|
||||
notificationConfigs: ImmutableList<NotificationUM>,
|
||||
showMemoDisclaimer: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(space = 16.dp),
|
||||
) {
|
||||
if (showMemoDisclaimer) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 18.dp)
|
||||
.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.receive_bottom_sheet_no_memo_required_message),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
notificationConfigs.fastForEach { notificationConfig ->
|
||||
key(notificationConfig.hashCode()) {
|
||||
if (notificationConfig is NotificationUM.Warning.YieldSupplyIsActive) {
|
||||
YieldSupplyDepositedWarning(
|
||||
currencyIconState = currencyIconState,
|
||||
title = stringResourceSafe(
|
||||
R.string.yield_module_balance_info_sheet_title,
|
||||
notificationConfig.tokenName,
|
||||
),
|
||||
subtitle = stringResourceSafe(R.string.yield_module_balance_info_sheet_subtitle),
|
||||
)
|
||||
} else {
|
||||
Notification(config = notificationConfig.config)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun YieldSupplyDepositedWarning(
|
||||
currencyIconState: CurrencyIconState,
|
||||
title: String,
|
||||
subtitle: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.defaultMinSize(minHeight = TangemTheme.dimens.size44)
|
||||
.fillMaxWidth(),
|
||||
shape = TangemTheme.shapes.roundedCornersXMedium,
|
||||
color = TangemTheme.colors.button.disabled,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(all = TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(22.dp)
|
||||
.width(22.dp),
|
||||
contentAlignment = Alignment.TopStart,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.size(13.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = false,
|
||||
iconSize = 13.dp,
|
||||
)
|
||||
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.tertiary, RoundedCornerShape(15.dp))
|
||||
.padding(1.dp)
|
||||
.size(15.dp)
|
||||
.align(Alignment.BottomEnd),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.img_aave_22),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerW(width = TangemTheme.dimens.spacing8)
|
||||
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = title,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
|
||||
SpacerH(height = TangemTheme.dimens.spacing2)
|
||||
|
||||
Text(
|
||||
text = subtitle,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddressBlock(assetsUM: ReceiveAssetsUM, snackbarHostState: SnackbarHostState) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
assetsUM.addresses
|
||||
.fastFilter { it.type is ReceiveAddress.Type.Ens }
|
||||
.fastForEach { address ->
|
||||
key(address.value) {
|
||||
EnsItem(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
onCopyClick = {
|
||||
assetsUM.onCopyClick(address)
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(
|
||||
R.string.wallet_notification_address_copied,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
address = address.value,
|
||||
)
|
||||
SpacerH8()
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryAddressesItems(
|
||||
addresses = assetsUM.addresses.fastFilter { it.type is ReceiveAddress.Type.Primary }.toImmutableList(),
|
||||
currencyIconState = assetsUM.currencyIconState,
|
||||
snackbarHostState = snackbarHostState,
|
||||
onShareClick = { address ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onShareClick(address)
|
||||
},
|
||||
onCopyClick = { address ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(
|
||||
R.string.wallet_notification_address_copied,
|
||||
),
|
||||
)
|
||||
}
|
||||
assetsUM.onCopyClick(address)
|
||||
},
|
||||
onOpenQrCodeClick = { address ->
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
assetsUM.onOpenQrCodeClick(address)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun PrimaryAddressesItems(
|
||||
addresses: ImmutableList<ReceiveAddress>,
|
||||
currencyIconState: CurrencyIconState,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
onShareClick: (String) -> Unit,
|
||||
onCopyClick: (ReceiveAddress) -> Unit,
|
||||
onOpenQrCodeClick: (String) -> Unit,
|
||||
) {
|
||||
if (addresses.isEmpty()) return
|
||||
var selectedAddress by remember { mutableStateOf(addresses.first()) }
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = 0,
|
||||
initialPageOffsetFraction = 0f,
|
||||
pageCount = addresses::count,
|
||||
)
|
||||
LaunchedEffect(key1 = pagerState.currentPage) {
|
||||
selectedAddress = addresses[pagerState.currentPage]
|
||||
}
|
||||
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
pageSpacing = 16.dp,
|
||||
) {
|
||||
AddressItem(
|
||||
currencyIconState = currencyIconState,
|
||||
onOpenQrCodeClick = { onOpenQrCodeClick(selectedAddress.value) },
|
||||
onCopyClick = { onCopyClick(selectedAddress) },
|
||||
onShareClick = { onShareClick(selectedAddress.value) },
|
||||
primaryType = selectedAddress.type as ReceiveAddress.Type.Primary,
|
||||
address = selectedAddress.value,
|
||||
isDynamicAddress = selectedAddress.type is ReceiveAddress.Type.Primary.Dynamic,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(4.dp)
|
||||
|
||||
if (pagerState.pageCount > 1) {
|
||||
val indicatorState = rememberLazyListState()
|
||||
val selectedColor = TangemTheme.colors.icon.primary1
|
||||
val unselectedColor = TangemTheme.colors.icon.informative
|
||||
|
||||
LazyRow(
|
||||
modifier = Modifier.height(20.dp),
|
||||
state = indicatorState,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
repeat(pagerState.pageCount) { iteration ->
|
||||
item(key = iteration) {
|
||||
val color by animateColorAsState(
|
||||
targetValue = if (pagerState.currentPage == iteration) selectedColor else unselectedColor,
|
||||
label = "",
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp, vertical = 6.dp)
|
||||
.background(color = color, shape = CircleShape)
|
||||
.size(7.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun AddressItem(
|
||||
currencyIconState: CurrencyIconState,
|
||||
onOpenQrCodeClick: () -> Unit,
|
||||
onCopyClick: () -> Unit,
|
||||
onShareClick: () -> Unit,
|
||||
primaryType: ReceiveAddress.Type.Primary,
|
||||
address: String,
|
||||
isDynamicAddress: Boolean,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
onClick = onOpenQrCodeClick,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier.size(56.dp),
|
||||
state = currencyIconState,
|
||||
shouldDisplayNetwork = true,
|
||||
iconSize = 56.dp,
|
||||
)
|
||||
|
||||
SpacerH(12.dp)
|
||||
|
||||
if (isDynamicAddress) {
|
||||
DynamicAddressBadge()
|
||||
SpacerH(8.dp)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = primaryType.displayName.resolveReference(),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.heightIn(min = 40.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
text = address,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.body2,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
SpacerH8()
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable(onClick = onOpenQrCodeClick)
|
||||
.padding(vertical = 6.dp, horizontal = 12.dp),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(16.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_qrcode_new_24),
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SpacerW(4.dp)
|
||||
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.token_receive_show_qr_code_title),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH(20.dp)
|
||||
|
||||
ButtonsBlock(
|
||||
snackbarHostState = snackbarHostState,
|
||||
onCopyClick = onCopyClick,
|
||||
onShareClick = onShareClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ButtonsBlock(snackbarHostState: SnackbarHostState, onCopyClick: () -> Unit, onShareClick: () -> Unit) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val topSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = Modifier.width(IntrinsicSize.Min),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
ActionButtonWithResizableText(
|
||||
modifier = Modifier.weight(1f),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_copy),
|
||||
iconResId = R.drawable.ic_copy_new_24,
|
||||
onClick = {
|
||||
onCopyClick()
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
topSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(R.string.wallet_notification_address_copied),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ActionButtonWithResizableText(
|
||||
modifier = Modifier.weight(1f),
|
||||
config = ActionButtonConfig(
|
||||
text = TextReference.Res(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onShareClick()
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EnsItem(onCopyClick: () -> Unit, address: String, modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 14.dp, horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(36.dp),
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_ens_36),
|
||||
contentDescription = null,
|
||||
)
|
||||
|
||||
SpacerW12()
|
||||
|
||||
EllipsisText(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = address,
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
)
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_share_24,
|
||||
innerPadding = 6.dp,
|
||||
onClick = onCopyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LoadingBlock(modifier: Modifier = Modifier) {
|
||||
Card(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 64.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
color = TangemTheme.colors.icon.informative,
|
||||
modifier = Modifier.padding(TangemTheme.dimens.spacing8),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ActionButtonWithResizableText(config: ActionButtonConfig, modifier: Modifier = Modifier) {
|
||||
ActionBaseButton(
|
||||
config = config,
|
||||
shape = RoundedCornerShape(size = TangemTheme.dimens.radius24),
|
||||
content = { contentModifier ->
|
||||
ActionButtonContent(
|
||||
config = config,
|
||||
text = { color ->
|
||||
Text(
|
||||
text = config.text.resolveReference(),
|
||||
autoSize = TextAutoSize.StepBased(
|
||||
minFontSize = 10.sp,
|
||||
maxFontSize = TangemTheme.typography.button.fontSize,
|
||||
),
|
||||
color = color,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
style = TangemTheme.typography.button,
|
||||
)
|
||||
},
|
||||
modifier = contentModifier.padding(horizontal = 16.dp),
|
||||
paddingBetweenIconAndText = 4.dp,
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
color = TangemTheme.colors.button.secondary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DynamicAddressBadge(modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = TangemTheme.colors.text.accent.copy(alpha = 0.1f),
|
||||
shape = RoundedCornerShape(percent = 50),
|
||||
)
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(
|
||||
id = R.drawable.ic_dynamic_addresses_badge_16,
|
||||
),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.dynamic_addresses_receive_badge),
|
||||
style = TangemTheme.typography.caption1,
|
||||
color = TangemTheme.colors.text.accent,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_TokenReceiveAssetsContent(
|
||||
@PreviewParameter(TokenReceiveAssetsContentProvider::class) params: ReceiveAssetsUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TokenReceiveAssetsContentLegacy(assetsUM = params)
|
||||
}
|
||||
}
|
||||
|
||||
internal class TokenReceiveAssetsContentProvider : PreviewParameterProvider<ReceiveAssetsUM> {
|
||||
val address = ReceiveAddress(
|
||||
value = "0xe5178c7d4d0e861ed2e9414e045b501226b0de8d",
|
||||
type = ReceiveAddress.Type.Primary.Default(
|
||||
displayName = stringReference("Etherium address"),
|
||||
),
|
||||
)
|
||||
private val dynamicAddress = ReceiveAddress(
|
||||
value = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
|
||||
type = ReceiveAddress.Type.Primary.Dynamic(
|
||||
displayName = stringReference("Ethereum address"),
|
||||
),
|
||||
)
|
||||
private val tokenIconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = null,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
)
|
||||
private val config = ReceiveAssetsUM(
|
||||
notificationConfigs =
|
||||
persistentListOf(
|
||||
NotificationUM.Warning(
|
||||
title = stringReference("Send only XLM on the Ethereum network"),
|
||||
subtitle = resourceReference(R.string.receive_bottom_sheet_warning_message_description),
|
||||
),
|
||||
),
|
||||
addresses = persistentListOf(
|
||||
address,
|
||||
address,
|
||||
address.copy(type = ReceiveAddress.Type.Ens, value = "papasha.eth"),
|
||||
),
|
||||
showMemoDisclaimer = false,
|
||||
onCopyClick = {},
|
||||
onOpenQrCodeClick = {},
|
||||
isEnsResultLoading = true,
|
||||
network = "USDT",
|
||||
currencyIconState = CurrencyIconState.Locked,
|
||||
onShareClick = {},
|
||||
)
|
||||
private val yieldSupplyIsActiveConfig = config.copy(
|
||||
notificationConfigs = persistentListOf(
|
||||
NotificationUM.Warning.YieldSupplyIsActive(tokenName = "USDT"),
|
||||
),
|
||||
isEnsResultLoading = false,
|
||||
currencyIconState = tokenIconState,
|
||||
)
|
||||
private val dynamicAddressConfig = config.copy(
|
||||
addresses = persistentListOf(
|
||||
dynamicAddress,
|
||||
address,
|
||||
address.copy(type = ReceiveAddress.Type.Ens, value = "papasha.eth"),
|
||||
),
|
||||
isEnsResultLoading = false,
|
||||
notificationConfigs = persistentListOf(),
|
||||
currencyIconState = tokenIconState,
|
||||
)
|
||||
|
||||
override val values: Sequence<ReceiveAssetsUM>
|
||||
get() = sequenceOf(config, yieldSupplyIsActiveConfig, dynamicAddressConfig)
|
||||
}
|
||||
|
|
@ -2,22 +2,32 @@ package com.tangem.features.tokenreceive.ui
|
|||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.fade
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetType
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBar
|
||||
import com.tangem.core.ui.ds.topbar.TangemTopBarType
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.LocalHazeState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_chevron_left_24
|
||||
import com.tangem.core.ui.res.generated.icons.ic_cross_24
|
||||
import com.tangem.features.tokenreceive.route.TokenReceiveRoutes
|
||||
import dev.chrisbanes.haze.rememberHazeState
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveContentSheet(
|
||||
|
|
@ -26,59 +36,89 @@ internal fun TokenReceiveContentSheet(
|
|||
onBackClick: () -> Unit,
|
||||
contentStack: ChildStack<TokenReceiveRoutes, ComposableContentComponent>,
|
||||
) {
|
||||
TangemModalBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onCloseClick,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
onBack = onBackClick,
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = {
|
||||
Title(
|
||||
route = route,
|
||||
onBackClick = onBackClick,
|
||||
onCloseClick = onCloseClick,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
TokenReceiveContent(
|
||||
stackState = contentStack,
|
||||
modifier = Modifier,
|
||||
)
|
||||
},
|
||||
)
|
||||
CompositionLocalProvider(LocalHazeState provides rememberHazeState()) {
|
||||
TangemBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
type = TangemBottomSheetType.Modal,
|
||||
onBack = onBackClick,
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onCloseClick,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
containerColor = TangemTheme.colors3.bg.secondary,
|
||||
title = {
|
||||
Title(
|
||||
route = route,
|
||||
onBackClick = onBackClick,
|
||||
onCloseClick = onCloseClick,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
TokenReceiveContent(
|
||||
stackState = contentStack,
|
||||
modifier = Modifier,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Title(route: TokenReceiveRoutes, onBackClick: () -> Unit, onCloseClick: () -> Unit) {
|
||||
when (route) {
|
||||
is TokenReceiveRoutes.QrCode -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
startIconRes = R.drawable.ic_back_24,
|
||||
onStartClick = onBackClick,
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
TangemTopBar(
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
endContent = {
|
||||
TangemButton(
|
||||
iconStart = TangemIconUM.Icon(Icons.ic_cross_24),
|
||||
onClick = onCloseClick,
|
||||
size = TangemButton.Size.X11,
|
||||
variant = TangemButton.Variant.Material,
|
||||
)
|
||||
},
|
||||
startContent = {
|
||||
TangemButton(
|
||||
iconStart = TangemIconUM.Icon(imageVector = Icons.ic_chevron_left_24),
|
||||
onClick = onBackClick,
|
||||
size = TangemButton.Size.X11,
|
||||
variant = TangemButton.Variant.Material,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
TokenReceiveRoutes.ReceiveAssets -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
TangemTopBar(
|
||||
title = resourceReference(R.string.domain_receive_assets_navigation_title),
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
endContent = {
|
||||
TangemButton(
|
||||
iconStart = TangemIconUM.Icon(Icons.ic_cross_24),
|
||||
onClick = onCloseClick,
|
||||
size = TangemButton.Size.X11,
|
||||
variant = TangemButton.Variant.Material,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
TokenReceiveRoutes.Warning -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
TangemTopBar(
|
||||
type = TangemTopBarType.BottomSheet,
|
||||
endContent = {
|
||||
TangemButton(
|
||||
iconStart = TangemIconUM.Icon(Icons.ic_cross_24),
|
||||
onClick = onCloseClick,
|
||||
size = TangemButton.Size.X11,
|
||||
variant = TangemButton.Variant.Material,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveContent(
|
||||
private fun TokenReceiveContent(
|
||||
stackState: ChildStack<TokenReceiveRoutes, ComposableContentComponent>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -86,9 +126,9 @@ internal fun TokenReceiveContent(
|
|||
stack = stackState,
|
||||
animation = stackAnimation(fade(animationSpec = tween(durationMillis = 100))),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.fillMaxWidth()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
it.instance.Content(Modifier.fillMaxSize())
|
||||
it.instance.Content(Modifier.fillMaxWidth())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.fade
|
||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
||||
import com.arkivanov.decompose.router.stack.ChildStack
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.tokenreceive.route.TokenReceiveRoutes
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveContentSheetLegacy(
|
||||
route: TokenReceiveRoutes,
|
||||
onCloseClick: () -> Unit,
|
||||
onBackClick: () -> Unit,
|
||||
contentStack: ChildStack<TokenReceiveRoutes, ComposableContentComponent>,
|
||||
) {
|
||||
TangemModalBottomSheet<TangemBottomSheetConfigContent.Empty>(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = onCloseClick,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
onBack = onBackClick,
|
||||
containerColor = TangemTheme.colors.background.tertiary,
|
||||
title = {
|
||||
Title(
|
||||
route = route,
|
||||
onBackClick = onBackClick,
|
||||
onCloseClick = onCloseClick,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
TokenReceiveContent(
|
||||
stackState = contentStack,
|
||||
modifier = Modifier,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Title(route: TokenReceiveRoutes, onBackClick: () -> Unit, onCloseClick: () -> Unit) {
|
||||
when (route) {
|
||||
is TokenReceiveRoutes.QrCode -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
startIconRes = R.drawable.ic_back_24,
|
||||
onStartClick = onBackClick,
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
)
|
||||
}
|
||||
TokenReceiveRoutes.ReceiveAssets -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
title = resourceReference(R.string.domain_receive_assets_navigation_title),
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
)
|
||||
}
|
||||
TokenReceiveRoutes.Warning -> {
|
||||
TangemModalBottomSheetTitle(
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = onCloseClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TokenReceiveContent(
|
||||
stackState: ChildStack<TokenReceiveRoutes, ComposableContentComponent>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Children(
|
||||
stack = stackState,
|
||||
animation = stackAnimation(fade(animationSpec = tween(durationMillis = 100))),
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.animateContentSize(),
|
||||
) {
|
||||
it.instance.Content(Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,9 @@ package com.tangem.features.tokenreceive.ui
|
|||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -18,24 +16,25 @@ import androidx.compose.ui.graphics.painter.BitmapPainter
|
|||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.ds.image.TangemIconUM
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.LocalTopSnackbarHostState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.res.generated.icons.Icons
|
||||
import com.tangem.core.ui.res.generated.icons.ic_copy_24
|
||||
import com.tangem.core.ui.res.generated.icons.ic_share_android_24
|
||||
import com.tangem.core.ui.test.TokenReceiveQrCodeBottomSheetTestTags
|
||||
import com.tangem.features.tokenreceive.impl.R
|
||||
import com.tangem.features.tokenreceive.ui.state.QrCodeUM
|
||||
|
|
@ -43,34 +42,28 @@ import kotlinx.coroutines.launch
|
|||
|
||||
@Composable
|
||||
internal fun TokenReceiveQrCodeContent(qrCodeUM: QrCodeUM) {
|
||||
val snackbarHostState = remember(::SnackbarHostState)
|
||||
val qrCodePainter = rememberQrPainter(content = qrCodeUM.addressValue)
|
||||
|
||||
ContainerWithSnackbarHost(snackbarHostState = snackbarHostState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(bottom = 16.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
SpacerH8()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp, start = 16.dp, end = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
QrCodePage(
|
||||
addressFullName = qrCodeUM.addressName,
|
||||
addressValue = qrCodeUM.addressValue,
|
||||
network = qrCodeUM.network,
|
||||
qrCodePainter = qrCodePainter,
|
||||
)
|
||||
|
||||
QrCodePage(
|
||||
addressFullName = qrCodeUM.addressName,
|
||||
addressValue = qrCodeUM.addressValue,
|
||||
network = qrCodeUM.network,
|
||||
qrCodePainter = qrCodePainter,
|
||||
)
|
||||
SpacerH24()
|
||||
SpacerH(24.dp)
|
||||
|
||||
Buttons(
|
||||
onShareClick = { qrCodeUM.onShareClick(qrCodeUM.addressValue) },
|
||||
onCopyClick = qrCodeUM.onCopyClick,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
}
|
||||
Buttons(
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
onShareClick = { qrCodeUM.onShareClick(qrCodeUM.addressValue) },
|
||||
onCopyClick = qrCodeUM.onCopyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +74,12 @@ private fun QrCodePage(addressFullName: TextReference, addressValue: String, net
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.size36),
|
||||
modifier = Modifier.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 24.dp,
|
||||
bottom = 16.dp,
|
||||
),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
|
|
@ -90,22 +88,22 @@ private fun QrCodePage(addressFullName: TextReference, addressValue: String, net
|
|||
addressFullName.resolveReference(),
|
||||
network,
|
||||
),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.h3,
|
||||
style = TangemTheme.typography3.heading.small,
|
||||
modifier = Modifier.testTag(TokenReceiveQrCodeBottomSheetTestTags.TITLE),
|
||||
)
|
||||
|
||||
SpacerH(20.dp)
|
||||
SpacerH(32.dp)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.border(
|
||||
width = 8.dp,
|
||||
color = TangemTheme.colors.icon.constant,
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
width = 16.dp,
|
||||
color = TangemTheme.colors3.bg.secondary,
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
)
|
||||
.padding(8.dp)
|
||||
.padding(16.dp)
|
||||
.testTag(TokenReceiveQrCodeBottomSheetTestTags.QR_CODE),
|
||||
|
||||
) {
|
||||
|
|
@ -116,79 +114,66 @@ private fun QrCodePage(addressFullName: TextReference, addressValue: String, net
|
|||
modifier = Modifier.sizeIn(minWidth = 148.dp),
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH24()
|
||||
}
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.wc_common_address),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
style = TangemTheme.typography3.caption.medium,
|
||||
)
|
||||
|
||||
SpacerH2()
|
||||
SpacerH(4.dp)
|
||||
|
||||
Text(
|
||||
text = addressValue,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
style = TangemTheme.typography3.body.medium,
|
||||
modifier = Modifier.testTag(TokenReceiveQrCodeBottomSheetTestTags.ADDRESS),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Buttons(
|
||||
snackbarHostState: SnackbarHostState,
|
||||
onShareClick: () -> Unit,
|
||||
onCopyClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
private fun Buttons(onShareClick: () -> Unit, onCopyClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val tangemTopSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
SecondaryButtonIconStart(
|
||||
TangemButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResourceSafe(id = R.string.common_copy),
|
||||
iconResId = R.drawable.ic_copy_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onCopyClick()
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
tangemTopSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(R.string.wallet_notification_address_copied),
|
||||
)
|
||||
}
|
||||
tangemTopSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
text = resourceReference(R.string.common_copy),
|
||||
iconStart = TangemIconUM.Icon(Icons.ic_copy_24),
|
||||
size = TangemButton.Size.X12,
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
)
|
||||
|
||||
SecondaryButtonIconStart(
|
||||
TangemButton(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResourceSafe(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onShareClick()
|
||||
},
|
||||
text = resourceReference(R.string.common_share),
|
||||
iconStart = TangemIconUM.Icon(Icons.ic_share_android_24),
|
||||
size = TangemButton.Size.X12,
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -212,20 +197,7 @@ private fun rememberQrPainter(content: String, size: Dp = 248.dp, padding: Dp =
|
|||
private fun Preview_TokenReceiveQrCodeContent(
|
||||
@PreviewParameter(TokenReceiveQrCodeContentPreviewProvider::class) qrCodeUM: QrCodeUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TangemThemePreviewRedesign {
|
||||
TokenReceiveQrCodeContent(qrCodeUM = qrCodeUM)
|
||||
}
|
||||
}
|
||||
|
||||
private class TokenReceiveQrCodeContentPreviewProvider : PreviewParameterProvider<QrCodeUM> {
|
||||
private val config = QrCodeUM(
|
||||
network = "Ethereum",
|
||||
addressName = stringReference("Etherium"),
|
||||
addressValue = "0xe5178c7d4d0e861ed2e9414e045b501226b0de8d",
|
||||
onCopyClick = {},
|
||||
onShareClick = {},
|
||||
)
|
||||
|
||||
override val values: Sequence<QrCodeUM>
|
||||
get() = sequenceOf(config)
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.painter.BitmapPainter
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.res.getStringSafe
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.res.LocalRedesignEnabled
|
||||
import com.tangem.core.ui.res.LocalTopSnackbarHostState
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.TokenReceiveQrCodeBottomSheetTestTags
|
||||
import com.tangem.features.tokenreceive.impl.R
|
||||
import com.tangem.features.tokenreceive.ui.state.QrCodeUM
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveQrCodeContentLegacy(qrCodeUM: QrCodeUM) {
|
||||
val snackbarHostState = remember(::SnackbarHostState)
|
||||
val qrCodePainter = rememberQrPainter(content = qrCodeUM.addressValue)
|
||||
|
||||
ContainerWithSnackbarHost(snackbarHostState = snackbarHostState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(bottom = 16.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
SpacerH8()
|
||||
|
||||
QrCodePage(
|
||||
addressFullName = qrCodeUM.addressName,
|
||||
addressValue = qrCodeUM.addressValue,
|
||||
network = qrCodeUM.network,
|
||||
qrCodePainter = qrCodePainter,
|
||||
)
|
||||
SpacerH24()
|
||||
|
||||
Buttons(
|
||||
onShareClick = { qrCodeUM.onShareClick(qrCodeUM.addressValue) },
|
||||
onCopyClick = qrCodeUM.onCopyClick,
|
||||
snackbarHostState = snackbarHostState,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun QrCodePage(addressFullName: TextReference, addressValue: String, network: String, qrCodePainter: Painter) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = TangemTheme.dimens.size36),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
text = stringResourceSafe(
|
||||
R.string.receive_bottom_sheet_warning_message_compact,
|
||||
addressFullName.resolveReference(),
|
||||
network,
|
||||
),
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.h3,
|
||||
modifier = Modifier.testTag(TokenReceiveQrCodeBottomSheetTestTags.TITLE),
|
||||
)
|
||||
|
||||
SpacerH(20.dp)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.border(
|
||||
width = 8.dp,
|
||||
color = TangemTheme.colors.icon.constant,
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
)
|
||||
.padding(8.dp)
|
||||
.testTag(TokenReceiveQrCodeBottomSheetTestTags.QR_CODE),
|
||||
|
||||
) {
|
||||
Image(
|
||||
painter = qrCodePainter,
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Fit,
|
||||
modifier = Modifier.sizeIn(minWidth = 148.dp),
|
||||
)
|
||||
}
|
||||
|
||||
SpacerH24()
|
||||
}
|
||||
Text(
|
||||
text = stringResourceSafe(R.string.wc_common_address),
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
)
|
||||
|
||||
SpacerH2()
|
||||
|
||||
Text(
|
||||
text = addressValue,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
textAlign = TextAlign.Center,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
modifier = Modifier.testTag(TokenReceiveQrCodeBottomSheetTestTags.ADDRESS),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Buttons(
|
||||
snackbarHostState: SnackbarHostState,
|
||||
onShareClick: () -> Unit,
|
||||
onCopyClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val resources = context.resources
|
||||
|
||||
val isRedesignEnabled = LocalRedesignEnabled.current
|
||||
val tangemTopSnackbarHostState = LocalTopSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
SecondaryButtonIconStart(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResourceSafe(id = R.string.common_copy),
|
||||
iconResId = R.drawable.ic_copy_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onCopyClick()
|
||||
coroutineScope.launch {
|
||||
if (isRedesignEnabled) {
|
||||
tangemTopSnackbarHostState.showSnackbar(
|
||||
SnackbarMessage(
|
||||
startIconId = R.drawable.ic_check_24,
|
||||
message = resourceReference(R.string.wallet_notification_address_copied),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
snackbarHostState.showSnackbar(
|
||||
message = resources.getStringSafe(R.string.wallet_notification_address_copied),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
SecondaryButtonIconStart(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResourceSafe(id = R.string.common_share),
|
||||
iconResId = R.drawable.ic_share_24,
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onShareClick()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberQrPainter(content: String, size: Dp = 248.dp, padding: Dp = 0.dp): BitmapPainter {
|
||||
val density = LocalDensity.current
|
||||
return remember(content) {
|
||||
BitmapPainter(
|
||||
content.toQrCode(
|
||||
sizePx = with(density) { size.roundToPx() },
|
||||
paddingPx = with(density) { padding.roundToPx() },
|
||||
).asImageBitmap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_TokenReceiveQrCodeContent(
|
||||
@PreviewParameter(TokenReceiveQrCodeContentPreviewProvider::class) qrCodeUM: QrCodeUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TokenReceiveQrCodeContentLegacy(qrCodeUM = qrCodeUM)
|
||||
}
|
||||
}
|
||||
|
||||
internal class TokenReceiveQrCodeContentPreviewProvider : PreviewParameterProvider<QrCodeUM> {
|
||||
private val config = QrCodeUM(
|
||||
network = "Ethereum",
|
||||
addressName = stringReference("Etherium"),
|
||||
addressValue = "0xe5178c7d4d0e861ed2e9414e045b501226b0de8d",
|
||||
onCopyClick = {},
|
||||
onShareClick = {},
|
||||
)
|
||||
|
||||
override val values: Sequence<QrCodeUM>
|
||||
get() = sequenceOf(config)
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -13,19 +15,14 @@ import androidx.compose.ui.platform.testTag
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH12
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.SpacerW6
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.ds2.button.TangemButton
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.res.TangemThemePreviewRedesign
|
||||
import com.tangem.core.ui.test.TokenReceiveWarningBottomSheetTestTags
|
||||
import com.tangem.features.tokenreceive.impl.R
|
||||
import com.tangem.features.tokenreceive.ui.state.WarningUM
|
||||
|
|
@ -37,51 +34,51 @@ internal fun TokenReceiveWarningContent(warningUM: WarningUM) {
|
|||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(
|
||||
top = 28.dp,
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
).testTag(TokenReceiveWarningBottomSheetTestTags.BOTTOM_SHEET),
|
||||
)
|
||||
.testTag(TokenReceiveWarningBottomSheetTestTags.BOTTOM_SHEET),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(size = 64.dp),
|
||||
.size(size = 76.dp),
|
||||
state = warningUM.iconState,
|
||||
shouldDisplayNetwork = true,
|
||||
iconSize = 56.dp,
|
||||
networkBadgeSize = 24.dp,
|
||||
iconSize = 72.dp,
|
||||
)
|
||||
|
||||
SpacerH24()
|
||||
|
||||
SpacerH(32.dp)
|
||||
WarningBlock(networkName = warningUM.network)
|
||||
|
||||
SpacerH12()
|
||||
|
||||
SpacerH(8.dp)
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_description),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
style = TangemTheme.typography3.subheading.medium,
|
||||
color = TangemTheme.colors3.text.secondary,
|
||||
)
|
||||
|
||||
SpacerH(48.dp)
|
||||
|
||||
SecondaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.common_got_it),
|
||||
TangemButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
variant = TangemButton.Variant.Secondary,
|
||||
text = resourceReference(R.string.common_got_it),
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
warningUM.onWarningAcknowledged()
|
||||
},
|
||||
size = TangemButton.Size.X12,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WarningBlock(networkName: String, modifier: Modifier = Modifier) {
|
||||
private fun WarningBlock(networkName: String, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
|
|
@ -89,17 +86,15 @@ fun WarningBlock(networkName: String, modifier: Modifier = Modifier) {
|
|||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_title),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography3.heading.small,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
)
|
||||
|
||||
SpacerW6()
|
||||
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_network_name, networkName),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography3.heading.small,
|
||||
color = TangemTheme.colors3.text.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -110,27 +105,7 @@ fun WarningBlock(networkName: String, modifier: Modifier = Modifier) {
|
|||
private fun Preview_TokenReceiveWarningContent(
|
||||
@PreviewParameter(TokenReceiveWarningContentProvider::class) warningUM: WarningUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TangemThemePreviewRedesign {
|
||||
TokenReceiveWarningContent(warningUM = warningUM)
|
||||
}
|
||||
}
|
||||
|
||||
private class TokenReceiveWarningContentProvider : PreviewParameterProvider<WarningUM> {
|
||||
val iconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = null,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
)
|
||||
|
||||
override val values: Sequence<WarningUM>
|
||||
get() = sequenceOf(
|
||||
WarningUM(
|
||||
iconState = iconState,
|
||||
onWarningAcknowledged = {},
|
||||
network = "Etherium",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package com.tangem.features.tokenreceive.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH12
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIcon
|
||||
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.test.TokenReceiveWarningBottomSheetTestTags
|
||||
import com.tangem.features.tokenreceive.impl.R
|
||||
import com.tangem.features.tokenreceive.ui.state.WarningUM
|
||||
|
||||
@Composable
|
||||
internal fun TokenReceiveWarningContentLegacy(warningUM: WarningUM) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(color = TangemTheme.colors.background.tertiary)
|
||||
.padding(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
bottom = 16.dp,
|
||||
)
|
||||
.testTag(TokenReceiveWarningBottomSheetTestTags.BOTTOM_SHEET),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
CurrencyIcon(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.size(size = 64.dp),
|
||||
state = warningUM.iconState,
|
||||
shouldDisplayNetwork = true,
|
||||
iconSize = 56.dp,
|
||||
)
|
||||
|
||||
SpacerH24()
|
||||
|
||||
WarningBlock(networkName = warningUM.network)
|
||||
|
||||
SpacerH12()
|
||||
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_description),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
|
||||
SpacerH(48.dp)
|
||||
|
||||
SecondaryButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResourceSafe(R.string.common_got_it),
|
||||
onClick = {
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
warningUM.onWarningAcknowledged()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WarningBlock(networkName: String, modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_title),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
SpacerH(6.dp)
|
||||
|
||||
Text(
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_network_name, networkName),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_TokenReceiveWarningContent(
|
||||
@PreviewParameter(TokenReceiveWarningContentProvider::class) warningUM: WarningUM,
|
||||
) {
|
||||
TangemThemePreview {
|
||||
TokenReceiveWarningContentLegacy(warningUM = warningUM)
|
||||
}
|
||||
}
|
||||
|
||||
internal class TokenReceiveWarningContentProvider : PreviewParameterProvider<WarningUM> {
|
||||
val iconState = CurrencyIconState.TokenIcon(
|
||||
url = null,
|
||||
topBadgeIconResId = null,
|
||||
fallbackTint = TangemColorPalette.Black,
|
||||
fallbackBackground = TangemColorPalette.Meadow,
|
||||
isGrayscale = false,
|
||||
shouldShowCustomBadge = false,
|
||||
)
|
||||
|
||||
override val values: Sequence<WarningUM>
|
||||
get() = sequenceOf(
|
||||
WarningUM(
|
||||
iconState = iconState,
|
||||
onWarningAcknowledged = {},
|
||||
network = "Etherium",
|
||||
),
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue