Updated on 2026-08-14
This commit is contained in:
parent
aea7f5f415
commit
c83ce2ada3
53 changed files with 1062 additions and 238 deletions
|
|
@ -12,6 +12,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.model.TokenActionsState
|
||||
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap
|
||||
|
|
@ -55,6 +56,8 @@ internal interface WalletContentClickIntents {
|
|||
fun onConfirmDisposeExpressStatus()
|
||||
|
||||
fun onDisposeExpressStatus()
|
||||
|
||||
fun onNFTClick(userWalletId: UserWalletId)
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
|
|
@ -235,4 +238,8 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
|
|||
}
|
||||
stateHolder.update(CloseBottomSheetTransformer(userWalletId))
|
||||
}
|
||||
|
||||
override fun onNFTClick(userWalletId: UserWalletId) {
|
||||
router.openNFTCollectionsScreen(userWalletId)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,6 +125,7 @@ internal object WalletScreenPreviewData {
|
|||
collectionsCount = 1,
|
||||
assetsCount = 3,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,4 +115,8 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
override fun openScanFailedDialog(onTryAgain: () -> Unit) {
|
||||
reduxStateHolder.dispatchDialogShow(StateDialog.ScanFailsDialog(StateDialog.ScanFailsSource.MAIN, onTryAgain))
|
||||
}
|
||||
|
||||
override fun openNFTCollectionsScreen(userWalletId: UserWalletId) {
|
||||
router.push(AppRoute.NFTCollections(userWalletId))
|
||||
}
|
||||
}
|
||||
|
|
@ -56,4 +56,7 @@ internal interface InnerWalletRouter {
|
|||
|
||||
/** Open scan failed dialog */
|
||||
fun openScanFailedDialog(onTryAgain: () -> Unit)
|
||||
|
||||
/** Open NFT collections screen */
|
||||
fun openNFTCollectionsScreen(userWalletId: UserWalletId)
|
||||
}
|
||||
|
|
@ -10,7 +10,9 @@ sealed class WalletNFTItemUM {
|
|||
|
||||
data object Loading : WalletNFTItemUM()
|
||||
|
||||
data object Empty : WalletNFTItemUM()
|
||||
data class Empty(
|
||||
val onItemClick: () -> Unit,
|
||||
) : WalletNFTItemUM()
|
||||
|
||||
data object Failed : WalletNFTItemUM()
|
||||
|
||||
|
|
@ -19,6 +21,7 @@ sealed class WalletNFTItemUM {
|
|||
val collectionsCount: Int,
|
||||
val assetsCount: Int,
|
||||
val isFlickering: Boolean,
|
||||
val onItemClick: () -> Unit,
|
||||
) : WalletNFTItemUM() {
|
||||
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.transformers
|
||||
|
||||
import com.tangem.domain.models.StatusSource
|
||||
import com.tangem.domain.nft.models.NFTCollections
|
||||
import com.tangem.domain.nft.models.*
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNFTItemUM
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
|
||||
|
|
@ -10,16 +10,21 @@ import kotlinx.collections.immutable.toPersistentList
|
|||
internal class SetNFTCollectionsTransformer(
|
||||
userWalletId: UserWalletId,
|
||||
private val nftCollections: List<NFTCollections>,
|
||||
private val onItemClick: () -> Unit,
|
||||
) : WalletStateTransformer(userWalletId) {
|
||||
|
||||
override fun transform(prevState: WalletState): WalletState = when (prevState) {
|
||||
is WalletState.MultiCurrency.Content -> prevState.copy(
|
||||
nftState = when {
|
||||
allCollectionsFailed() -> WalletNFTItemUM.Failed
|
||||
anyCollectionFailed() && allLoadedCollectionsEmpty() -> WalletNFTItemUM.Failed
|
||||
allCollectionsLoaded() && allCollectionsEmpty() -> WalletNFTItemUM.Empty
|
||||
!allCollectionsLoaded() && allCollectionsEmpty() -> WalletNFTItemUM.Loading
|
||||
else -> createContentNFTItemUM()
|
||||
nftCollections.allCollectionsFailed() ->
|
||||
WalletNFTItemUM.Failed
|
||||
nftCollections.anyCollectionFailed() && nftCollections.allLoadedCollectionsEmpty() ->
|
||||
WalletNFTItemUM.Failed
|
||||
nftCollections.allCollectionsLoaded() && nftCollections.allCollectionsEmpty() ->
|
||||
WalletNFTItemUM.Empty(onItemClick)
|
||||
!nftCollections.allCollectionsLoaded() && nftCollections.allCollectionsEmpty() ->
|
||||
WalletNFTItemUM.Loading
|
||||
else -> createContentNFTItemUM(onItemClick)
|
||||
},
|
||||
)
|
||||
is WalletState.SingleCurrency.Content,
|
||||
|
|
@ -31,7 +36,7 @@ internal class SetNFTCollectionsTransformer(
|
|||
-> prevState
|
||||
}
|
||||
|
||||
private fun createContentNFTItemUM(): WalletNFTItemUM.Content {
|
||||
private fun createContentNFTItemUM(onItemClick: () -> Unit): WalletNFTItemUM.Content {
|
||||
val collectionsContent = nftCollections
|
||||
.map { it.content }
|
||||
.filterIsInstance<NFTCollections.Content.Collections>()
|
||||
|
|
@ -61,34 +66,10 @@ internal class SetNFTCollectionsTransformer(
|
|||
assetsCount = collections
|
||||
.sumOf { it.count },
|
||||
isFlickering = isFlickering,
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
}
|
||||
|
||||
private fun allCollectionsFailed() = nftCollections.all {
|
||||
it.content is NFTCollections.Content.Error
|
||||
}
|
||||
|
||||
private fun anyCollectionFailed() = nftCollections.any {
|
||||
it.content is NFTCollections.Content.Error
|
||||
}
|
||||
|
||||
private fun allLoadedCollectionsEmpty() = nftCollections
|
||||
.map { it.content }
|
||||
.filterIsInstance<NFTCollections.Content.Collections>()
|
||||
.all { it.collections.isNullOrEmpty() }
|
||||
|
||||
private fun allCollectionsLoaded() = nftCollections.all {
|
||||
val content = it.content
|
||||
content is NFTCollections.Content.Collections &&
|
||||
content.source != StatusSource.CACHE
|
||||
}
|
||||
|
||||
private fun allCollectionsEmpty() = nftCollections.all {
|
||||
val content = it.content
|
||||
content is NFTCollections.Content.Collections &&
|
||||
content.collections.isNullOrEmpty()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NFT_COLLECTIONS_MAX_PREVIEWS_COUNT = 4
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,12 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class WalletNFTListSubscriber(
|
||||
private val userWallet: UserWallet,
|
||||
private val stateHolder: WalletStateController,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val getNFTCollectionsUseCase: GetNFTCollectionsUseCase,
|
||||
clickIntents: WalletClickIntents,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : WalletSubscriber() {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
|
@ -27,8 +26,7 @@ internal class WalletNFTListSubscriber(
|
|||
.flatMapLatest { nftEnabled ->
|
||||
// if NFT is enabled for this wallet, then start observing changes from store and apply transformer if need
|
||||
if (nftEnabled) {
|
||||
getNFTCollectionsUseCase
|
||||
.launch(userWallet.walletId)
|
||||
getNFTCollectionsUseCase(userWallet.walletId)
|
||||
.shareIn(
|
||||
scope = coroutineScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
|
|
@ -36,7 +34,11 @@ internal class WalletNFTListSubscriber(
|
|||
)
|
||||
.onEach {
|
||||
stateHolder.update(
|
||||
SetNFTCollectionsTransformer(userWallet.walletId, it),
|
||||
SetNFTCollectionsTransformer(
|
||||
userWalletId = userWallet.walletId,
|
||||
nftCollections = it,
|
||||
onItemClick = { clickIntents.onNFTClick(userWallet.walletId) },
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -713,7 +713,6 @@ internal fun LazyListScope.nftCollections(state: WalletState, itemModifier: Modi
|
|||
nftCollections(
|
||||
modifier = itemModifier,
|
||||
state = it.nftState,
|
||||
onClick = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,19 +34,19 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun WalletNFTItem(state: WalletNFTItemUM, modifier: Modifier = Modifier, onClick: () -> Unit = { }) {
|
||||
internal fun WalletNFTItem(state: WalletNFTItemUM, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is WalletNFTItemUM.Hidden -> Unit
|
||||
is WalletNFTItemUM.Empty -> WalletNFTItemEmpty(
|
||||
modifier = modifier,
|
||||
onClick = onClick,
|
||||
onClick = state.onItemClick,
|
||||
)
|
||||
is WalletNFTItemUM.Failed -> WalletNFTItemFailed(modifier = modifier)
|
||||
is WalletNFTItemUM.Loading -> WalletNFTItemLoading(modifier = modifier)
|
||||
|
||||
is WalletNFTItemUM.Content -> WalletNFTItemContent(
|
||||
state = state,
|
||||
onClick = onClick,
|
||||
onClick = state.onItemClick,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -396,16 +396,15 @@ private fun RowContentContainer(
|
|||
@Composable
|
||||
private fun Preview_WalletNFTItem(@PreviewParameter(WalletNFTItemProvider::class) state: WalletNFTItemUM) {
|
||||
TangemThemePreview {
|
||||
WalletNFTItem(
|
||||
state = state,
|
||||
onClick = {},
|
||||
)
|
||||
WalletNFTItem(state = state)
|
||||
}
|
||||
}
|
||||
|
||||
private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletNFTItemUM>(
|
||||
collection = listOf(
|
||||
WalletNFTItemUM.Empty,
|
||||
WalletNFTItemUM.Empty(
|
||||
onItemClick = { },
|
||||
),
|
||||
WalletNFTItemUM.Loading,
|
||||
WalletNFTItemUM.Failed,
|
||||
WalletNFTItemUM.Content(
|
||||
|
|
@ -415,6 +414,7 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
assetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = true,
|
||||
onItemClick = { },
|
||||
),
|
||||
WalletNFTItemUM.Content(
|
||||
previews = persistentListOf(
|
||||
|
|
@ -424,6 +424,7 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
assetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
WalletNFTItemUM.Content(
|
||||
previews = persistentListOf(
|
||||
|
|
@ -434,6 +435,7 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
assetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
WalletNFTItemUM.Content(
|
||||
previews = persistentListOf(
|
||||
|
|
@ -445,6 +447,7 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
assetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = false,
|
||||
onItemClick = { },
|
||||
),
|
||||
WalletNFTItemUM.Content(
|
||||
previews = persistentListOf(
|
||||
|
|
@ -456,6 +459,7 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider<WalletN
|
|||
assetsCount = 125,
|
||||
collectionsCount = 11,
|
||||
isFlickering = true,
|
||||
onItemClick = { },
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -7,12 +7,11 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletNFTItem
|
|||
|
||||
private const val NFT_COLLECTIONS_CONTENT_TYPE = "NFTCollections"
|
||||
|
||||
internal fun LazyListScope.nftCollections(state: WalletNFTItemUM, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
internal fun LazyListScope.nftCollections(state: WalletNFTItemUM, modifier: Modifier = Modifier) {
|
||||
item(key = NFT_COLLECTIONS_CONTENT_TYPE, contentType = NFT_COLLECTIONS_CONTENT_TYPE) {
|
||||
WalletNFTItem(
|
||||
modifier = modifier,
|
||||
state = state,
|
||||
onClick = onClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue