Updated on 2026-08-14
This commit is contained in:
parent
bce16bf692
commit
6d461cf400
16 changed files with 180 additions and 84 deletions
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.models.ReceiveAddressModel
|
|||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
|
|
@ -399,16 +400,17 @@ internal class MarketsPortfolioModel @Inject constructor(
|
|||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Ens,
|
||||
value = ens,
|
||||
displayName = ens,
|
||||
),
|
||||
)
|
||||
}
|
||||
addresses.availableAddresses.map { address ->
|
||||
add(
|
||||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Default,
|
||||
nameService = when (address.type) {
|
||||
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
|
||||
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
|
||||
},
|
||||
value = address.value,
|
||||
displayName = "${cryptoCurrency.name} (${cryptoCurrency.symbol})",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,16 +209,17 @@ internal class NFTReceiveModel @Inject constructor(
|
|||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Ens,
|
||||
value = ens,
|
||||
displayName = ens,
|
||||
),
|
||||
)
|
||||
}
|
||||
addresses.availableAddresses.map { address ->
|
||||
add(
|
||||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Default,
|
||||
nameService = when (address.type) {
|
||||
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
|
||||
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
|
||||
},
|
||||
value = address.value,
|
||||
displayName = cryptoCurrency.symbol,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ internal class DefaultTokenReceiveComponent @AssistedInject constructor(
|
|||
is TokenReceiveRoutes.QrCode -> TokenReceiveQrCodeComponent(
|
||||
appComponentContext = appComponentContext,
|
||||
params = TokenReceiveQrCodeComponent.TokenReceiveQrCodeParams(
|
||||
network = model.params.config.cryptoCurrency.network.name,
|
||||
cryptoCurrency = model.params.config.cryptoCurrency,
|
||||
address = model.state.value.addresses[config.addressId] ?: error("Address has to be there"),
|
||||
callback = model,
|
||||
onDismiss = ::dismiss,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ 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.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.model.TokenReceiveQrCodeModel
|
||||
import com.tangem.features.tokenreceive.ui.TokenReceiveQrCodeContent
|
||||
|
|
@ -31,7 +32,7 @@ internal class TokenReceiveQrCodeComponent(
|
|||
|
||||
data class TokenReceiveQrCodeParams(
|
||||
val id: Int,
|
||||
val network: String,
|
||||
val cryptoCurrency: CryptoCurrency,
|
||||
val address: ReceiveAddress,
|
||||
val callback: TokenReceiveQrCodeModelCallback,
|
||||
val onDismiss: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,27 @@
|
|||
package com.tangem.features.tokenreceive.entity
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
internal data class ReceiveAddress(
|
||||
val value: String,
|
||||
val type: Type,
|
||||
) {
|
||||
|
||||
@Immutable
|
||||
sealed interface Type {
|
||||
data object Ens : Type
|
||||
|
||||
data class Default(
|
||||
val displayName: TextReference,
|
||||
) : Type
|
||||
sealed interface Primary : Type {
|
||||
|
||||
val displayName: TextReference
|
||||
|
||||
data class Default(
|
||||
val title: TextReference?,
|
||||
override val displayName: TextReference,
|
||||
) : Primary
|
||||
|
||||
data class Legacy(override val displayName: TextReference) : Primary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,6 @@ internal class TokenReceiveAssetsModel @Inject constructor(
|
|||
showMemoDisclaimer = params.showMemoDisclaimer,
|
||||
isEnsResultLoading = false,
|
||||
notificationConfigs = params.notificationConfigs,
|
||||
fullName = params.fullName,
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ import com.tangem.core.ui.R
|
|||
import com.tangem.core.ui.clipboard.ClipboardManager
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.models.Asset
|
||||
import com.tangem.domain.models.ReceiveAddressModel
|
||||
|
|
@ -25,6 +25,8 @@ import com.tangem.domain.transaction.usecase.GetReverseResolvedEnsAddressUseCase
|
|||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
import com.tangem.features.tokenreceive.component.TokenReceiveModelCallback
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Ens
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress.Type.Primary
|
||||
import com.tangem.features.tokenreceive.route.TokenReceiveRoutes
|
||||
import com.tangem.features.tokenreceive.ui.state.TokenReceiveUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -103,17 +105,33 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun mapAddresses(addresses: List<ReceiveAddressModel>): ImmutableMap<Int, ReceiveAddress> {
|
||||
private fun mapAddresses(
|
||||
addresses: List<ReceiveAddressModel>,
|
||||
networkName: String,
|
||||
): ImmutableMap<Int, ReceiveAddress> {
|
||||
val conditionToUseTitle = addresses.any { it.nameService == ReceiveAddressModel.NameService.Legacy }
|
||||
return buildMap {
|
||||
addresses.mapIndexed { index, model ->
|
||||
val type = when (model.nameService) {
|
||||
ReceiveAddressModel.NameService.Default -> {
|
||||
ReceiveAddress.Type.Default(
|
||||
displayName = stringReference(model.displayName),
|
||||
Primary.Default(
|
||||
displayName = TextReference.Res(
|
||||
id = R.string.domain_receive_assets_onboarding_network_name,
|
||||
formatArgs = wrappedList(networkName),
|
||||
),
|
||||
title = if (conditionToUseTitle) {
|
||||
TextReference.Res(R.string.domain_receive_assets_default_address)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
}
|
||||
ReceiveAddressModel.NameService.Ens -> ReceiveAddress.Type.Ens
|
||||
ReceiveAddressModel.NameService.Ens -> Ens
|
||||
ReceiveAddressModel.NameService.Legacy -> Primary.Legacy(
|
||||
displayName = TextReference.Res(R.string.common_legacy_bitcoin_address),
|
||||
)
|
||||
}
|
||||
|
||||
put(
|
||||
key = index,
|
||||
value = ReceiveAddress(
|
||||
|
|
@ -146,10 +164,18 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
val newEnsAddresses = reverseResolveResult
|
||||
.filterIsInstance<EnsAddress.Address>()
|
||||
.filterNot { it.name in currentAddressValues }
|
||||
.map { ensAddress -> ReceiveAddress(value = ensAddress.name, type = ReceiveAddress.Type.Ens) }
|
||||
.map { ensAddress -> ReceiveAddress(value = ensAddress.name, type = Ens) }
|
||||
|
||||
val combinedAddresses = (state.value.addresses.values + newEnsAddresses)
|
||||
.sortedWith(compareByDescending { it.type is ReceiveAddress.Type.Ens })
|
||||
.sortedWith(
|
||||
compareBy { address ->
|
||||
when (address.type) {
|
||||
is Ens -> 0
|
||||
is Primary.Default -> 1
|
||||
is Primary.Legacy -> 2
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
val updatedAddresses = combinedAddresses
|
||||
.mapIndexed { index, address -> index to address }
|
||||
|
|
@ -191,7 +217,10 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
|
||||
private fun getInitState(): TokenReceiveUM {
|
||||
return TokenReceiveUM(
|
||||
addresses = mapAddresses(params.config.receiveAddress),
|
||||
addresses = mapAddresses(
|
||||
addresses = params.config.receiveAddress,
|
||||
networkName = params.config.cryptoCurrency.network.name,
|
||||
),
|
||||
iconState = iconStateConverter.convert(params.config.cryptoCurrency),
|
||||
network = params.config.cryptoCurrency.network.name,
|
||||
isEnsResultLoading = false,
|
||||
|
|
@ -201,13 +230,13 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
|
||||
private fun sendCopyActionAnalytic(receiveAddress: ReceiveAddress) {
|
||||
val event = when (receiveAddress.type) {
|
||||
is ReceiveAddress.Type.Default -> {
|
||||
is Primary -> {
|
||||
TokenReceiveNewAnalyticsEvent.ButtonCopyAddress(
|
||||
token = getTokenName(),
|
||||
blockchainName = params.config.cryptoCurrency.network.name,
|
||||
)
|
||||
}
|
||||
ReceiveAddress.Type.Ens -> {
|
||||
Ens -> {
|
||||
TokenReceiveNewAnalyticsEvent.ButtonCopyEns(
|
||||
token = getTokenName(),
|
||||
blockchainName = params.config.cryptoCurrency.network.name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.features.tokenreceive.component.TokenReceiveQrCodeComponent
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.ui.state.QrCodeUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -25,9 +24,9 @@ internal class TokenReceiveQrCodeModel @Inject constructor(
|
|||
internal val state: StateFlow<QrCodeUM>
|
||||
field = MutableStateFlow<QrCodeUM>(
|
||||
QrCodeUM(
|
||||
network = params.network,
|
||||
network = params.cryptoCurrency.network.name,
|
||||
addressValue = params.address.value,
|
||||
addressName = (params.address.type as? ReceiveAddress.Type.Default)?.displayName ?: TextReference.EMPTY,
|
||||
addressName = TextReference.Str("${params.cryptoCurrency.name} (${params.cryptoCurrency.symbol})"),
|
||||
onCopyClick = { params.callback.onCopyClick(params.id) },
|
||||
onShareClick = params.callback::onShareClick,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ 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.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH12
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.SpacerW12
|
||||
|
|
@ -36,6 +37,7 @@ import com.tangem.core.ui.components.atoms.text.TextEllipsis
|
|||
import com.tangem.core.ui.components.buttons.small.TangemIconButton
|
||||
import com.tangem.core.ui.components.icons.identicon.IdentIcon
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
|
|
@ -78,7 +80,6 @@ internal fun TokenReceiveAssetsContent(assetsUM: ReceiveAssetsUM) {
|
|||
onOpenQrCodeClick = assetsUM.onOpenQrCodeClick,
|
||||
addresses = assetsUM.addresses,
|
||||
snackbarHostState = snackbarHostState,
|
||||
fullName = assetsUM.fullName,
|
||||
)
|
||||
|
||||
if (assetsUM.isEnsResultLoading) {
|
||||
|
|
@ -125,7 +126,6 @@ private fun AddressBlock(
|
|||
onCopyClick: (id: Int) -> Unit,
|
||||
addresses: ImmutableMap<Int, ReceiveAddress>,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
fullName: String,
|
||||
) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
|
@ -133,8 +133,8 @@ private fun AddressBlock(
|
|||
val resources = context.resources
|
||||
|
||||
addresses.entries.toList().fastForEach { entry ->
|
||||
when (entry.value.type) {
|
||||
is ReceiveAddress.Type.Default -> {
|
||||
when (val type = entry.value.type) {
|
||||
is ReceiveAddress.Type.Primary -> {
|
||||
key(entry.key) {
|
||||
AddressItem(
|
||||
onCopyClick = {
|
||||
|
|
@ -152,8 +152,8 @@ private fun AddressBlock(
|
|||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
onOpenQrCodeClick(entry.key)
|
||||
},
|
||||
fullName = fullName,
|
||||
address = entry.value.value,
|
||||
primaryType = type,
|
||||
)
|
||||
SpacerH8()
|
||||
}
|
||||
|
|
@ -184,9 +184,9 @@ private fun AddressBlock(
|
|||
@Composable
|
||||
private fun AddressItem(
|
||||
onOpenQrCodeClick: () -> Unit,
|
||||
fullName: String,
|
||||
onCopyClick: () -> Unit,
|
||||
address: String,
|
||||
primaryType: ReceiveAddress.Type.Primary,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Card(
|
||||
|
|
@ -195,52 +195,68 @@ private fun AddressItem(
|
|||
colors = CardDefaults.cardColors(containerColor = TangemTheme.colors.background.action),
|
||||
onClick = onOpenQrCodeClick,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 14.dp, horizontal = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
Column(
|
||||
modifier = Modifier.padding(vertical = 14.dp, horizontal = 12.dp),
|
||||
) {
|
||||
IdentIcon(
|
||||
address = address,
|
||||
modifier = Modifier
|
||||
.size(size = 36.dp)
|
||||
.clip(shape = RoundedCornerShape(18.dp)),
|
||||
)
|
||||
|
||||
SpacerW12()
|
||||
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
EllipsisText(
|
||||
text = stringResourceSafe(R.string.domain_receive_assets_onboarding_network_name, fullName),
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
)
|
||||
|
||||
EllipsisText(
|
||||
text = address,
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
)
|
||||
when (primaryType) {
|
||||
is ReceiveAddress.Type.Primary.Default -> {
|
||||
primaryType.title?.let {
|
||||
Text(
|
||||
text = it.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
SpacerH(12.dp)
|
||||
}
|
||||
}
|
||||
is ReceiveAddress.Type.Primary.Legacy -> Unit
|
||||
}
|
||||
|
||||
SpacerW12()
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
IdentIcon(
|
||||
address = address,
|
||||
modifier = Modifier
|
||||
.size(size = 36.dp)
|
||||
.clip(shape = RoundedCornerShape(18.dp)),
|
||||
)
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_qrcode_new_24,
|
||||
onClick = onOpenQrCodeClick,
|
||||
)
|
||||
SpacerW12()
|
||||
|
||||
SpacerW8()
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
EllipsisText(
|
||||
text = primaryType.displayName.resolveReference(),
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
)
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_copy_new_24,
|
||||
onClick = onCopyClick,
|
||||
)
|
||||
EllipsisText(
|
||||
text = address,
|
||||
ellipsis = TextEllipsis.Middle,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
style = TangemTheme.typography.caption2,
|
||||
)
|
||||
}
|
||||
|
||||
SpacerW12()
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_qrcode_new_24,
|
||||
onClick = onOpenQrCodeClick,
|
||||
)
|
||||
|
||||
SpacerW8()
|
||||
|
||||
TangemIconButton(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size28),
|
||||
iconRes = R.drawable.ic_copy_new_24,
|
||||
onClick = onCopyClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -318,8 +334,9 @@ private fun Preview_TokenReceiveAssetsContent(
|
|||
private class TokenReceiveAssetsContentProvider : PreviewParameterProvider<ReceiveAssetsUM> {
|
||||
val address = ReceiveAddress(
|
||||
value = "0xe5178c7d4d0e861ed2e9414e045b501226b0de8d",
|
||||
type = ReceiveAddress.Type.Default(
|
||||
type = ReceiveAddress.Type.Primary.Default(
|
||||
displayName = stringReference("Etherium address"),
|
||||
title = null,
|
||||
),
|
||||
)
|
||||
private val config = ReceiveAssetsUM(
|
||||
|
|
@ -338,7 +355,6 @@ private class TokenReceiveAssetsContentProvider : PreviewParameterProvider<Recei
|
|||
onCopyClick = {},
|
||||
onOpenQrCodeClick = {},
|
||||
isEnsResultLoading = true,
|
||||
fullName = "Etherium",
|
||||
)
|
||||
|
||||
override val values: Sequence<ReceiveAssetsUM>
|
||||
|
|
|
|||
|
|
@ -12,5 +12,4 @@ internal data class ReceiveAssetsUM(
|
|||
val onCopyClick: (id: Int) -> Unit,
|
||||
val isEnsResultLoading: Boolean,
|
||||
val notificationConfigs: ImmutableList<NotificationUM>,
|
||||
val fullName: String,
|
||||
)
|
||||
|
|
@ -1089,16 +1089,17 @@ internal class TokenDetailsModel @Inject constructor(
|
|||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Ens,
|
||||
value = ens,
|
||||
displayName = ens,
|
||||
),
|
||||
)
|
||||
}
|
||||
addresses.availableAddresses.map { address ->
|
||||
add(
|
||||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Default,
|
||||
nameService = when (address.type) {
|
||||
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
|
||||
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
|
||||
},
|
||||
value = address.value,
|
||||
displayName = "${cryptoCurrency.name} (${cryptoCurrency.symbol})",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -673,16 +673,17 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
|
|||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Ens,
|
||||
value = ens,
|
||||
displayName = ens,
|
||||
),
|
||||
)
|
||||
}
|
||||
networkAddress.availableAddresses.map { address ->
|
||||
add(
|
||||
ReceiveAddressModel(
|
||||
nameService = ReceiveAddressModel.NameService.Default,
|
||||
nameService = when (address.type) {
|
||||
NetworkAddress.Address.Type.Primary -> ReceiveAddressModel.NameService.Default
|
||||
NetworkAddress.Address.Type.Secondary -> ReceiveAddressModel.NameService.Legacy
|
||||
},
|
||||
value = address.value,
|
||||
displayName = "${cryptoCurrencyStatus.currency.name} (${cryptoCurrencyStatus.currency.symbol})",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue