Updated on 2026-08-14
This commit is contained in:
parent
4f47d876ed
commit
e125eff471
40 changed files with 251 additions and 119 deletions
|
|
@ -14,6 +14,8 @@ import com.tangem.feature.wallet.presentation.wallet.domain.IsWalletNFTEnabledSy
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.features.nft.NFTFeatureToggles
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.sdk.api.featuretoggles.CardSdkFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -172,8 +174,16 @@ internal object WalletsDomainModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideGetCardImageUseCase(onlineCardVerifier: OnlineCardVerifier): GetCardImageUseCase {
|
||||
return GetCardImageUseCase(verifier = onlineCardVerifier)
|
||||
fun provideGetCardImageUseCase(
|
||||
onlineCardVerifier: OnlineCardVerifier,
|
||||
cardArtworksProvider: CardArtworksProvider,
|
||||
cardSdkFeatureToggles: CardSdkFeatureToggles,
|
||||
): GetCardImageUseCase {
|
||||
return GetCardImageUseCase(
|
||||
verifier = onlineCardVerifier,
|
||||
cardArtworksProvider = cardArtworksProvider,
|
||||
cardSdkFeatureToggles = cardSdkFeatureToggles,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.common.TwinCardNumber
|
|||
import com.tangem.domain.common.getTwinCardNumber
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.wallets.models.Artwork
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.operations.attestation.api.models.CardVerifyAndGetInfo
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ suspend fun CardDTO.getOrLoadCardArtworkUrl(
|
|||
if (artworkId.isNullOrEmpty()) {
|
||||
ifAnyError()
|
||||
} else {
|
||||
OnlineCardVerifier.getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId)
|
||||
CardArtworksProvider.getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ internal data class UserWalletPublicInformation(
|
|||
val name: String,
|
||||
@Json(name = "walletId")
|
||||
val walletId: UserWalletId,
|
||||
@Json(name = "artworkUrl")
|
||||
val artworkUrl: String,
|
||||
@Json(name = "cardsInWallet")
|
||||
val cardsInWallet: Set<String>,
|
||||
@Json(name = "scanResponse")
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ internal val UserWallet.publicInformation: UserWalletPublicInformation
|
|||
get() = UserWalletPublicInformation(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
artworkUrl = artworkUrl,
|
||||
cardsInWallet = cardsInWallet,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
scanResponse = scanResponse.copy(
|
||||
|
|
@ -31,7 +30,6 @@ internal fun UserWalletPublicInformation.toUserWallet(): UserWallet {
|
|||
return UserWallet(
|
||||
name = name,
|
||||
walletId = walletId,
|
||||
artworkUrl = artworkUrl,
|
||||
cardsInWallet = cardsInWallet,
|
||||
scanResponse = scanResponse,
|
||||
isMultiCurrency = isMultiCurrency,
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.BackupValidator
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.CreateProductWalletTaskResponse
|
||||
import com.tangem.sdk.extensions.localizedDescriptionRes
|
||||
|
|
@ -250,7 +250,7 @@ private suspend fun loadArtworkForCard(cardId: String, cardPublicKey: ByteArray,
|
|||
if (artworkId.isNullOrEmpty()) {
|
||||
defaultArtwork ?: Uri.EMPTY
|
||||
} else {
|
||||
Uri.parse(OnlineCardVerifier.getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId))
|
||||
Uri.parse(CardArtworksProvider.getUrlForArtwork(cardId, cardPublicKey.toHexString(), artworkId))
|
||||
}
|
||||
}
|
||||
is Result.Failure -> defaultArtwork ?: Uri.EMPTY
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
|||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.features.onboarding.v2.OnboardingV2FeatureToggles
|
||||
import com.tangem.features.onramp.OnrampFeatureToggles
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.tap.domain.scanCard.CardScanningFeatureToggles
|
||||
import com.tangem.tap.domain.walletconnect2.domain.LegacyWalletConnectRepository
|
||||
|
|
@ -76,5 +77,6 @@ data class DaggerGraphState(
|
|||
val settingsManager: SettingsManager? = null,
|
||||
val uiMessageSender: UiMessageSender? = null,
|
||||
val onlineCardVerifier: OnlineCardVerifier? = null,
|
||||
val cardArworksProvider: CardArtworksProvider? = null,
|
||||
val userWalletBuilderFactory: UserWalletBuilder.Factory? = null,
|
||||
) : StateType
|
||||
|
|
@ -39,7 +39,6 @@ internal class DefaultDerivationsRepositoryTest {
|
|||
private val defaultUserWallet = UserWallet(
|
||||
name = "",
|
||||
walletId = defaultUserWalletId,
|
||||
artworkUrl = "",
|
||||
cardsInWallet = setOf(),
|
||||
isMultiCurrency = false,
|
||||
scanResponse = MockScanResponseFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()),
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ internal class BiometricUserWalletsListManagerTest(private val model: Model) {
|
|||
return UserWallet(
|
||||
name = "Wallet $id",
|
||||
walletId = UserWalletId(stringValue = id),
|
||||
artworkUrl = "",
|
||||
cardsInWallet = emptySet(),
|
||||
isMultiCurrency = true,
|
||||
hasBackupError = false,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ object MockUserWalletFactory {
|
|||
return UserWallet(
|
||||
walletId = userWalletId,
|
||||
name = "Wallet 1",
|
||||
artworkUrl = "",
|
||||
cardsInWallet = emptySet(),
|
||||
scanResponse = scanResponse,
|
||||
isMultiCurrency = scanResponse.cardTypesResolver.isMultiwalletAllowed(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import androidx.compose.foundation.layout.*
|
|||
import androidx.compose.material3.CardColors
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -61,7 +61,7 @@ fun UserWalletItem(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
) {
|
||||
CardImage(imageUrl = state.imageUrl)
|
||||
CardImage(state.imageState)
|
||||
NameAndInfo(
|
||||
modifier = Modifier.weight(1f),
|
||||
name = state.name,
|
||||
|
|
@ -147,39 +147,49 @@ private fun NameAndInfo(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun CardImage(imageUrl: String, modifier: Modifier = Modifier) {
|
||||
private fun CardImage(imageState: UserWalletItemUM.ImageState, modifier: Modifier = Modifier) {
|
||||
val imageModifier = modifier
|
||||
.width(TangemTheme.dimens.size24)
|
||||
.height(TangemTheme.dimens.size36)
|
||||
.clip(TangemTheme.shapes.roundedCornersSmall)
|
||||
|
||||
SubcomposeAsyncImage(
|
||||
modifier = imageModifier,
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.transformations(RotationTransformation(angle = 90f))
|
||||
.size(
|
||||
width = with(LocalDensity.current) { TangemTheme.dimens.size36.roundToPx() },
|
||||
height = with(LocalDensity.current) { TangemTheme.dimens.size24.roundToPx() },
|
||||
)
|
||||
.data(imageUrl)
|
||||
.crossfade(enable = true)
|
||||
.allowHardware(enable = false)
|
||||
.build(),
|
||||
loading = {
|
||||
when (imageState) {
|
||||
is UserWalletItemUM.ImageState.Loading -> {
|
||||
RectangleShimmer(
|
||||
modifier = imageModifier,
|
||||
radius = TangemTheme.dimens.size2,
|
||||
)
|
||||
},
|
||||
error = {
|
||||
Image(
|
||||
}
|
||||
is UserWalletItemUM.ImageState.Image -> {
|
||||
SubcomposeAsyncImage(
|
||||
modifier = imageModifier,
|
||||
imageVector = ImageVector.vectorResource(R.drawable.img_card_wallet_2_gray_22_36),
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.transformations(RotationTransformation(angle = 90f))
|
||||
.size(
|
||||
width = with(LocalDensity.current) { TangemTheme.dimens.size36.roundToPx() },
|
||||
height = with(LocalDensity.current) { TangemTheme.dimens.size24.roundToPx() },
|
||||
)
|
||||
.data(imageState.artwork.verifiedArtwork?.toByteArray() ?: imageState.artwork.defaultUrl)
|
||||
.crossfade(enable = true)
|
||||
.allowHardware(enable = false)
|
||||
.build(),
|
||||
loading = {
|
||||
RectangleShimmer(
|
||||
modifier = imageModifier,
|
||||
radius = TangemTheme.dimens.size2,
|
||||
)
|
||||
},
|
||||
error = {
|
||||
Image(
|
||||
modifier = imageModifier,
|
||||
imageVector = ImageVector.vectorResource(R.drawable.img_card_wallet_2_gray_22_36),
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -215,7 +225,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
name = stringReference("My Wallet"),
|
||||
information = getInformation(cardCount = 1),
|
||||
balance = UserWalletItemUM.Balance.Locked,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
|
|
@ -224,7 +233,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
name = stringReference("Old wallet"),
|
||||
information = getInformation(cardCount = 2),
|
||||
balance = UserWalletItemUM.Balance.Hidden,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
endIcon = UserWalletItemUM.EndIcon.Arrow,
|
||||
|
|
@ -234,7 +242,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Failed,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
|
|
@ -244,7 +251,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
|
|
@ -257,7 +263,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
value = "1.2345 BTC",
|
||||
isFlickering = false,
|
||||
),
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
|
|
@ -270,7 +275,6 @@ private class UserWalletItemUMPreviewProvider : PreviewParameterProvider<UserWal
|
|||
value = "1.2345 BTC",
|
||||
isFlickering = true,
|
||||
),
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
endIcon = UserWalletItemUM.EndIcon.Checkmark,
|
||||
onClick = {},
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.common.ui.userwallet.converter
|
|||
|
||||
import com.tangem.common.ui.R
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
|
|
@ -9,6 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.fiat
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.common.util.getCardsCount
|
||||
import com.tangem.domain.models.ArtworkModel
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -31,6 +33,7 @@ class UserWalletItemUMConverter(
|
|||
private val balance: TotalFiatBalance? = null,
|
||||
private val isBalanceHidden: Boolean = false,
|
||||
private val endIcon: UserWalletItemUM.EndIcon = UserWalletItemUM.EndIcon.None,
|
||||
private val artwork: ArtworkModel? = null,
|
||||
) : Converter<UserWallet, UserWalletItemUM> {
|
||||
|
||||
override fun convert(value: UserWallet): UserWalletItemUM {
|
||||
|
|
@ -40,10 +43,12 @@ class UserWalletItemUMConverter(
|
|||
name = stringReference(name),
|
||||
information = getInfo(userWallet = this),
|
||||
balance = getBalanceInfo(userWallet = this),
|
||||
imageUrl = artworkUrl,
|
||||
isEnabled = !isLocked,
|
||||
endIcon = endIcon,
|
||||
onClick = { onClick(value.walletId) },
|
||||
imageState = artwork?.let {
|
||||
UserWalletItemUM.ImageState.Image(ArtworkUM(it.verifiedArtwork, it.defaultUrl))
|
||||
} ?: UserWalletItemUM.ImageState.Loading,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.common.ui.userwallet.state
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
|
@ -10,7 +11,7 @@ data class UserWalletItemUM(
|
|||
val name: TextReference,
|
||||
val information: TextReference,
|
||||
val balance: Balance,
|
||||
val imageUrl: String,
|
||||
val imageState: ImageState = ImageState.Loading,
|
||||
val isEnabled: Boolean,
|
||||
val endIcon: EndIcon = EndIcon.None,
|
||||
val onClick: () -> Unit,
|
||||
|
|
@ -36,4 +37,14 @@ data class UserWalletItemUM(
|
|||
val isFlickering: Boolean,
|
||||
) : Balance()
|
||||
}
|
||||
|
||||
@Immutable
|
||||
sealed class ImageState {
|
||||
|
||||
data object Loading : ImageState()
|
||||
|
||||
data class Image(
|
||||
val artwork: ArtworkUM,
|
||||
) : ImageState()
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,10 @@
|
|||
"name": "NOTE_REFACTORING_ENABLED",
|
||||
"version": "5.23.0"
|
||||
},
|
||||
{
|
||||
"name": "NEW_ARTWORK_LOADING",
|
||||
"version": "5.24.0"
|
||||
},
|
||||
{
|
||||
"name": "NEW_ATTESTATION_ENABLED",
|
||||
"version": "5.23.0"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.core.ui.components.artwork
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Immutable
|
||||
data class ArtworkUM(
|
||||
val verifiedArtwork: ImmutableList<Byte>? = null,
|
||||
val defaultUrl: String,
|
||||
) {
|
||||
|
||||
constructor(bytes: ByteArray?, defaultUrl: String) : this(
|
||||
verifiedArtwork = bytes?.toList()?.toImmutableList(),
|
||||
defaultUrl = defaultUrl,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.domain.models
|
||||
|
||||
data class ArtworkModel(
|
||||
val verifiedArtwork: ByteArray? = null,
|
||||
val defaultUrl: String,
|
||||
)
|
||||
|
|
@ -10,7 +10,6 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
*
|
||||
* @property name User wallet name
|
||||
* @property walletId User wallet [UserWalletId]
|
||||
* @property artworkUrl User wallet card artwork URL
|
||||
* @property cardsInWallet List of cards IDs assigned with this user's wallet. The list will be empty if the wallet
|
||||
* has been backed up on another device.
|
||||
* @property isMultiCurrency Indicates whether this user wallet can work with more than one currency
|
||||
|
|
@ -22,8 +21,6 @@ data class UserWallet(
|
|||
val name: String,
|
||||
@Json(name = "walletId")
|
||||
val walletId: UserWalletId,
|
||||
@Json(name = "artworkUrl")
|
||||
val artworkUrl: String,
|
||||
@Json(name = "cardsInWallet")
|
||||
val cardsInWallet: Set<String>,
|
||||
@Json(name = "isMultiCurrency")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.domain.models.scan.CardDTO
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -13,7 +12,6 @@ import dagger.assisted.AssistedInject
|
|||
class UserWalletBuilder @AssistedInject constructor(
|
||||
@Assisted private val scanResponse: ScanResponse,
|
||||
private val generateWalletNameUseCase: GenerateWalletNameUseCase,
|
||||
private val getCardImageUseCase: GetCardImageUseCase,
|
||||
) {
|
||||
private var backupCardsIds: Set<String> = emptySet()
|
||||
private var hasBackupError: Boolean = false
|
||||
|
|
@ -38,7 +36,7 @@ class UserWalletBuilder @AssistedInject constructor(
|
|||
this.hasBackupError = hasBackupError
|
||||
}
|
||||
|
||||
suspend fun build(): UserWallet? {
|
||||
fun build(): UserWallet? {
|
||||
return with(scanResponse) {
|
||||
UserWalletIdBuilder.scanResponse(scanResponse)
|
||||
.build()
|
||||
|
|
@ -50,7 +48,6 @@ class UserWalletBuilder @AssistedInject constructor(
|
|||
isBackupNotAllowed = card.isBackupNotAllowed,
|
||||
isStartToCoin = cardTypesResolver.isStart2Coin(),
|
||||
),
|
||||
artworkUrl = getCardImageUseCase.invoke(card.cardId, card.cardPublicKey),
|
||||
cardsInWallet = backupCardsIds.plus(card.cardId),
|
||||
scanResponse = this,
|
||||
isMultiCurrency = cardTypesResolver.isMultiwalletAllowed(),
|
||||
|
|
|
|||
|
|
@ -4,8 +4,12 @@ import com.tangem.common.extensions.toHexString
|
|||
import com.tangem.common.services.Result
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.domain.common.TwinsHelper
|
||||
import com.tangem.domain.models.ArtworkModel
|
||||
import com.tangem.domain.wallets.models.Artwork
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.sdk.api.featuretoggles.CardSdkFeatureToggles
|
||||
|
||||
/**
|
||||
* Use case for getting card image url
|
||||
|
|
@ -14,7 +18,11 @@ import com.tangem.operations.attestation.OnlineCardVerifier
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class GetCardImageUseCase(private val verifier: OnlineCardVerifier) {
|
||||
class GetCardImageUseCase(
|
||||
private val verifier: OnlineCardVerifier,
|
||||
private val cardArtworksProvider: CardArtworksProvider,
|
||||
private val cardSdkFeatureToggles: CardSdkFeatureToggles,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Get card image url
|
||||
|
|
@ -22,14 +30,30 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier) {
|
|||
* @param cardId card id
|
||||
* @param cardPublicKey card public key
|
||||
*/
|
||||
suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray): String {
|
||||
suspend operator fun invoke(cardId: String, cardPublicKey: ByteArray, size: ArtworkSize): ArtworkModel {
|
||||
return if (cardSdkFeatureToggles.isNewArtworkLoadingEnabled) {
|
||||
val result = cardArtworksProvider.getArtwork(
|
||||
cardId = cardId,
|
||||
cardPublicKey = cardPublicKey,
|
||||
size = size,
|
||||
)
|
||||
when (result) {
|
||||
is Result.Failure -> ArtworkModel(null, getFallbackArtworkUrl(cardId))
|
||||
is Result.Success -> ArtworkModel(result.data, getFallbackArtworkUrl(cardId))
|
||||
}
|
||||
} else {
|
||||
ArtworkModel(null, getLegacyArtwork(cardId, cardPublicKey))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getLegacyArtwork(cardId: String, cardPublicKey: ByteArray): String {
|
||||
return when (val result = verifier.getCardInfo(cardId, cardPublicKey)) {
|
||||
is Result.Success -> {
|
||||
val artworkId = result.data.artwork?.id
|
||||
if (artworkId.isNullOrEmpty()) {
|
||||
getFallbackArtworkUrl(cardId)
|
||||
} else {
|
||||
OnlineCardVerifier.getUrlForArtwork(
|
||||
CardArtworksProvider.getUrlForArtwork(
|
||||
cardId = cardId,
|
||||
cardPublicKey = cardPublicKey.toHexString(),
|
||||
artworkId = artworkId,
|
||||
|
|
@ -41,8 +65,6 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier) {
|
|||
}
|
||||
}
|
||||
|
||||
fun getDefaultFallbackUrl(): String = Artwork.DEFAULT_IMG_URL
|
||||
|
||||
private fun getFallbackArtworkUrl(cardId: String): String {
|
||||
return when {
|
||||
cardId.startsWith(Artwork.SERGIO_CARD_ID) -> Artwork.SERGIO_CARD_URL
|
||||
|
|
@ -50,7 +72,7 @@ class GetCardImageUseCase(private val verifier: OnlineCardVerifier) {
|
|||
else -> when (TwinsHelper.getTwinCardNumber(cardId)) {
|
||||
TwinCardNumber.First -> Artwork.TWIN_CARD_1_URL
|
||||
TwinCardNumber.Second -> Artwork.TWIN_CARD_2_URL
|
||||
else -> getDefaultFallbackUrl()
|
||||
else -> Artwork.DEFAULT_IMG_URL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ internal class PreviewUserWalletListComponent : UserWalletListComponent {
|
|||
name = stringReference("My Wallet"),
|
||||
information = getInformation(cardCount = 1),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
|
|
@ -38,7 +37,6 @@ internal class PreviewUserWalletListComponent : UserWalletListComponent {
|
|||
name = stringReference("Old wallet"),
|
||||
information = getInformation(cardCount = 2),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
|
|
@ -47,7 +45,6 @@ internal class PreviewUserWalletListComponent : UserWalletListComponent {
|
|||
name = stringReference("Multi Card"),
|
||||
information = getInformation(cardCount = 3),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = false,
|
||||
onClick = {},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -18,19 +18,23 @@ import com.tangem.domain.core.lce.Lce
|
|||
import com.tangem.domain.core.lce.lce
|
||||
import com.tangem.domain.core.utils.getOrElse
|
||||
import com.tangem.domain.core.utils.toLce
|
||||
import com.tangem.domain.models.ArtworkModel
|
||||
import com.tangem.domain.tokens.GetWalletTotalBalanceUseCase
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.TotalFiatBalance
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.features.details.impl.R
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class UserWalletsFetcher @Inject constructor(
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
|
|
@ -39,8 +43,11 @@ internal class UserWalletsFetcher @Inject constructor(
|
|||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val router: Router,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val getCardImageUseCase: GetCardImageUseCase,
|
||||
) {
|
||||
|
||||
private var loadedArtworks: HashMap<UserWalletId, ArtworkModel> = hashMapOf()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val userWallets: Flow<ImmutableList<UserWalletItemUM>> = getWalletsUseCase().transformLatest { wallets ->
|
||||
val uiModels = UserWalletItemUMConverter(onClick = ::navigateToWalletSettings).convertList(wallets)
|
||||
|
|
@ -52,12 +59,14 @@ internal class UserWalletsFetcher @Inject constructor(
|
|||
flow = getSelectedAppCurrencyUseCase().distinctUntilChanged(),
|
||||
flow2 = getBalanceHidingSettingsUseCase().distinctUntilChanged(),
|
||||
flow3 = getWalletTotalBalanceUseCase(wallets.map(UserWallet::walletId)).distinctUntilChanged(),
|
||||
) { maybeAppCurrency, balanceHidingSettings, maybeBalances ->
|
||||
flow4 = loadArtworks(wallets),
|
||||
) { maybeAppCurrency, balanceHidingSettings, maybeBalances, artworks ->
|
||||
val models = createUiModels(
|
||||
wallets = wallets,
|
||||
maybeAppCurrency = maybeAppCurrency,
|
||||
maybeBalances = maybeBalances,
|
||||
balanceHidingSettings = balanceHidingSettings,
|
||||
artworks = artworks,
|
||||
).getOrElse(
|
||||
ifLoading = { return@combine },
|
||||
ifError = {
|
||||
|
|
@ -72,11 +81,27 @@ internal class UserWalletsFetcher @Inject constructor(
|
|||
}.collect()
|
||||
}
|
||||
|
||||
private fun loadArtworks(wallets: List<UserWallet>): Flow<HashMap<UserWalletId, ArtworkModel>> {
|
||||
return flow {
|
||||
emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish
|
||||
wallets.forEach { wallet ->
|
||||
val artwork = getCardImageUseCase(
|
||||
cardId = wallet.cardId,
|
||||
cardPublicKey = wallet.scanResponse.card.cardPublicKey,
|
||||
size = ArtworkSize.SMALL,
|
||||
)
|
||||
loadedArtworks[wallet.walletId] = artwork
|
||||
emit(loadedArtworks)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createUiModels(
|
||||
wallets: List<UserWallet>,
|
||||
maybeAppCurrency: Either<SelectedAppCurrencyError, AppCurrency>,
|
||||
maybeBalances: Lce<TokenListError, Map<UserWalletId, TotalFiatBalance>>,
|
||||
balanceHidingSettings: BalanceHidingSettings,
|
||||
artworks: HashMap<UserWalletId, ArtworkModel>,
|
||||
): Lce<Error, ImmutableList<UserWalletItemUM>> = lce {
|
||||
val balances = withError(
|
||||
transform = { Error.UnableToGetBalances },
|
||||
|
|
@ -99,6 +124,7 @@ internal class UserWalletsFetcher @Inject constructor(
|
|||
appCurrency = appCurrency,
|
||||
balance = balance,
|
||||
isBalanceHidden = balanceHidingSettings.isBalanceHidden,
|
||||
artwork = artworks[userWallet.walletId],
|
||||
)
|
||||
.convert(userWallet)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ internal class PreviewAddToPortfolioBSContentProvider : PreviewParameterProvider
|
|||
name = stringReference("Wallet 1"),
|
||||
information = stringReference("3 cards"),
|
||||
balance = UserWalletItemUM.Balance.Loading,
|
||||
imageUrl = "",
|
||||
isEnabled = true,
|
||||
endIcon = UserWalletItemUM.EndIcon.Arrow,
|
||||
onClick = {},
|
||||
|
|
|
|||
|
|
@ -7,14 +7,15 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
|
||||
@Composable
|
||||
internal fun WalletCard(url: String?, modifier: Modifier = Modifier) {
|
||||
internal fun WalletCard(artwork: ArtworkUM?, modifier: Modifier = Modifier) {
|
||||
AsyncImage(
|
||||
modifier = modifier,
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(url)
|
||||
.data(artwork?.verifiedArtwork ?: artwork?.defaultUrl)
|
||||
.crossfade(true)
|
||||
.build(),
|
||||
placeholder = painterResource(R.drawable.card_placeholder_black),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ProductType
|
||||
import com.tangem.domain.onboarding.repository.OnboardingRepository
|
||||
|
|
@ -16,6 +17,7 @@ import com.tangem.features.onboarding.v2.common.ui.interruptBackupDialog
|
|||
import com.tangem.features.onboarding.v2.multiwallet.impl.child.MultiWalletChildParams
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.model.OnboardingMultiWalletState.FinalizeStage
|
||||
import com.tangem.features.onboarding.v2.multiwallet.impl.ui.state.OnboardingMultiWalletUM
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.sdk.api.BackupServiceHolder
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -78,18 +80,26 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
backups.collectLatest { backup ->
|
||||
when {
|
||||
_uiState.value.artwork2Url == null && backup.card2 != null -> {
|
||||
_uiState.value.artwork2 == null && backup.card2 != null -> {
|
||||
val artwork =
|
||||
getCardImageUseCase.invoke(backup.card2.cardId, backup.card2.cardPublicKey)
|
||||
getCardImageUseCase.invoke(
|
||||
cardId = backup.card2.cardId,
|
||||
cardPublicKey = backup.card2.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(artwork2Url = artwork)
|
||||
it.copy(artwork2 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
}
|
||||
}
|
||||
_uiState.value.artwork3Url == null && backup.card3 != null -> {
|
||||
_uiState.value.artwork3 == null && backup.card3 != null -> {
|
||||
val artwork =
|
||||
getCardImageUseCase.invoke(backup.card3.cardId, backup.card3.cardPublicKey)
|
||||
getCardImageUseCase.invoke(
|
||||
cardId = backup.card3.cardId,
|
||||
cardPublicKey = backup.card3.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(artwork3Url = artwork)
|
||||
it.copy(artwork3 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -156,12 +166,14 @@ internal class OnboardingMultiWalletModel @Inject constructor(
|
|||
private fun loadCardArtwork() {
|
||||
modelScope.launch {
|
||||
val artwork =
|
||||
getCardImageUseCase.invoke(params.scanResponse.card.cardId, params.scanResponse.card.cardPublicKey)
|
||||
getCardImageUseCase.invoke(
|
||||
cardId = params.scanResponse.card.cardId,
|
||||
cardPublicKey = params.scanResponse.card.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
)
|
||||
|
||||
if (artwork != getCardImageUseCase.getDefaultFallbackUrl()) {
|
||||
_uiState.update {
|
||||
it.copy(artwork1Url = artwork)
|
||||
}
|
||||
_uiState.update {
|
||||
it.copy(artwork1 = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ internal fun OnboardingMultiWallet(
|
|||
) {
|
||||
if (isSeedPhraseState.not()) {
|
||||
WalletArtworks(
|
||||
url1 = state.artwork1Url,
|
||||
url2 = state.artwork2Url,
|
||||
url3 = state.artwork3Url,
|
||||
artwork1 = state.artwork1,
|
||||
artwork2 = state.artwork2,
|
||||
artwork3 = state.artwork3,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 34.dp)
|
||||
.padding(top = 20.dp)
|
||||
|
|
@ -53,7 +53,7 @@ internal fun OnboardingMultiWallet(
|
|||
private fun Preview() {
|
||||
TangemThemePreview {
|
||||
OnboardingMultiWallet(
|
||||
state = OnboardingMultiWalletUM(artwork1Url = null),
|
||||
state = OnboardingMultiWalletUM(artwork1 = null),
|
||||
artworksState = WalletArtworksState.Folded,
|
||||
isSeedPhraseState = false,
|
||||
childContent = { md ->
|
||||
|
|
@ -73,7 +73,7 @@ private fun Preview() {
|
|||
private fun Preview2() {
|
||||
TangemThemePreview {
|
||||
OnboardingMultiWallet(
|
||||
state = OnboardingMultiWalletUM(artwork1Url = null),
|
||||
state = OnboardingMultiWalletUM(artwork1 = null),
|
||||
artworksState = WalletArtworksState.Folded,
|
||||
isSeedPhraseState = true,
|
||||
childContent = { md ->
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.compose.ui.zIndex
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.onboarding.v2.common.ui.WalletCard
|
||||
|
|
@ -57,9 +58,9 @@ sealed class WalletArtworksState {
|
|||
|
||||
@Composable
|
||||
fun WalletArtworks(
|
||||
url1: String?,
|
||||
url2: String?,
|
||||
url3: String?,
|
||||
artwork1: ArtworkUM?,
|
||||
artwork2: ArtworkUM?,
|
||||
artwork3: ArtworkUM?,
|
||||
state: WalletArtworksState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -120,9 +121,9 @@ fun WalletArtworks(
|
|||
}
|
||||
|
||||
AnimatedWalletCards(
|
||||
url1 = url1,
|
||||
url2 = url2,
|
||||
url3 = url3,
|
||||
artwork1 = artwork1,
|
||||
artwork2 = artwork2,
|
||||
artwork3 = artwork3,
|
||||
modifier = Modifier
|
||||
.widthIn(max = 450.dp)
|
||||
.matchParentSize(),
|
||||
|
|
@ -152,9 +153,9 @@ private data class WalletCardTransitionState(
|
|||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
private fun AnimatedWalletCards(
|
||||
url1: String?,
|
||||
url2: String?,
|
||||
url3: String?,
|
||||
artwork1: ArtworkUM?,
|
||||
artwork2: ArtworkUM?,
|
||||
artwork3: ArtworkUM?,
|
||||
transition1: Transition<WalletCardTransitionState>,
|
||||
transition2: Transition<WalletCardTransitionState>,
|
||||
transition3: Transition<WalletCardTransitionState>,
|
||||
|
|
@ -199,7 +200,7 @@ private fun AnimatedWalletCards(
|
|||
scaleY = scaleY3
|
||||
rotationZ = rotation3
|
||||
},
|
||||
url = url3,
|
||||
artwork = artwork3,
|
||||
)
|
||||
|
||||
WalletCard(
|
||||
|
|
@ -217,7 +218,7 @@ private fun AnimatedWalletCards(
|
|||
scaleX = scaleX2
|
||||
scaleY = scaleY2
|
||||
},
|
||||
url = url2,
|
||||
artwork = artwork2,
|
||||
)
|
||||
|
||||
WalletCard(
|
||||
|
|
@ -234,7 +235,7 @@ private fun AnimatedWalletCards(
|
|||
translationY = translationY1
|
||||
rotationZ = rotation1
|
||||
},
|
||||
url = url1,
|
||||
artwork = artwork1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -447,9 +448,9 @@ private fun Preview() {
|
|||
var state: WalletArtworksState by remember { mutableStateOf(WalletArtworksState.Folded) }
|
||||
|
||||
WalletArtworks(
|
||||
url1 = null,
|
||||
url2 = null,
|
||||
url3 = null,
|
||||
artwork1 = null,
|
||||
artwork2 = null,
|
||||
artwork3 = null,
|
||||
state = state,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.features.onboarding.v2.multiwallet.impl.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
|
||||
internal data class OnboardingMultiWalletUM(
|
||||
val artwork1Url: String? = null,
|
||||
val artwork2Url: String? = null,
|
||||
val artwork3Url: String? = null,
|
||||
val artwork1: ArtworkUM? = null,
|
||||
val artwork2: ArtworkUM? = null,
|
||||
val artwork3: ArtworkUM? = null,
|
||||
)
|
||||
|
|
@ -5,6 +5,7 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.builder.UserWalletBuilder
|
||||
|
|
@ -93,9 +94,11 @@ internal class OnboardingNoteCreateWalletModel @Inject constructor(
|
|||
|
||||
private fun observeArtwork() {
|
||||
modelScope.launch {
|
||||
params.childParams.commonState.collect {
|
||||
params.childParams.commonState.collect { state ->
|
||||
_uiState.value = _uiState.value.copy(
|
||||
artworkUrl = it.cardArtworkUrl,
|
||||
artwork = state.cardArtwork?.let {
|
||||
ArtworkUM(it.verifiedArtwork, it.defaultUrl)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ internal fun OnboardingNoteCreateWallet(state: OnboardingNoteCreateWalletUM, mod
|
|||
verticalArrangement = Arrangement.Bottom,
|
||||
) {
|
||||
WalletArtworks(
|
||||
url1 = state.artworkUrl,
|
||||
url2 = null,
|
||||
url3 = null,
|
||||
artwork1 = state.artwork,
|
||||
artwork2 = null,
|
||||
artwork3 = null,
|
||||
modifier = Modifier
|
||||
.padding(top = 64.dp)
|
||||
.padding(horizontal = 24.dp)
|
||||
|
|
@ -86,7 +86,7 @@ private fun OnboardingNoteCreatePreview() {
|
|||
TangemThemePreview {
|
||||
OnboardingNoteCreateWallet(
|
||||
state = OnboardingNoteCreateWalletUM(
|
||||
artworkUrl = null,
|
||||
artwork = null,
|
||||
createWalletInProgress = false,
|
||||
onCreateClick = {},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.child.create.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
|
||||
data class OnboardingNoteCreateWalletUM(
|
||||
val artworkUrl: String? = null,
|
||||
val artwork: ArtworkUM? = null,
|
||||
val createWalletInProgress: Boolean = false,
|
||||
val onCreateClick: () -> Unit = {},
|
||||
)
|
||||
|
|
@ -129,7 +129,7 @@ internal class OnboardingNoteTopUpModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
params.childParams.commonState.collect {
|
||||
_uiState.value = _uiState.value.copy(
|
||||
cardArtworkUrl = it.cardArtworkUrl,
|
||||
cardArtwork = it.cardArtwork,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.LocalTangemShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -21,11 +22,12 @@ import com.tangem.features.onboarding.v2.common.ui.RefreshButton
|
|||
import com.tangem.features.onboarding.v2.common.ui.WalletCard
|
||||
import com.tangem.features.onboarding.v2.impl.R
|
||||
import com.valentinilk.shimmer.shimmer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun OnboardingNoteTopUpHeader(
|
||||
balance: String,
|
||||
cardArtworkUrl: String?,
|
||||
cardArtwork: ArtworkUM?,
|
||||
isRefreshing: Boolean,
|
||||
onRefreshBalanceClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -77,7 +79,7 @@ fun OnboardingNoteTopUpHeader(
|
|||
}
|
||||
WalletCard(
|
||||
modifier = Modifier.width(120.dp).align(Alignment.TopCenter),
|
||||
url = cardArtworkUrl,
|
||||
artwork = cardArtwork,
|
||||
)
|
||||
RefreshButton(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
|
|
@ -93,7 +95,7 @@ private fun OnboardinNoteTopUpHeaderPreview() {
|
|||
TangemThemePreview {
|
||||
OnboardingNoteTopUpHeader(
|
||||
balance = "0.00000001 BTC",
|
||||
cardArtworkUrl = "",
|
||||
cardArtwork = ArtworkUM(null as ImmutableList<Byte>?, ""),
|
||||
onRefreshBalanceClick = {},
|
||||
isRefreshing = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fun OnboardingNoteTopUp(state: OnboardingNoteTopUpUM, modifier: Modifier = Modif
|
|||
) {
|
||||
OnboardingNoteTopUpHeader(
|
||||
balance = state.balance,
|
||||
cardArtworkUrl = state.cardArtworkUrl,
|
||||
cardArtwork = state.cardArtwork,
|
||||
onRefreshBalanceClick = state.onRefreshBalanceClick,
|
||||
isRefreshing = state.isRefreshing,
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.child.topup.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
|
||||
data class OnboardingNoteTopUpUM(
|
||||
val cardArtworkUrl: String? = null,
|
||||
val cardArtwork: ArtworkUM? = null,
|
||||
val availableForBuy: Boolean = false,
|
||||
val availableForBuyLoading: Boolean = true,
|
||||
val balance: String = "",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.onboarding.v2.note.impl.model
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -7,6 +8,6 @@ import com.tangem.domain.wallets.models.UserWallet
|
|||
internal data class OnboardingNoteCommonState(
|
||||
val scanResponse: ScanResponse,
|
||||
val userWallet: UserWallet? = null,
|
||||
val cardArtworkUrl: String? = null,
|
||||
val cardArtwork: ArtworkUM? = null,
|
||||
val cryptoCurrencyStatus: CryptoCurrencyStatus? = null,
|
||||
)
|
||||
|
|
@ -6,6 +6,7 @@ import com.tangem.core.decompose.model.Model
|
|||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
|
||||
import com.tangem.features.onboarding.v2.common.ui.exitOnboardingDialog
|
||||
|
|
@ -13,6 +14,7 @@ import com.tangem.features.onboarding.v2.note.api.OnboardingNoteComponent
|
|||
import com.tangem.features.onboarding.v2.note.impl.OnboardingNoteInnerNavigationState
|
||||
import com.tangem.features.onboarding.v2.note.impl.route.OnboardingNoteRoute
|
||||
import com.tangem.features.onboarding.v2.note.impl.route.stepNum
|
||||
import com.tangem.operations.attestation.ArtworkSize
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
|
@ -50,7 +52,7 @@ internal class OnboardingNoteModel @Inject constructor(
|
|||
val commonUiState: MutableStateFlow<OnboardingNoteCommonState> = _uiState
|
||||
|
||||
init {
|
||||
loadArtworkUrl()
|
||||
loadArtwork()
|
||||
}
|
||||
|
||||
fun updateStepForNewRoute(route: OnboardingNoteRoute) {
|
||||
|
|
@ -85,15 +87,16 @@ internal class OnboardingNoteModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadArtworkUrl() {
|
||||
private fun loadArtwork() {
|
||||
modelScope.launch {
|
||||
val cardInfo = params.scanResponse.card
|
||||
val url = getCardImageUseCase(
|
||||
val artwork = getCardImageUseCase.invoke(
|
||||
cardId = cardInfo.cardId,
|
||||
cardPublicKey = cardInfo.cardPublicKey,
|
||||
size = ArtworkSize.LARGE,
|
||||
)
|
||||
_uiState.update {
|
||||
it.copy(cardArtworkUrl = url)
|
||||
it.copy(cardArtwork = ArtworkUM(artwork.verifiedArtwork, artwork.defaultUrl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.util.fastForEach
|
|||
import androidx.compose.ui.zIndex
|
||||
import com.tangem.core.ui.components.SpacerH8
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
|
|
@ -212,7 +213,7 @@ private fun AnimatedTwinCards(
|
|||
scaleX = scaleX2
|
||||
scaleY = scaleY2
|
||||
},
|
||||
url = Artwork.TWIN_CARD_2_URL,
|
||||
artwork = ArtworkUM(defaultUrl = Artwork.TWIN_CARD_2_URL),
|
||||
)
|
||||
|
||||
WalletCard(
|
||||
|
|
@ -229,7 +230,7 @@ private fun AnimatedTwinCards(
|
|||
translationY = translationY1
|
||||
rotationZ = rotation1
|
||||
},
|
||||
url = Artwork.TWIN_CARD_1_URL,
|
||||
artwork = ArtworkUM(defaultUrl = Artwork.TWIN_CARD_1_URL),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
[versions]
|
||||
tangemBlockchainSdk = "develop-1009"
|
||||
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
|
||||
tangemCardSdk = "develop-451"
|
||||
tangemCardSdk = "develop-453"
|
||||
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
|
||||
tangemVico = "2.0.0-alpha.25-tangem-developments8"
|
||||
#tangemVico = "0.0.1" # Keep it! - used for local builds ^
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.sdk.api.di
|
||||
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.operations.attestation.CardArtworksProvider
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -14,4 +16,9 @@ internal object CardSdkModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideOnlineCardVerifier(): OnlineCardVerifier = OnlineCardVerifier()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideCardArtworksProvider(sdkRepository: CardSdkConfigRepository): CardArtworksProvider =
|
||||
CardArtworksProvider(sdkRepository.sdk.config.isTangemAttestationProdEnv)
|
||||
}
|
||||
|
|
@ -8,4 +8,6 @@ package com.tangem.sdk.api.featuretoggles
|
|||
interface CardSdkFeatureToggles {
|
||||
|
||||
val isNewAttestationEnabled: Boolean
|
||||
|
||||
val isNewArtworkLoadingEnabled: Boolean
|
||||
}
|
||||
|
|
@ -9,4 +9,7 @@ internal class DefaultCardSdkFeatureToggles @Inject constructor(
|
|||
|
||||
override val isNewAttestationEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "NEW_ATTESTATION_ENABLED")
|
||||
|
||||
override val isNewArtworkLoadingEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled(name = "NEW_ARTWORK_LOADING")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue