Updated on 2026-08-14
This commit is contained in:
parent
3ff771e48b
commit
160153bfa3
28 changed files with 913 additions and 368 deletions
|
|
@ -31,6 +31,7 @@ dependencies {
|
|||
implementation(project(":domain:wallets:models"))
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.txhistory)
|
||||
|
||||
implementation(project(":common"))
|
||||
implementation(project(":core:analytics"))
|
||||
|
|
@ -43,11 +44,13 @@ dependencies {
|
|||
implementation(project(":core:utils"))
|
||||
implementation(project(":libs:crypto"))
|
||||
implementation(project(":libs:auth"))
|
||||
|
||||
implementation(project(":data:source:preferences"))
|
||||
implementation(projects.data.card)
|
||||
implementation(projects.data.common)
|
||||
implementation(projects.data.settings)
|
||||
implementation(projects.data.tokens)
|
||||
implementation(projects.data.common)
|
||||
implementation(projects.data.txhistory)
|
||||
|
||||
/** Features */
|
||||
implementation(project(":features:onboarding"))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.txhistory.repository.TxHistoryRepository
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ViewModelComponent
|
||||
import dagger.hilt.android.scopes.ViewModelScoped
|
||||
|
||||
@Module
|
||||
@InstallIn(ViewModelComponent::class)
|
||||
internal object TxHistoryDomainModule {
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetTxHistoryItemsCountUseCase(txHistoryRepository: TxHistoryRepository): GetTxHistoryItemsCountUseCase {
|
||||
return GetTxHistoryItemsCountUseCase(repository = txHistoryRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetTxHistoryItemsUseCase(txHistoryRepository: TxHistoryRepository): GetTxHistoryItemsUseCase {
|
||||
return GetTxHistoryItemsUseCase(repository = txHistoryRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,12 +12,12 @@ class GetTxHistoryItemsCountUseCase(private val repository: TxHistoryRepository)
|
|||
return either {
|
||||
catch(
|
||||
block = { repository.getTxHistoryItemsCount(networkId, derivationPath) },
|
||||
catch = { e ->
|
||||
catch = { throwable ->
|
||||
raise(
|
||||
when (e) {
|
||||
is TxHistoryStateError.TxHistoryNotImplemented -> e
|
||||
is TxHistoryStateError.EmptyTxHistories -> e
|
||||
else -> TxHistoryStateError.DataError(e)
|
||||
when (throwable) {
|
||||
is TxHistoryStateError.TxHistoryNotImplemented -> throwable
|
||||
is TxHistoryStateError.EmptyTxHistories -> throwable
|
||||
else -> TxHistoryStateError.DataError(throwable)
|
||||
},
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,17 +2,12 @@ package com.tangem.domain.txhistory.usecase
|
|||
|
||||
import androidx.paging.PagingData
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.recover
|
||||
import arrow.core.right
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.txhistory.error.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.model.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.repository.TxHistoryRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
|
||||
private const val DEFAULT_PAGE_SIZE = 20
|
||||
|
||||
|
|
@ -21,29 +16,11 @@ class GetTxHistoryItemsUseCase(private val repository: TxHistoryRepository) {
|
|||
operator fun invoke(
|
||||
networkId: String,
|
||||
pageSize: Int = DEFAULT_PAGE_SIZE,
|
||||
): Flow<Either<TxHistoryListError,
|
||||
PagingData<TxHistoryItem>,>,> {
|
||||
return channelFlow {
|
||||
recover(
|
||||
block = {
|
||||
getTxHistoryItems(
|
||||
networkId = networkId,
|
||||
pageSize = pageSize,
|
||||
).collect { items ->
|
||||
send(items.right())
|
||||
}
|
||||
},
|
||||
recover = { error -> send(error.left()) },
|
||||
)
|
||||
): Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>> {
|
||||
return either {
|
||||
repository
|
||||
.getTxHistoryItems(networkId = networkId, pageSize = pageSize)
|
||||
.catch { raise(TxHistoryListError.DataError(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun Raise<TxHistoryListError>.getTxHistoryItems(
|
||||
networkId: String,
|
||||
pageSize: Int,
|
||||
): Flow<PagingData<TxHistoryItem>> {
|
||||
return repository
|
||||
.getTxHistoryItems(networkId = networkId, pageSize = pageSize)
|
||||
.catch { raise(TxHistoryListError.DataError(it)) }
|
||||
}
|
||||
}
|
||||
|
|
@ -12,18 +12,19 @@ dependencies {
|
|||
implementation(deps.material)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.compose.coil)
|
||||
implementation(deps.compose.constraintLayout)
|
||||
implementation(deps.compose.material)
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.material)
|
||||
implementation(deps.compose.material3)
|
||||
implementation(deps.compose.navigation)
|
||||
implementation(deps.compose.navigation.hilt)
|
||||
implementation(deps.compose.paging)
|
||||
implementation(deps.compose.reorderable)
|
||||
implementation(deps.compose.shimmer)
|
||||
implementation(deps.compose.ui)
|
||||
implementation(deps.compose.ui.tooling)
|
||||
implementation(deps.compose.shimmer)
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.compose.reorderable)
|
||||
|
||||
/** Other libraries */
|
||||
implementation(deps.arrow.core)
|
||||
|
|
@ -50,6 +51,7 @@ dependencies {
|
|||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.txhistory)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.common
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
|
|
@ -11,8 +12,11 @@ import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem
|
|||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensListState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.util.UUID
|
||||
|
||||
internal object WalletPreviewData {
|
||||
|
|
@ -221,54 +225,57 @@ internal object WalletPreviewData {
|
|||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
contentItems = persistentListOf(
|
||||
WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle("Bitcoin"),
|
||||
WalletContentItemState.MultiCurrencyItem.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_1",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletContentItemState.MultiCurrencyItem.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_2",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletContentItemState.MultiCurrencyItem.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_3",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletContentItemState.MultiCurrencyItem.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_4",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle("Ethereum"),
|
||||
WalletContentItemState.MultiCurrencyItem.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_5",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
tokensListState = WalletTokensListState.Content(
|
||||
persistentListOf(
|
||||
WalletTokensListState.TokensListItemState.NetworkGroupTitle("Bitcoin"),
|
||||
WalletTokensListState.TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_1",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletTokensListState.TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_2",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletTokensListState.TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_3",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletTokensListState.TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_4",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
WalletTokensListState.TokensListItemState.NetworkGroupTitle("Ethereum"),
|
||||
WalletTokensListState.TokensListItemState.Token(
|
||||
tokenItemVisibleState.copy(
|
||||
id = "token_5",
|
||||
name = "Ethereum",
|
||||
tokenIconResId = R.drawable.img_eth_22,
|
||||
networkIconResId = null,
|
||||
amount = "1,89340821 ETH",
|
||||
),
|
||||
),
|
||||
),
|
||||
onOrganizeTokensClick = {},
|
||||
),
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
|
|
@ -281,32 +288,12 @@ internal object WalletPreviewData {
|
|||
WalletNotification.ScanCard(onClick = {}),
|
||||
),
|
||||
bottomSheet = bottomSheet,
|
||||
onOrganizeTokensClick = {},
|
||||
)
|
||||
|
||||
val singleWalletScreenState = WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
contentItems = persistentListOf(
|
||||
WalletContentItemState.SingleCurrencyItem.Title(onExploreClick = {}),
|
||||
WalletContentItemState.SingleCurrencyItem.GroupTitle("Today"),
|
||||
WalletContentItemState.SingleCurrencyItem.Transaction(
|
||||
TransactionState.Sending(
|
||||
address = "33BddS...ga2B",
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
),
|
||||
),
|
||||
WalletContentItemState.SingleCurrencyItem.GroupTitle("Yesterday"),
|
||||
WalletContentItemState.SingleCurrencyItem.Transaction(
|
||||
TransactionState.Sending(
|
||||
address = "33BddS...ga2B",
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
),
|
||||
),
|
||||
),
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
onRefresh = {},
|
||||
|
|
@ -322,5 +309,30 @@ internal object WalletPreviewData {
|
|||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
txHistoryState = WalletTxHistoryState.Content(
|
||||
flowOf(
|
||||
PagingData.from(
|
||||
listOf(
|
||||
WalletTxHistoryState.TxHistoryItemState.Title(onExploreClick = {}),
|
||||
WalletTxHistoryState.TxHistoryItemState.GroupTitle("Today"),
|
||||
WalletTxHistoryState.TxHistoryItemState.Transaction(
|
||||
TransactionState.Sending(
|
||||
address = "33BddS...ga2B",
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
),
|
||||
),
|
||||
WalletTxHistoryState.TxHistoryItemState.GroupTitle("Yesterday"),
|
||||
WalletTxHistoryState.TxHistoryItemState.Transaction(
|
||||
TransactionState.Sending(
|
||||
address = "33BddS...ga2B",
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state
|
||||
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
|
||||
/**
|
||||
* Wallet screen content item state
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal sealed interface WalletContentItemState {
|
||||
|
||||
/** Multi currency wallet content state */
|
||||
sealed interface MultiCurrencyItem : WalletContentItemState {
|
||||
|
||||
/**
|
||||
* Network group title item
|
||||
*
|
||||
* @property networkName network name
|
||||
*/
|
||||
data class NetworkGroupTitle(val networkName: String) : MultiCurrencyItem
|
||||
|
||||
/**
|
||||
* Token item
|
||||
*
|
||||
* @property state token item state
|
||||
*/
|
||||
data class Token(val state: TokenItemState) : MultiCurrencyItem
|
||||
}
|
||||
|
||||
/** Single currency wallet content state */
|
||||
sealed interface SingleCurrencyItem : WalletContentItemState {
|
||||
|
||||
/**
|
||||
* Title item
|
||||
*
|
||||
* @property onExploreClick lambda be invoke when explore button was clicked
|
||||
*/
|
||||
data class Title(val onExploreClick: () -> Unit) : SingleCurrencyItem
|
||||
|
||||
/**
|
||||
* Group title item
|
||||
*
|
||||
* @property title title
|
||||
*/
|
||||
data class GroupTitle(val title: String) : SingleCurrencyItem
|
||||
|
||||
/**
|
||||
* Transaction item
|
||||
*
|
||||
* @property state transaction state
|
||||
*/
|
||||
data class Transaction(val state: TransactionState) : SingleCurrencyItem
|
||||
}
|
||||
|
||||
object Loading : WalletContentItemState
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@ package com.tangem.feature.wallet.presentation.wallet.state
|
|||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletLockedContentState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
|
|
@ -13,7 +16,6 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
* @property topBarConfig top bar config
|
||||
* @property walletsListConfig wallets list config
|
||||
* @property pullToRefreshConfig pull to refresh config
|
||||
* @property contentItems content items
|
||||
* @property notifications notifications
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
@ -23,7 +25,6 @@ internal sealed class WalletStateHolder(
|
|||
open val topBarConfig: WalletTopBarConfig,
|
||||
open val walletsListConfig: WalletsListConfig,
|
||||
open val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
open val contentItems: ImmutableList<WalletContentItemState>,
|
||||
open val notifications: ImmutableList<WalletNotification>,
|
||||
open val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
) {
|
||||
|
|
@ -33,7 +34,6 @@ internal sealed class WalletStateHolder(
|
|||
topBarConfig: WalletTopBarConfig = this.topBarConfig,
|
||||
walletsListConfig: WalletsListConfig = this.walletsListConfig,
|
||||
pullToRefreshConfig: WalletPullToRefreshConfig = this.pullToRefreshConfig,
|
||||
contentItems: ImmutableList<WalletContentItemState> = this.contentItems,
|
||||
notifications: ImmutableList<WalletNotification> = this.notifications,
|
||||
bottomSheet: WalletBottomSheetConfig? = this.bottomSheet,
|
||||
): WalletStateHolder {
|
||||
|
|
@ -43,7 +43,6 @@ internal sealed class WalletStateHolder(
|
|||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
contentItems = contentItems as ImmutableList<WalletContentItemState.MultiCurrencyItem>,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
)
|
||||
|
|
@ -52,7 +51,6 @@ internal sealed class WalletStateHolder(
|
|||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
contentItems = contentItems as ImmutableList<WalletContentItemState.SingleCurrencyItem>,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
)
|
||||
|
|
@ -73,27 +71,24 @@ internal sealed class WalletStateHolder(
|
|||
* @property topBarConfig top bar config
|
||||
* @property walletsListConfig wallets list config
|
||||
* @property pullToRefreshConfig pull to refresh config
|
||||
* @property contentItems content items
|
||||
* @property tokensListState token list state
|
||||
* @property notifications notifications
|
||||
* @property onOrganizeTokensClick lambda be invoked when organize tokens button is clicked
|
||||
*/
|
||||
data class MultiCurrencyContent(
|
||||
override val onBackClick: () -> Unit,
|
||||
override val topBarConfig: WalletTopBarConfig,
|
||||
override val walletsListConfig: WalletsListConfig,
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
override val contentItems: ImmutableList<WalletContentItemState.MultiCurrencyItem>,
|
||||
override val notifications: ImmutableList<WalletNotification>,
|
||||
override val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
val onOrganizeTokensClick: () -> Unit,
|
||||
val tokensListState: WalletTokensListState,
|
||||
) : WalletStateHolder(
|
||||
onBackClick = onBackClick,
|
||||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
contentItems = contentItems,
|
||||
bottomSheet = bottomSheet,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -103,27 +98,26 @@ internal sealed class WalletStateHolder(
|
|||
* @property topBarConfig top bar config
|
||||
* @property walletsListConfig wallets list config
|
||||
* @property pullToRefreshConfig pull to refresh config
|
||||
* @property contentItems content items
|
||||
* @property notifications notifications
|
||||
* @property buttons manage buttons
|
||||
* @property marketPriceBlockState market price block state
|
||||
* @property txHistoryState transactions history state
|
||||
*/
|
||||
data class SingleCurrencyContent(
|
||||
override val onBackClick: () -> Unit,
|
||||
override val topBarConfig: WalletTopBarConfig,
|
||||
override val walletsListConfig: WalletsListConfig,
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
override val contentItems: ImmutableList<WalletContentItemState.SingleCurrencyItem>,
|
||||
override val notifications: ImmutableList<WalletNotification>,
|
||||
override val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
val buttons: ImmutableList<ActionButtonConfig>,
|
||||
val marketPriceBlockState: MarketPriceBlockState,
|
||||
val txHistoryState: WalletTxHistoryState,
|
||||
) : WalletStateHolder(
|
||||
onBackClick = onBackClick,
|
||||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
contentItems = contentItems,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
)
|
||||
|
|
@ -134,6 +128,8 @@ internal sealed class WalletStateHolder(
|
|||
* @property onBackClick lambda be invoked when back button is clicked
|
||||
* @property topBarConfig top bar config
|
||||
* @property walletsListConfig wallets list config
|
||||
* @property pullToRefreshConfig pull to refresh config
|
||||
* @property lockedContentState locked content state
|
||||
* @property onUnlockWalletsNotificationClick lambda be invoked when unlock wallets notification is clicked
|
||||
* @property onBottomSheetDismissRequest lambda be invoked when bottom sheet is dismissed
|
||||
* @property onUnlockClick lambda be invoked when unlock button is clicked
|
||||
|
|
@ -144,6 +140,7 @@ internal sealed class WalletStateHolder(
|
|||
override val topBarConfig: WalletTopBarConfig,
|
||||
override val walletsListConfig: WalletsListConfig,
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
val lockedContentState: WalletLockedContentState,
|
||||
val onUnlockWalletsNotificationClick: () -> Unit,
|
||||
val onBottomSheetDismissRequest: () -> Unit,
|
||||
val onUnlockClick: () -> Unit,
|
||||
|
|
@ -153,7 +150,6 @@ internal sealed class WalletStateHolder(
|
|||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
contentItems = persistentListOf(WalletContentItemState.Loading),
|
||||
notifications = persistentListOf(WalletNotification.UnlockWallets(onUnlockWalletsNotificationClick)),
|
||||
bottomSheet = WalletBottomSheetConfig(
|
||||
isShow = false,
|
||||
|
|
@ -186,7 +182,6 @@ internal sealed class WalletStateHolder(
|
|||
onWalletChange = {},
|
||||
),
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(isRefreshing = false, onRefresh = {}),
|
||||
contentItems = persistentListOf(WalletContentItemState.Loading),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.content
|
||||
|
||||
/**
|
||||
* Wallet locked content state.
|
||||
* It allows to divide the locked content of multi-currency and single-currency wallets.
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal sealed interface WalletLockedContentState
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.content
|
||||
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
/**
|
||||
* Wallet tokens list state
|
||||
*
|
||||
* @property items content items
|
||||
* @property onOrganizeTokensClick lambda be invoked when organize tokens button is clicked
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
// TODO: Finalize strings [REDACTED_JIRA]
|
||||
internal sealed class WalletTokensListState(
|
||||
open val items: ImmutableList<TokensListItemState>,
|
||||
open val onOrganizeTokensClick: (() -> Unit)?,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Content state
|
||||
*
|
||||
* @property items content items
|
||||
* @property onOrganizeTokensClick lambda be invoked when organize tokens button is clicked
|
||||
*/
|
||||
data class Content(
|
||||
override val items: ImmutableList<TokensListItemState>,
|
||||
override val onOrganizeTokensClick: (() -> Unit)?,
|
||||
) : WalletTokensListState(items, onOrganizeTokensClick)
|
||||
|
||||
/** Locked content state */
|
||||
object Locked :
|
||||
WalletTokensListState(
|
||||
items = persistentListOf(
|
||||
TokensListItemState.NetworkGroupTitle(networkName = "Tokens"),
|
||||
TokensListItemState.Token(state = TokenItemState.Loading),
|
||||
),
|
||||
onOrganizeTokensClick = null,
|
||||
),
|
||||
WalletLockedContentState
|
||||
|
||||
/** Tokens list item state */
|
||||
sealed interface TokensListItemState {
|
||||
|
||||
/**
|
||||
* Network group title item
|
||||
*
|
||||
* @property networkName network name
|
||||
*/
|
||||
data class NetworkGroupTitle(val networkName: String) : TokensListItemState
|
||||
|
||||
/**
|
||||
* Token item
|
||||
*
|
||||
* @property state token item state
|
||||
*/
|
||||
data class Token(val state: TokenItemState) : TokensListItemState
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.content
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
/**
|
||||
* Wallet transaction history state
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal sealed interface WalletTxHistoryState {
|
||||
|
||||
/**
|
||||
* Wallet transaction history state with content
|
||||
*
|
||||
* @property items content items
|
||||
*/
|
||||
sealed class ContentItemsState(open val items: Flow<PagingData<TxHistoryItemState>>) : WalletTxHistoryState
|
||||
|
||||
/**
|
||||
* Content state
|
||||
*
|
||||
* @property items content items
|
||||
*/
|
||||
data class Content(override val items: Flow<PagingData<TxHistoryItemState>>) : ContentItemsState(items)
|
||||
|
||||
/**
|
||||
* Empty state
|
||||
*
|
||||
* @property onBuyClick lambda be invoke when buy button was clicked
|
||||
*/
|
||||
data class Empty(val onBuyClick: () -> Unit) : WalletTxHistoryState
|
||||
|
||||
/**
|
||||
* Not supported tx history state
|
||||
*
|
||||
* @property onExploreClick lambda be invoke when explore button was clicked
|
||||
*/
|
||||
data class NotSupported(val onExploreClick: () -> Unit) : WalletTxHistoryState
|
||||
|
||||
/**
|
||||
* Error state
|
||||
*
|
||||
* @property onReloadClick lambda be invoke when reload button was clicked
|
||||
*/
|
||||
data class Error(val onReloadClick: () -> Unit) : WalletTxHistoryState
|
||||
|
||||
/**
|
||||
* Locked state
|
||||
*
|
||||
* @property onExploreClick lambda be invoke when explore button was clicked
|
||||
*/
|
||||
data class Locked(val onExploreClick: () -> Unit) :
|
||||
ContentItemsState(
|
||||
items = flowOf(
|
||||
PagingData.from(
|
||||
listOf(
|
||||
TxHistoryItemState.Title(onExploreClick = onExploreClick),
|
||||
TxHistoryItemState.Transaction(state = TransactionState.Loading),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
WalletLockedContentState
|
||||
|
||||
/** Transactions history item state */
|
||||
sealed interface TxHistoryItemState {
|
||||
|
||||
/**
|
||||
* Title item
|
||||
*
|
||||
* @property onExploreClick lambda be invoke when explore button was clicked
|
||||
*/
|
||||
data class Title(val onExploreClick: () -> Unit) : TxHistoryItemState
|
||||
|
||||
/**
|
||||
* Group title item
|
||||
*
|
||||
* @property title title
|
||||
*/
|
||||
data class GroupTitle(val title: String) : TxHistoryItemState
|
||||
|
||||
/**
|
||||
* Transaction item
|
||||
*
|
||||
* @property state transaction state
|
||||
*/
|
||||
data class Transaction(val state: TransactionState) : TxHistoryItemState
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.factory.WalletLoadedTokensListConverter.LoadedTokensListModel
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.TokenListErrorToWalletStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.TokenListToWalletStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickCallbacks
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
/**
|
||||
|
|
@ -19,17 +20,19 @@ import com.tangem.utils.converter.Converter
|
|||
*/
|
||||
internal class WalletLoadedTokensListConverter(
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
clickCallbacks: WalletClickCallbacks,
|
||||
) : Converter<LoadedTokensListModel, WalletStateHolder> {
|
||||
|
||||
private val tokenListStateConverter = TokenListToWalletStateConverter(
|
||||
currentState = currentStateProvider(),
|
||||
currentStateProvider = currentStateProvider,
|
||||
isWalletContentHidden = false, // TODO: [REDACTED_JIRA]
|
||||
fiatCurrencyCode = "USD", // TODO: [REDACTED_JIRA]
|
||||
fiatCurrencySymbol = "$", // TODO: [REDACTED_JIRA]
|
||||
clickCallbacks = clickCallbacks,
|
||||
)
|
||||
|
||||
private val tokenListErrorStateConverter = TokenListErrorToWalletStateConverter(
|
||||
currentState = currentStateProvider(),
|
||||
currentStateProvider = currentStateProvider,
|
||||
)
|
||||
|
||||
override fun convert(value: LoadedTokensListModel): WalletStateHolder {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.map
|
||||
import arrow.core.Either
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.txhistory.error.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.model.TxHistoryItem
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletManageButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState.TxHistoryItemState
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
/**
|
||||
* Converter from loaded tx history to [WalletTxHistoryState]
|
||||
*
|
||||
* @property currentStateProvider current state provider
|
||||
* @property currentCardTypeResolverProvider current card type resolver provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class WalletLoadedTxHistoryConverter(
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
private val currentCardTypeResolverProvider: Provider<CardTypesResolver>,
|
||||
) : Converter<Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>>, WalletStateHolder> {
|
||||
|
||||
override fun convert(value: Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>>): WalletStateHolder {
|
||||
return value.fold(ifLeft = { convertError() }, ifRight = ::convert)
|
||||
}
|
||||
|
||||
private fun convertError(): WalletStateHolder {
|
||||
val state = currentStateProvider()
|
||||
return WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = state.onBackClick,
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
buttons = persistentListOf(
|
||||
WalletManageButton.Buy(onClick = {}),
|
||||
WalletManageButton.Send(onClick = {}),
|
||||
WalletManageButton.Receive(onClick = {}),
|
||||
WalletManageButton.Exchange(onClick = {}),
|
||||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
.map(WalletManageButton::config)
|
||||
.toImmutableList(),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = currentCardTypeResolverProvider().getBlockchain().currency,
|
||||
),
|
||||
// TODO: [REDACTED_JIRA]
|
||||
txHistoryState = WalletTxHistoryState.Error(onReloadClick = {}),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convert(items: Flow<PagingData<TxHistoryItem>>): WalletStateHolder {
|
||||
val state = currentStateProvider()
|
||||
return WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = state.onBackClick,
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
buttons = persistentListOf(
|
||||
WalletManageButton.Buy(onClick = {}),
|
||||
WalletManageButton.Send(onClick = {}),
|
||||
WalletManageButton.Receive(onClick = {}),
|
||||
WalletManageButton.Exchange(onClick = {}),
|
||||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
.map(WalletManageButton::config)
|
||||
.toImmutableList(),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = currentCardTypeResolverProvider().getBlockchain().currency,
|
||||
),
|
||||
txHistoryState = createContentTxHistory(items),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createContentTxHistory(items: Flow<PagingData<TxHistoryItem>>): WalletTxHistoryState {
|
||||
return WalletTxHistoryState.Content(
|
||||
items = items.map { pagingData ->
|
||||
pagingData.map { item ->
|
||||
TxHistoryItemState.Transaction(
|
||||
state = when (val direction = item.direction) {
|
||||
is TxHistoryItem.TransactionDirection.Incoming -> {
|
||||
when (item.status) {
|
||||
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Receive(
|
||||
address = direction.from,
|
||||
amount = item.amount.toPlainString(),
|
||||
timestamp = item.timestamp.toString(),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Receiving(
|
||||
address = direction.from,
|
||||
amount = item.amount.toPlainString(),
|
||||
timestamp = item.timestamp.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
is TxHistoryItem.TransactionDirection.Outgoing -> {
|
||||
when (item.status) {
|
||||
TxHistoryItem.TxStatus.Confirmed -> TransactionState.Send(
|
||||
address = direction.to,
|
||||
amount = item.amount.toPlainString(),
|
||||
timestamp = item.timestamp.toString(),
|
||||
)
|
||||
TxHistoryItem.TxStatus.Unconfirmed -> TransactionState.Sending(
|
||||
address = direction.to,
|
||||
amount = item.amount.toPlainString(),
|
||||
timestamp = item.timestamp.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import arrow.core.Either
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.txhistory.error.TxHistoryStateError
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletManageButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
/**
|
||||
* Converter from loading tx history to [WalletTxHistoryState]
|
||||
*
|
||||
* @property currentStateProvider current state provider
|
||||
* @property currentCardTypeResolverProvider current card type resolver provider
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class WalletLoadingTxHistoryConverter(
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
private val currentCardTypeResolverProvider: Provider<CardTypesResolver>,
|
||||
) : Converter<Either<TxHistoryStateError, Int>, WalletStateHolder> {
|
||||
|
||||
override fun convert(value: Either<TxHistoryStateError, Int>): WalletStateHolder {
|
||||
return value.fold(ifLeft = ::convertError, ifRight = ::convert)
|
||||
}
|
||||
|
||||
private fun convert(value: Int): WalletStateHolder {
|
||||
val state = currentStateProvider()
|
||||
|
||||
return WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = state.onBackClick,
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
buttons = persistentListOf(
|
||||
WalletManageButton.Buy(onClick = {}),
|
||||
WalletManageButton.Send(onClick = {}),
|
||||
WalletManageButton.Receive(onClick = {}),
|
||||
WalletManageButton.Exchange(onClick = {}),
|
||||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
.map(WalletManageButton::config)
|
||||
.toImmutableList(),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = currentCardTypeResolverProvider().getBlockchain().currency,
|
||||
),
|
||||
txHistoryState = createLoadingTxHistory(itemCount = value),
|
||||
)
|
||||
}
|
||||
|
||||
private fun createLoadingTxHistory(itemCount: Int): WalletTxHistoryState {
|
||||
return WalletTxHistoryState.Content(
|
||||
items = flowOf(
|
||||
value = PagingData.from(
|
||||
data = buildList(
|
||||
capacity = itemCount,
|
||||
builderAction = {
|
||||
add(
|
||||
element = WalletTxHistoryState.TxHistoryItemState.Transaction(
|
||||
state = TransactionState.Loading,
|
||||
),
|
||||
)
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertError(error: TxHistoryStateError): WalletStateHolder {
|
||||
val state = currentStateProvider()
|
||||
|
||||
return WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = state.onBackClick,
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
buttons = WalletPreviewData.singleWalletScreenState.buttons,
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = currentCardTypeResolverProvider().getBlockchain().currency,
|
||||
),
|
||||
// TODO: [REDACTED_JIRA]
|
||||
txHistoryState = when (error) {
|
||||
is TxHistoryStateError.EmptyTxHistories -> WalletTxHistoryState.Empty(onBuyClick = {})
|
||||
is TxHistoryStateError.DataError -> WalletTxHistoryState.Error(onReloadClick = {})
|
||||
is TxHistoryStateError.TxHistoryNotImplemented -> WalletTxHistoryState.NotSupported(onExploreClick = {})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,20 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickCallbacks
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
/**
|
||||
* Converter from loaded list of [UserWallet] to skeleton state of screen [WalletStateHolder]
|
||||
|
|
@ -40,10 +43,12 @@ internal class WalletSkeletonStateConverter(
|
|||
topBarConfig = createTopBarConfig(),
|
||||
walletsListConfig = createWalletsListConfig(wallets),
|
||||
pullToRefreshConfig = createPullToRefreshConfig(),
|
||||
contentItems = persistentListOf(),
|
||||
tokensListState = WalletTokensListState.Content(
|
||||
items = persistentListOf(),
|
||||
onOrganizeTokensClick = clickCallbacks::onOrganizeTokensClick,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
onOrganizeTokensClick = clickCallbacks::onOrganizeTokensClick,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -56,13 +61,15 @@ internal class WalletSkeletonStateConverter(
|
|||
topBarConfig = createTopBarConfig(),
|
||||
walletsListConfig = createWalletsListConfig(wallets),
|
||||
pullToRefreshConfig = createPullToRefreshConfig(),
|
||||
contentItems = persistentListOf(),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
buttons = WalletPreviewData.singleWalletScreenState.buttons, // TODO: create buttons
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = cardTypeResolver.getBlockchain().currency,
|
||||
),
|
||||
txHistoryState = WalletTxHistoryState.Content(
|
||||
items = flow { PagingData.empty<WalletTxHistoryState.TxHistoryItemState>() },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -78,12 +85,7 @@ internal class WalletSkeletonStateConverter(
|
|||
selectedWalletIndex = 0,
|
||||
wallets = wallets.map { wallet ->
|
||||
WalletCardState.Loading(
|
||||
// TODO remove after adding release logic for GetTokenListUseCase
|
||||
id = if (wallet.scanResponse.cardTypesResolver.isMultiwalletAllowed()) {
|
||||
UserWalletId("123")
|
||||
} else {
|
||||
UserWalletId("321")
|
||||
},
|
||||
id = wallet.walletId,
|
||||
title = wallet.name,
|
||||
additionalInfo = "", // TODO add additional info resolver
|
||||
imageResId = WalletImageResolver.resolve(cardTypesResolver = wallet.scanResponse.cardTypesResolver),
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import arrow.core.Either
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.txhistory.error.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.error.TxHistoryStateError
|
||||
import com.tangem.domain.txhistory.model.TxHistoryItem
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletNotification
|
||||
|
|
@ -11,6 +16,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.factory.WalletLoadedTokensListConverter.LoadedTokensListModel
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickCallbacks
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Main factory for creating [WalletStateHolder]
|
||||
|
|
@ -20,11 +26,32 @@ import kotlinx.collections.immutable.ImmutableList
|
|||
*/
|
||||
internal class WalletStateFactory(
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
currentCardTypeResolverProvider: Provider<CardTypesResolver>,
|
||||
private val clickCallbacks: WalletClickCallbacks,
|
||||
) {
|
||||
|
||||
private val skeletonConverter = WalletSkeletonStateConverter(clickCallbacks = clickCallbacks)
|
||||
private val loadedTokensListConverter = WalletLoadedTokensListConverter(currentStateProvider = currentStateProvider)
|
||||
private val skeletonConverter by lazy { WalletSkeletonStateConverter(clickCallbacks = clickCallbacks) }
|
||||
|
||||
private val loadedTokensListConverter by lazy {
|
||||
WalletLoadedTokensListConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
clickCallbacks = clickCallbacks,
|
||||
)
|
||||
}
|
||||
|
||||
private val loadingTransactionsStateConverter by lazy {
|
||||
WalletLoadingTxHistoryConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
currentCardTypeResolverProvider = currentCardTypeResolverProvider,
|
||||
)
|
||||
}
|
||||
|
||||
private val loadedTxHistoryConverter by lazy {
|
||||
WalletLoadedTxHistoryConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
currentCardTypeResolverProvider = currentCardTypeResolverProvider,
|
||||
)
|
||||
}
|
||||
|
||||
fun getInitialState(): WalletStateHolder = WalletStateHolder.Loading(onBackClick = clickCallbacks::onBackClick)
|
||||
|
||||
|
|
@ -66,4 +93,14 @@ internal class WalletStateFactory(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getLoadingTxHistoryState(itemsCountEither: Either<TxHistoryStateError, Int>): WalletStateHolder {
|
||||
return loadingTransactionsStateConverter.convert(value = itemsCountEither)
|
||||
}
|
||||
|
||||
fun getLoadedTxHistoryState(
|
||||
txHistoryEither: Either<TxHistoryListError, Flow<PagingData<TxHistoryItem>>>,
|
||||
): WalletStateHolder {
|
||||
return loadedTxHistoryConverter.convert(txHistoryEither)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,7 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.PullRefreshState
|
||||
|
|
@ -17,29 +14,26 @@ import androidx.compose.material3.*
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemsIndexed
|
||||
import com.tangem.core.ui.components.buttons.HorizontalActionChips
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.RoundedActionButton
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.transactions.Transaction
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.component.NetworkGroupItem
|
||||
import com.tangem.feature.wallet.presentation.common.component.TokenItem
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletBottomSheet
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletTopBar
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TransactionsBlockGroupTitle
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TransactionsBlockTitle
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.MultiCurrencyContentItem
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.OrganizeTokensButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.SingleCurrencyContentItem
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.decorations.walletContentItemDecoration
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.ScrollOffsetCollector
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||
|
|
@ -74,6 +68,16 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
.padding(paddingValues = scaffoldPaddings)
|
||||
.pullRefresh(pullRefreshState),
|
||||
) {
|
||||
val txHistoryItems = if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
if (state.txHistoryState is WalletTxHistoryState.ContentItemsState) {
|
||||
state.txHistoryState.items.collectAsLazyPagingItems()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(vertical = TangemTheme.dimens.spacing8),
|
||||
|
|
@ -90,8 +94,7 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
item {
|
||||
HorizontalActionChips(
|
||||
buttons = state.buttons,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14),
|
||||
modifier = changeableItemModifier.padding(top = TangemTheme.dimens.spacing14),
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
|
|
@ -120,33 +123,12 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
}
|
||||
}
|
||||
|
||||
itemsIndexed(
|
||||
items = state.contentItems,
|
||||
key = { index, item ->
|
||||
when (item) {
|
||||
is WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle -> item.networkName
|
||||
is WalletContentItemState.MultiCurrencyItem.Token -> index
|
||||
is WalletContentItemState.SingleCurrencyItem.Title -> index
|
||||
is WalletContentItemState.SingleCurrencyItem.GroupTitle -> item.title
|
||||
is WalletContentItemState.SingleCurrencyItem.Transaction -> index
|
||||
is WalletContentItemState.Loading -> index
|
||||
}
|
||||
},
|
||||
itemContent = { index, item ->
|
||||
ContentItem(
|
||||
item = item,
|
||||
modifier = changeableItemModifier.walletContentItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = state.contentItems.lastIndex,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
contentItems(state = state, txHistoryItems = txHistoryItems, modifier = changeableItemModifier)
|
||||
|
||||
if (state is WalletStateHolder.MultiCurrencyContent) {
|
||||
item {
|
||||
OrganizeTokensButton(
|
||||
onClick = state.onOrganizeTokensClick,
|
||||
onClick = state.tokensListState.onOrganizeTokensClick,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
|
|
@ -173,6 +155,74 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.contentItems(
|
||||
state: WalletStateHolder,
|
||||
txHistoryItems: LazyPagingItems<WalletTxHistoryState.TxHistoryItemState>?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (state) {
|
||||
is WalletStateHolder.MultiCurrencyContent -> {
|
||||
tokensListItems(state = state.tokensListState, modifier = modifier)
|
||||
}
|
||||
is WalletStateHolder.SingleCurrencyContent -> {
|
||||
txHistoryItems(
|
||||
state = state.txHistoryState,
|
||||
txHistoryItems = txHistoryItems,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
is WalletStateHolder.Loading,
|
||||
is WalletStateHolder.UnlockWalletContent,
|
||||
-> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.tokensListItems(state: WalletTokensListState, modifier: Modifier = Modifier) {
|
||||
itemsIndexed(
|
||||
items = state.items,
|
||||
key = { index, _ -> index },
|
||||
itemContent = { index, item ->
|
||||
MultiCurrencyContentItem(
|
||||
state = item,
|
||||
modifier = modifier.walletContentItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = state.items.lastIndex,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun LazyListScope.txHistoryItems(
|
||||
state: WalletTxHistoryState,
|
||||
txHistoryItems: LazyPagingItems<WalletTxHistoryState.TxHistoryItemState>?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (state) {
|
||||
is WalletTxHistoryState.ContentItemsState -> {
|
||||
checkNotNull(txHistoryItems)
|
||||
itemsIndexed(
|
||||
items = txHistoryItems,
|
||||
key = { index, _ -> index },
|
||||
itemContent = { index, item ->
|
||||
if (item == null) return@itemsIndexed
|
||||
|
||||
SingleCurrencyContentItem(
|
||||
state = item,
|
||||
modifier = modifier.walletContentItemDecoration(
|
||||
currentIndex = index,
|
||||
lastIndex = txHistoryItems.itemCount,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
is WalletTxHistoryState.Empty -> TODO("[REDACTED_JIRA]")
|
||||
is WalletTxHistoryState.Error -> TODO("[REDACTED_JIRA]")
|
||||
is WalletTxHistoryState.NotSupported -> TODO("[REDACTED_JIRA]")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun PullToRefreshIndicator(isRefreshing: Boolean, state: PullRefreshState, modifier: Modifier = Modifier) {
|
||||
|
|
@ -183,42 +233,6 @@ private fun PullToRefreshIndicator(isRefreshing: Boolean, state: PullRefreshStat
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentItem(item: WalletContentItemState, modifier: Modifier = Modifier) {
|
||||
when (item) {
|
||||
is WalletContentItemState.MultiCurrencyItem.NetworkGroupTitle -> {
|
||||
NetworkGroupItem(networkName = item.networkName, modifier = modifier)
|
||||
}
|
||||
is WalletContentItemState.MultiCurrencyItem.Token -> {
|
||||
TokenItem(state = item.state, modifier = modifier)
|
||||
}
|
||||
is WalletContentItemState.SingleCurrencyItem.Title -> {
|
||||
TransactionsBlockTitle(config = item, modifier = modifier)
|
||||
}
|
||||
is WalletContentItemState.SingleCurrencyItem.GroupTitle -> {
|
||||
TransactionsBlockGroupTitle(config = item, modifier = modifier)
|
||||
}
|
||||
is WalletContentItemState.SingleCurrencyItem.Transaction -> {
|
||||
Transaction(state = item.state, modifier = modifier)
|
||||
}
|
||||
WalletContentItemState.Loading -> {
|
||||
TokenItem(state = TokenItemState.Loading, modifier = modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun OrganizeTokensButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
RoundedActionButton(
|
||||
config = ActionButtonConfig(
|
||||
text = stringResource(id = R.string.organize_tokens_title),
|
||||
iconResId = R.drawable.ic_filter_24,
|
||||
onClick = onClick,
|
||||
),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.feature.wallet.presentation.common.component.NetworkGroupItem
|
||||
import com.tangem.feature.wallet.presentation.common.component.TokenItem
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
|
||||
/**
|
||||
* Multi-currency content item
|
||||
*
|
||||
* @param state item state
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun MultiCurrencyContentItem(state: WalletTokensListState.TokensListItemState, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is WalletTokensListState.TokensListItemState.NetworkGroupTitle -> {
|
||||
NetworkGroupItem(networkName = state.networkName, modifier = modifier)
|
||||
}
|
||||
is WalletTokensListState.TokensListItemState.Token -> {
|
||||
TokenItem(state = state.state, modifier = modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.RoundedActionButton
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
|
||||
/**
|
||||
* Organize tokens button
|
||||
*
|
||||
* @param onClick callback, if null button is disabled
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun OrganizeTokensButton(onClick: (() -> Unit)?, modifier: Modifier = Modifier) {
|
||||
RoundedActionButton(
|
||||
config = ActionButtonConfig(
|
||||
text = stringResource(id = R.string.organize_tokens_title),
|
||||
iconResId = R.drawable.ic_filter_24,
|
||||
onClick = onClick ?: {},
|
||||
enabled = onClick != null,
|
||||
),
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.transactions.Transaction
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState
|
||||
|
||||
/**
|
||||
* Single currency content item
|
||||
*
|
||||
* @param state state
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun SingleCurrencyContentItem(state: WalletTxHistoryState.TxHistoryItemState, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
is WalletTxHistoryState.TxHistoryItemState.GroupTitle -> {
|
||||
TxHistoryGroupTitle(config = state, modifier = modifier)
|
||||
}
|
||||
is WalletTxHistoryState.TxHistoryItemState.Title -> {
|
||||
TxHistoryTitle(config = state, modifier = modifier)
|
||||
}
|
||||
is WalletTxHistoryState.TxHistoryItemState.Transaction -> {
|
||||
Transaction(state = state.state, modifier = modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState.TxHistoryItemState
|
||||
|
||||
/**
|
||||
* Transactions block group title
|
||||
|
|
@ -18,10 +18,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemStat
|
|||
* @param modifier modifier
|
||||
*/
|
||||
@Composable
|
||||
internal fun TransactionsBlockGroupTitle(
|
||||
config: WalletContentItemState.SingleCurrencyItem.GroupTitle,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
internal fun TxHistoryGroupTitle(config: TxHistoryItemState.GroupTitle, modifier: Modifier = Modifier) {
|
||||
Text(
|
||||
text = config.title,
|
||||
modifier = modifier
|
||||
|
|
@ -41,7 +38,7 @@ internal fun TransactionsBlockGroupTitle(
|
|||
@Composable
|
||||
private fun Preview_TransactionsBlockGroupTitle_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
TransactionsBlockGroupTitle(config = WalletContentItemState.SingleCurrencyItem.GroupTitle(title = "Today"))
|
||||
TxHistoryGroupTitle(config = TxHistoryItemState.GroupTitle(title = "Today"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +46,6 @@ private fun Preview_TransactionsBlockGroupTitle_Light() {
|
|||
@Composable
|
||||
private fun Preview_TransactionsBlockGroupTitle_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
TransactionsBlockGroupTitle(config = WalletContentItemState.SingleCurrencyItem.GroupTitle(title = "Today"))
|
||||
TxHistoryGroupTitle(config = TxHistoryItemState.GroupTitle(title = "Today"))
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTxHistoryState.TxHistoryItemState
|
||||
|
||||
/**
|
||||
* Transactions block title
|
||||
|
|
@ -21,10 +21,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemStat
|
|||
* @param modifier modifier
|
||||
*/
|
||||
@Composable
|
||||
internal fun TransactionsBlockTitle(
|
||||
config: WalletContentItemState.SingleCurrencyItem.Title,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
internal fun TxHistoryTitle(config: TxHistoryItemState.Title, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.background(TangemTheme.colors.background.primary)
|
||||
|
|
@ -62,9 +59,7 @@ internal fun TransactionsBlockTitle(
|
|||
@Composable
|
||||
private fun Preview_TransactionsBlockTitle_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
TransactionsBlockTitle(
|
||||
config = WalletContentItemState.SingleCurrencyItem.Title(onExploreClick = {}),
|
||||
)
|
||||
TxHistoryTitle(config = TxHistoryItemState.Title(onExploreClick = {}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,8 +67,6 @@ private fun Preview_TransactionsBlockTitle_Light() {
|
|||
@Composable
|
||||
private fun Preview_TransactionsBlockTitle_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
TransactionsBlockTitle(
|
||||
config = WalletContentItemState.SingleCurrencyItem.Title(onExploreClick = {}),
|
||||
)
|
||||
TxHistoryTitle(config = TxHistoryItemState.Title(onExploreClick = {}))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState.MultiCurrencyItem
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal object LoadingItemsProvider {
|
||||
|
||||
fun getLoadingMultiCurrencyTokens(): PersistentList<MultiCurrencyItem> {
|
||||
return List(size = 5) { TokenItemState.Loading }
|
||||
.map { MultiCurrencyItem.Token(it) }
|
||||
.toPersistentList()
|
||||
fun getLoadingMultiCurrencyTokens(): ImmutableList<WalletTokensListState.TokensListItemState.Token> {
|
||||
return buildList(capacity = 5) {
|
||||
add(WalletTokensListState.TokensListItemState.Token(state = TokenItemState.Loading))
|
||||
}.toImmutableList()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,27 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.tokens.error.TokenListError
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal class TokenListErrorToWalletStateConverter(
|
||||
private val currentState: WalletStateHolder,
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
) : Converter<TokenListError, WalletStateHolder> {
|
||||
|
||||
// TODO: [REDACTED_JIRA]
|
||||
override fun convert(value: TokenListError): WalletStateHolder {
|
||||
return currentState
|
||||
val state = currentStateProvider()
|
||||
return WalletStateHolder.MultiCurrencyContent(
|
||||
onBackClick = state.onBackClick,
|
||||
topBarConfig = state.topBarConfig,
|
||||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
tokensListState = WalletTokensListState.Content(items = persistentListOf(), onOrganizeTokensClick = null),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@ package com.tangem.feature.wallet.presentation.wallet.utils
|
|||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.model.TokenStatus
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState.MultiCurrencyItem
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState.TokensListItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.LoadingItemsProvider.getLoadingMultiCurrencyTokens
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickCallbacks
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.mutate
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -15,36 +16,44 @@ internal class TokenListToContentItemsConverter(
|
|||
isWalletContentHidden: Boolean,
|
||||
fiatCurrencyCode: String,
|
||||
fiatCurrencySymbol: String,
|
||||
) : Converter<TokenList, ImmutableList<MultiCurrencyItem>> {
|
||||
private val clickCallbacks: WalletClickCallbacks,
|
||||
) : Converter<TokenList, WalletTokensListState> {
|
||||
|
||||
private val tokenStatusConverter = TokenStatusToTokenItemConverter(
|
||||
isWalletContentHidden,
|
||||
fiatCurrencyCode,
|
||||
fiatCurrencySymbol,
|
||||
isWalletContentHidden = isWalletContentHidden,
|
||||
fiatCurrencyCode = fiatCurrencyCode,
|
||||
fiatCurrencySymbol = fiatCurrencySymbol,
|
||||
)
|
||||
|
||||
override fun convert(value: TokenList): ImmutableList<MultiCurrencyItem> {
|
||||
return when (value) {
|
||||
is TokenList.GroupedByNetwork -> value.mapToMultiCurrencyItems()
|
||||
is TokenList.Ungrouped -> value.mapToMultiCurrencyItems()
|
||||
is TokenList.NotInitialized -> getLoadingMultiCurrencyTokens()
|
||||
}
|
||||
override fun convert(value: TokenList): WalletTokensListState {
|
||||
return WalletTokensListState.Content(
|
||||
items = when (value) {
|
||||
is TokenList.GroupedByNetwork -> value.mapToMultiCurrencyItems()
|
||||
is TokenList.Ungrouped -> value.mapToMultiCurrencyItems()
|
||||
is TokenList.NotInitialized -> getLoadingMultiCurrencyTokens()
|
||||
},
|
||||
onOrganizeTokensClick = if (value.totalFiatBalance is TokenList.FiatBalance.Loaded) {
|
||||
clickCallbacks::onOrganizeTokensClick
|
||||
} else {
|
||||
null
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun TokenList.GroupedByNetwork.mapToMultiCurrencyItems(): PersistentList<MultiCurrencyItem> {
|
||||
private fun TokenList.GroupedByNetwork.mapToMultiCurrencyItems(): PersistentList<TokensListItemState> {
|
||||
return groups.fold(initial = persistentListOf()) { acc, group ->
|
||||
acc.mutate { it.addGroup(group) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun TokenList.Ungrouped.mapToMultiCurrencyItems(): PersistentList<MultiCurrencyItem> {
|
||||
private fun TokenList.Ungrouped.mapToMultiCurrencyItems(): PersistentList<TokensListItemState> {
|
||||
return tokens.fold(initial = persistentListOf()) { acc, token ->
|
||||
acc.mutate { it.addToken(token) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<MultiCurrencyItem>.addGroup(group: NetworkGroup): List<MultiCurrencyItem> {
|
||||
this.add(MultiCurrencyItem.NetworkGroupTitle(group.network.name))
|
||||
private fun MutableList<TokensListItemState>.addGroup(group: NetworkGroup): List<TokensListItemState> {
|
||||
this.add(TokensListItemState.NetworkGroupTitle(group.network.name))
|
||||
|
||||
group.tokens.forEach { token ->
|
||||
this.addToken(token)
|
||||
|
|
@ -53,10 +62,10 @@ internal class TokenListToContentItemsConverter(
|
|||
return this
|
||||
}
|
||||
|
||||
private fun MutableList<MultiCurrencyItem>.addToken(token: TokenStatus): List<MultiCurrencyItem> {
|
||||
private fun MutableList<TokensListItemState>.addToken(token: TokenStatus): List<TokensListItemState> {
|
||||
val tokenItemState = tokenStatusConverter.convert(token)
|
||||
|
||||
this.add(MultiCurrencyItem.Token(tokenItemState))
|
||||
this.add(TokensListItemState.Token(tokenItemState))
|
||||
|
||||
return this
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +1,56 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder.MultiCurrencyContent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletsListConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.TokenListToWalletStateConverter.TokensListModel
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickCallbacks
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
internal class TokenListToWalletStateConverter(
|
||||
private val currentState: WalletStateHolder,
|
||||
private val currentStateProvider: Provider<WalletStateHolder>,
|
||||
private val isWalletContentHidden: Boolean,
|
||||
private val fiatCurrencyCode: String,
|
||||
private val fiatCurrencySymbol: String,
|
||||
clickCallbacks: WalletClickCallbacks,
|
||||
) : Converter<TokensListModel, WalletStateHolder> {
|
||||
|
||||
private val tokenListToContentConverter = TokenListToContentItemsConverter(
|
||||
isWalletContentHidden = isWalletContentHidden,
|
||||
fiatCurrencyCode = fiatCurrencyCode,
|
||||
fiatCurrencySymbol = fiatCurrencySymbol,
|
||||
clickCallbacks = clickCallbacks,
|
||||
)
|
||||
|
||||
override fun convert(value: TokensListModel): WalletStateHolder {
|
||||
val state = if (currentState is MultiCurrencyContent) {
|
||||
currentState.updateWithTokenList(tokenList = value.tokenList)
|
||||
} else {
|
||||
currentState
|
||||
}
|
||||
|
||||
return state.copySealed(
|
||||
walletsListConfig = state.updateSelectedWallet(value.tokenList.totalFiatBalance),
|
||||
pullToRefreshConfig = if (value.isRefreshing) {
|
||||
state.pullToRefreshConfig.copy(isRefreshing = state.getRefreshingStatus())
|
||||
} else {
|
||||
state.pullToRefreshConfig
|
||||
},
|
||||
)
|
||||
val state = currentStateProvider()
|
||||
return state
|
||||
.updateWithTokenList(tokenList = value.tokenList)
|
||||
.copySealed(
|
||||
walletsListConfig = state.updateSelectedWallet(value.tokenList.totalFiatBalance),
|
||||
pullToRefreshConfig = if (value.isRefreshing) {
|
||||
state.pullToRefreshConfig.copy(isRefreshing = state.getRefreshingStatus())
|
||||
} else {
|
||||
state.pullToRefreshConfig
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun MultiCurrencyContent.updateWithTokenList(tokenList: TokenList): MultiCurrencyContent {
|
||||
return this.copy(contentItems = tokenListToContentConverter.convert(value = tokenList))
|
||||
private fun WalletStateHolder.updateWithTokenList(tokenList: TokenList): MultiCurrencyContent {
|
||||
return MultiCurrencyContent(
|
||||
onBackClick = onBackClick,
|
||||
topBarConfig = topBarConfig,
|
||||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
tokensListState = tokenListToContentConverter.convert(value = tokenList),
|
||||
)
|
||||
}
|
||||
|
||||
private fun WalletStateHolder.updateSelectedWallet(fiatBalance: TokenList.FiatBalance): WalletsListConfig {
|
||||
|
|
@ -63,13 +71,13 @@ internal class TokenListToWalletStateConverter(
|
|||
}
|
||||
|
||||
private fun WalletStateHolder.getRefreshingStatus(): Boolean {
|
||||
return contentItems.any { state ->
|
||||
val isMultiCurrencyItem = state as? WalletContentItemState.MultiCurrencyItem.Token
|
||||
val isSingleCurrencyItem = state as? WalletContentItemState.SingleCurrencyItem.Transaction
|
||||
|
||||
isMultiCurrencyItem?.state is TokenItemState.Loading ||
|
||||
isSingleCurrencyItem?.state is TransactionState.Loading ||
|
||||
state is WalletContentItemState.Loading
|
||||
return if (this is MultiCurrencyContent) {
|
||||
tokensListState.items.any { tokensListItemState ->
|
||||
tokensListItemState is WalletTokensListState.TokensListItemState.Token &&
|
||||
tokensListItemState.state is TokenItemState.Loading
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@ import com.tangem.domain.tokens.model.NetworkGroup
|
|||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.model.TokenStatus
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletContentItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.content.WalletTokensListState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -32,7 +32,7 @@ internal class WalletNotificationsListFactory(
|
|||
private val clickCallbacks: WalletClickCallbacks,
|
||||
) {
|
||||
|
||||
fun create(cardTypesResolver: CardTypesResolver, tokenList: TokenList): Flow<ImmutableList<WalletNotification>> {
|
||||
fun create(cardTypesResolver: CardTypesResolver, tokenList: TokenList?): Flow<ImmutableList<WalletNotification>> {
|
||||
// TODO: [REDACTED_JIRA] order
|
||||
return flow {
|
||||
emit(
|
||||
|
|
@ -63,7 +63,7 @@ internal class WalletNotificationsListFactory(
|
|||
add(element = WalletNotification.BackupCard(onClick = clickCallbacks::onBackupCardClick))
|
||||
}
|
||||
|
||||
if (tokenList.hasMissedDerivations()) {
|
||||
if (tokenList != null && tokenList.hasMissedDerivations()) {
|
||||
add(element = WalletNotification.ScanCard(onClick = clickCallbacks::onScanCardClick))
|
||||
}
|
||||
|
||||
|
|
@ -112,12 +112,12 @@ internal class WalletNotificationsListFactory(
|
|||
}
|
||||
|
||||
private fun hasUnreachableNetworks(): Boolean {
|
||||
val isUnreachableState = { item: WalletContentItemState.MultiCurrencyItem ->
|
||||
(item as? WalletContentItemState.MultiCurrencyItem.Token)?.state is TokenItemState.Unreachable
|
||||
val isUnreachableState = { item: WalletTokensListState.TokensListItemState ->
|
||||
(item as? WalletTokensListState.TokensListItemState.Token)?.state is TokenItemState.Unreachable
|
||||
}
|
||||
|
||||
return currentStateProvider().let { state ->
|
||||
state is WalletStateHolder.MultiCurrencyContent && state.contentItems.any(isUnreachableState)
|
||||
state is WalletStateHolder.MultiCurrencyContent && state.tokensListState.items.any(isUnreachableState)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.*
|
||||
import com.tangem.blockchain.common.DerivationStyle
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
|
|
@ -14,8 +15,10 @@ import com.tangem.domain.demo.IsDemoCardUseCase
|
|||
import com.tangem.domain.settings.IsUserAlreadyRateAppUseCase
|
||||
import com.tangem.domain.tokens.GetTokenListUseCase
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
|
||||
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
|
||||
import com.tangem.domain.userwallets.UserWalletBuilder
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
|
|
@ -46,6 +49,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val isUserAlreadyRateAppUseCase: IsUserAlreadyRateAppUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
private val scanCardProcessor: ScanCardProcessor,
|
||||
private val txHistoryItemsCountUseCase: GetTxHistoryItemsCountUseCase,
|
||||
private val txHistoryItemsUseCase: GetTxHistoryItemsUseCase,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) : ViewModel(), DefaultLifecycleObserver, WalletClickCallbacks {
|
||||
|
||||
|
|
@ -62,6 +67,9 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
private val stateFactory = WalletStateFactory(
|
||||
currentStateProvider = Provider { uiState },
|
||||
currentCardTypeResolverProvider = Provider {
|
||||
getCardTypeResolver(index = uiState.walletsListConfig.selectedWalletIndex)
|
||||
},
|
||||
clickCallbacks = this,
|
||||
)
|
||||
|
||||
|
|
@ -69,10 +77,10 @@ internal class WalletViewModel @Inject constructor(
|
|||
var uiState: WalletStateHolder by mutableStateOf(stateFactory.getInitialState())
|
||||
private set
|
||||
|
||||
private var cardTypeResolverMap: Map<UserWalletId, CardTypesResolver> by Delegates.notNull()
|
||||
private var wallets: List<UserWallet> by Delegates.notNull()
|
||||
|
||||
private val getTokensJobHolder = JobHolder()
|
||||
private val getNotificationJobHolder = JobHolder()
|
||||
private val tokensJobHolder = JobHolder()
|
||||
private val notificationsJobHolder = JobHolder()
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
getWalletsUseCase()
|
||||
|
|
@ -80,15 +88,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
.distinctUntilChanged()
|
||||
.onEach { wallets ->
|
||||
if (wallets.isEmpty()) return@onEach
|
||||
|
||||
cardTypeResolverMap = wallets.associate { wallet ->
|
||||
// TODO remove after adding release logic for GetTokenListUseCase
|
||||
if (wallet.scanResponse.cardTypesResolver.isMultiwalletAllowed()) {
|
||||
UserWalletId("123")
|
||||
} else {
|
||||
UserWalletId("321")
|
||||
} to wallet.scanResponse.cardTypesResolver
|
||||
}
|
||||
this.wallets = wallets
|
||||
|
||||
uiState = stateFactory.getSkeletonState(wallets = wallets)
|
||||
|
||||
|
|
@ -99,8 +99,15 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateContentItems(index: Int, isRefreshing: Boolean = false) {
|
||||
// TODO: use GetTransactionsUseCase
|
||||
val cardTypeResolver = getCardTypeResolver(index)
|
||||
if (cardTypeResolver.isMultiwalletAllowed()) {
|
||||
updateByTokensList(index, isRefreshing)
|
||||
} else {
|
||||
updateByTxHistory(index)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateByTokensList(index: Int, isRefreshing: Boolean) {
|
||||
getTokenListUseCase(userWalletId = uiState.walletsListConfig.wallets[index].id)
|
||||
.distinctUntilChanged()
|
||||
.onEach { tokenListEither ->
|
||||
|
|
@ -113,26 +120,50 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
.saveIn(jobHolder = getTokensJobHolder)
|
||||
.saveIn(tokensJobHolder)
|
||||
}
|
||||
|
||||
private fun updateNotifications(index: Int, tokenList: TokenList) {
|
||||
private fun updateByTxHistory(index: Int) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val wallet = getWallet(index)
|
||||
val blockchain = wallet.scanResponse.cardTypesResolver.getBlockchain()
|
||||
uiState = stateFactory.getLoadingTxHistoryState(
|
||||
itemsCountEither = txHistoryItemsCountUseCase(
|
||||
networkId = blockchain.id,
|
||||
derivationPath = requireNotNull(blockchain.derivationPath(style = DerivationStyle.LEGACY)).rawPath,
|
||||
),
|
||||
)
|
||||
|
||||
updateTxHistory(networkId = blockchain.id)
|
||||
updateNotifications(index)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTxHistory(networkId: String) {
|
||||
uiState = stateFactory.getLoadedTxHistoryState(txHistoryEither = txHistoryItemsUseCase(networkId))
|
||||
}
|
||||
|
||||
private fun updateNotifications(index: Int, tokenList: TokenList? = null) {
|
||||
notificationsListFactory.create(
|
||||
cardTypesResolver = requireNotNull(
|
||||
value = cardTypeResolverMap[uiState.walletsListConfig.wallets[index].id],
|
||||
lazyMessage = {
|
||||
"CardTypeResolverMap doesn't contain this id = ${uiState.walletsListConfig.wallets[index].id}"
|
||||
},
|
||||
),
|
||||
cardTypesResolver = getCardTypeResolver(index = index),
|
||||
tokenList = tokenList,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.onEach { uiState = stateFactory.getStateByNotifications(notifications = it) }
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
.saveIn(jobHolder = getNotificationJobHolder)
|
||||
.saveIn(jobHolder = notificationsJobHolder)
|
||||
}
|
||||
|
||||
private fun getWallet(index: Int): UserWallet {
|
||||
return requireNotNull(
|
||||
value = wallets.getOrNull(index),
|
||||
lazyMessage = { "WalletsList doesn't contain element with index = $index" },
|
||||
)
|
||||
}
|
||||
|
||||
private fun getCardTypeResolver(index: Int): CardTypesResolver = getWallet(index).scanResponse.cardTypesResolver
|
||||
|
||||
override fun onBackClick() = router.popBackStack()
|
||||
|
||||
override fun onScanCardClick() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue