Updated on 2026-08-14
This commit is contained in:
parent
dc0b2a7e70
commit
1943ed248c
21 changed files with 573 additions and 418 deletions
|
|
@ -19,320 +19,357 @@ import kotlinx.collections.immutable.toPersistentList
|
|||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("LargeClass")
|
||||
internal object WalletPreviewData {
|
||||
|
||||
val walletTopBarConfig = WalletTopBarConfig(onScanCardClick = {}, onMoreClick = {})
|
||||
val walletTopBarConfig by lazy { WalletTopBarConfig(onScanCardClick = {}, onMoreClick = {}) }
|
||||
|
||||
val walletCardContentState = WalletCardState.Content(
|
||||
id = UserWalletId(UUID.randomUUID().toString()),
|
||||
title = "Wallet 1",
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
val walletCardContentState by lazy {
|
||||
WalletCardState.Content(
|
||||
id = UserWalletId("123"),
|
||||
title = "Wallet 1",
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
val walletCardLoadingState = WalletCardState.Loading(
|
||||
id = UserWalletId(UUID.randomUUID().toString()),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
val walletCardLoadingState by lazy {
|
||||
WalletCardState.Loading(
|
||||
id = UserWalletId("321"),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
val walletCardHiddenContentState = WalletCardState.HiddenContent(
|
||||
id = UserWalletId(UUID.randomUUID().toString()),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
val walletCardHiddenContentState by lazy {
|
||||
WalletCardState.HiddenContent(
|
||||
id = UserWalletId("42"),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
val walletCardErrorState = WalletCardState.Error(
|
||||
id = UserWalletId(UUID.randomUUID().toString()),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
val walletCardErrorState by lazy {
|
||||
WalletCardState.Error(
|
||||
id = UserWalletId("24"),
|
||||
title = "Wallet 1",
|
||||
additionalInfo = "3 cards • Seed enabled",
|
||||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onClick = null,
|
||||
)
|
||||
}
|
||||
|
||||
val wallets = mapOf(
|
||||
UserWalletId(stringValue = "123") to walletCardContentState,
|
||||
UserWalletId(stringValue = "321") to walletCardLoadingState,
|
||||
UserWalletId(stringValue = "42") to walletCardHiddenContentState,
|
||||
UserWalletId(stringValue = "24") to walletCardErrorState,
|
||||
)
|
||||
val wallets by lazy {
|
||||
mapOf(
|
||||
UserWalletId(stringValue = "123") to walletCardContentState,
|
||||
UserWalletId(stringValue = "321") to walletCardLoadingState,
|
||||
UserWalletId(stringValue = "42") to walletCardHiddenContentState,
|
||||
UserWalletId(stringValue = "24") to walletCardErrorState,
|
||||
)
|
||||
}
|
||||
|
||||
val walletListConfig = WalletsListConfig(
|
||||
selectedWalletIndex = 0,
|
||||
wallets = wallets.values.toPersistentList(),
|
||||
onWalletChange = {},
|
||||
)
|
||||
val walletListConfig by lazy {
|
||||
WalletsListConfig(
|
||||
selectedWalletIndex = 0,
|
||||
wallets = wallets.values.toPersistentList(),
|
||||
onWalletChange = {},
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemVisibleState = TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Visible(
|
||||
fiatAmount = "321 $",
|
||||
priceChange = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
val tokenItemVisibleState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Visible(
|
||||
fiatAmount = "321 $",
|
||||
priceChange = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemHiddenState = TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Hidden(
|
||||
priceChange = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
val tokenItemHiddenState by lazy {
|
||||
TokenItemState.Content(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Hidden(
|
||||
priceChange = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemDragState = TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
fiatAmount = "3 172,14 $",
|
||||
)
|
||||
val tokenItemDragState by lazy {
|
||||
TokenItemState.Draggable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
fiatAmount = "3 172,14 $",
|
||||
)
|
||||
}
|
||||
|
||||
val tokenItemUnreachableState = TokenItemState.Unreachable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
)
|
||||
val tokenItemUnreachableState by lazy {
|
||||
TokenItemState.Unreachable(
|
||||
id = UUID.randomUUID().toString(),
|
||||
tokenIconUrl = null,
|
||||
tokenIconResId = R.drawable.img_polygon_22,
|
||||
networkIconResId = R.drawable.img_polygon_22,
|
||||
name = "Polygon",
|
||||
)
|
||||
}
|
||||
|
||||
val loadingTokenItemState = TokenItemState.Loading
|
||||
val loadingTokenItemState by lazy { TokenItemState.Loading }
|
||||
|
||||
private const val networksSize = 10
|
||||
private const val tokensSize = 3
|
||||
val draggableItems = List(networksSize) { it }
|
||||
.flatMap { index ->
|
||||
val lastNetworkIndex = networksSize - 1
|
||||
val lastTokenIndex = tokensSize - 1
|
||||
val networkNumber = index + 1
|
||||
val draggableItems by lazy {
|
||||
List(networksSize) { it }
|
||||
.flatMap { index ->
|
||||
val lastNetworkIndex = networksSize - 1
|
||||
val lastTokenIndex = tokensSize - 1
|
||||
val networkNumber = index + 1
|
||||
|
||||
val group = DraggableItem.GroupHeader(
|
||||
id = "group_$networkNumber",
|
||||
networkName = "$networkNumber",
|
||||
roundingMode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
)
|
||||
|
||||
val tokens: MutableList<DraggableItem.Token> = mutableListOf()
|
||||
repeat(times = tokensSize) { i ->
|
||||
val tokenNumber = i + 1
|
||||
tokens.add(
|
||||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
name = "Token $tokenNumber from $networkNumber network",
|
||||
networkIconResId = R.drawable.img_eth_22.takeIf { i != 0 },
|
||||
),
|
||||
groupId = group.id,
|
||||
roundingMode = when {
|
||||
i == lastTokenIndex && index == lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
),
|
||||
val group = DraggableItem.GroupHeader(
|
||||
id = "group_$networkNumber",
|
||||
networkName = "$networkNumber",
|
||||
roundingMode = when (index) {
|
||||
0 -> DraggableItem.RoundingMode.Top()
|
||||
lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
val divider = DraggableItem.GroupPlaceholder(id = "divider_$networkNumber")
|
||||
val tokens: MutableList<DraggableItem.Token> = mutableListOf()
|
||||
repeat(times = tokensSize) { i ->
|
||||
val tokenNumber = i + 1
|
||||
tokens.add(
|
||||
DraggableItem.Token(
|
||||
tokenItemState = tokenItemDragState.copy(
|
||||
id = "${group.id}_token_$tokenNumber",
|
||||
name = "Token $tokenNumber from $networkNumber network",
|
||||
networkIconResId = R.drawable.img_eth_22.takeIf { i != 0 },
|
||||
),
|
||||
groupId = group.id,
|
||||
roundingMode = when {
|
||||
i == lastTokenIndex && index == lastNetworkIndex -> DraggableItem.RoundingMode.Bottom()
|
||||
else -> DraggableItem.RoundingMode.None
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(tokens)
|
||||
if (index != lastNetworkIndex) {
|
||||
add(divider)
|
||||
val divider = DraggableItem.GroupPlaceholder(id = "divider_$networkNumber")
|
||||
|
||||
buildList {
|
||||
add(group)
|
||||
addAll(tokens)
|
||||
if (index != lastNetworkIndex) {
|
||||
add(divider)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.toPersistentList()
|
||||
.toPersistentList()
|
||||
}
|
||||
|
||||
val draggableTokens = draggableItems
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.toMutableList()
|
||||
.also {
|
||||
it[0] = it[0].copy(roundingMode = DraggableItem.RoundingMode.Top())
|
||||
}
|
||||
.toPersistentList()
|
||||
val draggableTokens by lazy {
|
||||
draggableItems
|
||||
.filterIsInstance<DraggableItem.Token>()
|
||||
.toMutableList()
|
||||
.also {
|
||||
it[0] = it[0].copy(roundingMode = DraggableItem.RoundingMode.Top())
|
||||
}
|
||||
.toPersistentList()
|
||||
}
|
||||
|
||||
val groupedOrganizeTokensState = OrganizeTokensStateHolder(
|
||||
itemsState = OrganizeTokensListState.GroupedByNetwork(
|
||||
items = draggableItems,
|
||||
),
|
||||
header = OrganizeTokensStateHolder.HeaderConfig(
|
||||
onSortByBalanceClick = {},
|
||||
onGroupByNetworkClick = {},
|
||||
),
|
||||
dragConfig = OrganizeTokensStateHolder.DragConfig(
|
||||
onItemDragged = { _, _ -> },
|
||||
onDragStart = {},
|
||||
canDragItemOver = { _, _ -> false },
|
||||
onItemDragEnd = {},
|
||||
),
|
||||
actions = OrganizeTokensStateHolder.ActionsConfig(
|
||||
onApplyClick = {},
|
||||
onCancelClick = {},
|
||||
),
|
||||
)
|
||||
|
||||
val organizeTokensState = groupedOrganizeTokensState.copy(
|
||||
itemsState = OrganizeTokensListState.Ungrouped(
|
||||
items = draggableTokens,
|
||||
),
|
||||
)
|
||||
|
||||
val bottomSheet = WalletBottomSheetConfig(
|
||||
isShow = false,
|
||||
onDismissRequest = {},
|
||||
content = WalletBottomSheetConfig.BottomSheetContentConfig.UnlockWallets(
|
||||
onUnlockClick = {},
|
||||
onScanClick = {},
|
||||
),
|
||||
)
|
||||
|
||||
private val manageButtons = persistentListOf(
|
||||
WalletManageButton.Buy(onClick = {}),
|
||||
WalletManageButton.Send(onClick = {}),
|
||||
WalletManageButton.Receive(onClick = {}),
|
||||
WalletManageButton.Exchange(onClick = {}),
|
||||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
|
||||
val multicurrencyWalletScreenState = WalletStateHolder.MultiCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
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",
|
||||
),
|
||||
),
|
||||
val groupedOrganizeTokensState by lazy {
|
||||
OrganizeTokensStateHolder(
|
||||
itemsState = OrganizeTokensListState.GroupedByNetwork(
|
||||
items = draggableItems,
|
||||
),
|
||||
onOrganizeTokensClick = {},
|
||||
),
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
onRefresh = {},
|
||||
),
|
||||
notifications = persistentListOf(
|
||||
WalletNotification.UnreachableNetworks,
|
||||
WalletNotification.LikeTangemApp(onClick = {}),
|
||||
WalletNotification.BackupCard(onClick = {}),
|
||||
WalletNotification.ScanCard(onClick = {}),
|
||||
),
|
||||
bottomSheet = bottomSheet,
|
||||
)
|
||||
|
||||
val singleWalletScreenState = WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
onRefresh = {},
|
||||
),
|
||||
notifications = persistentListOf(WalletNotification.LikeTangemApp(onClick = {})),
|
||||
buttons = manageButtons.map(WalletManageButton::config).toPersistentList(),
|
||||
bottomSheet = bottomSheet,
|
||||
marketPriceBlockState = MarketPriceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "98900.12$",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "5.16%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
header = OrganizeTokensStateHolder.HeaderConfig(
|
||||
onSortByBalanceClick = {},
|
||||
onGroupByNetworkClick = {},
|
||||
),
|
||||
),
|
||||
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",
|
||||
),
|
||||
dragConfig = OrganizeTokensStateHolder.DragConfig(
|
||||
onItemDragged = { _, _ -> },
|
||||
onDragStart = {},
|
||||
canDragItemOver = { _, _ -> false },
|
||||
onItemDragEnd = {},
|
||||
),
|
||||
actions = OrganizeTokensStateHolder.ActionsConfig(
|
||||
onApplyClick = {},
|
||||
onCancelClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val organizeTokensState by lazy {
|
||||
groupedOrganizeTokensState.copy(
|
||||
itemsState = OrganizeTokensListState.Ungrouped(
|
||||
items = draggableTokens,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val bottomSheet by lazy {
|
||||
WalletBottomSheetConfig(
|
||||
isShow = false,
|
||||
onDismissRequest = {},
|
||||
content = WalletBottomSheetConfig.BottomSheetContentConfig.UnlockWallets(
|
||||
onUnlockClick = {},
|
||||
onScanClick = {},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private val manageButtons by lazy {
|
||||
persistentListOf(
|
||||
WalletManageButton.Buy(onClick = {}),
|
||||
WalletManageButton.Send(onClick = {}),
|
||||
WalletManageButton.Receive(onClick = {}),
|
||||
WalletManageButton.Exchange(onClick = {}),
|
||||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
}
|
||||
|
||||
val multicurrencyWalletScreenState by lazy {
|
||||
WalletStateHolder.MultiCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
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",
|
||||
),
|
||||
WalletTxHistoryState.TxHistoryItemState.GroupTitle("Yesterday"),
|
||||
WalletTxHistoryState.TxHistoryItemState.Transaction(
|
||||
TransactionState.Sending(
|
||||
address = "33BddS...ga2B",
|
||||
amount = "-0.500913 BTC",
|
||||
timestamp = "8:41",
|
||||
),
|
||||
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,
|
||||
onRefresh = {},
|
||||
),
|
||||
notifications = persistentListOf(
|
||||
WalletNotification.UnreachableNetworks,
|
||||
WalletNotification.LikeTangemApp(onClick = {}),
|
||||
WalletNotification.BackupCard(onClick = {}),
|
||||
WalletNotification.ScanCard(onClick = {}),
|
||||
),
|
||||
bottomSheetConfig = bottomSheet,
|
||||
)
|
||||
}
|
||||
|
||||
val singleWalletScreenState by lazy {
|
||||
WalletStateHolder.SingleCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
walletsListConfig = walletListConfig,
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(
|
||||
isRefreshing = false,
|
||||
onRefresh = {},
|
||||
),
|
||||
notifications = persistentListOf(WalletNotification.LikeTangemApp(onClick = {})),
|
||||
buttons = manageButtons.map(WalletManageButton::config).toPersistentList(),
|
||||
bottomSheetConfig = bottomSheet,
|
||||
marketPriceBlockState = MarketPriceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "98900.12$",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "5.16%",
|
||||
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",
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ internal sealed class WalletStateHolder(
|
|||
open val walletsListConfig: WalletsListConfig,
|
||||
open val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
open val notifications: ImmutableList<WalletNotification>,
|
||||
open val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
open val bottomSheetConfig: WalletBottomSheetConfig? = null,
|
||||
) {
|
||||
|
||||
fun copySealed(
|
||||
|
|
@ -35,7 +35,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig: WalletsListConfig = this.walletsListConfig,
|
||||
pullToRefreshConfig: WalletPullToRefreshConfig = this.pullToRefreshConfig,
|
||||
notifications: ImmutableList<WalletNotification> = this.notifications,
|
||||
bottomSheet: WalletBottomSheetConfig? = this.bottomSheet,
|
||||
bottomSheet: WalletBottomSheetConfig? = this.bottomSheetConfig,
|
||||
): WalletStateHolder {
|
||||
return when (this) {
|
||||
is MultiCurrencyContent -> this.copy(
|
||||
|
|
@ -44,7 +44,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheet,
|
||||
)
|
||||
is SingleCurrencyContent -> this.copy(
|
||||
onBackClick = onBackClick,
|
||||
|
|
@ -52,7 +52,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheet,
|
||||
)
|
||||
is UnlockWalletContent -> this.copy(
|
||||
onBackClick = onBackClick,
|
||||
|
|
@ -80,7 +80,7 @@ internal sealed class WalletStateHolder(
|
|||
override val walletsListConfig: WalletsListConfig,
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
override val notifications: ImmutableList<WalletNotification>,
|
||||
override val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
override val bottomSheetConfig: WalletBottomSheetConfig? = null,
|
||||
val tokensListState: WalletTokensListState,
|
||||
) : WalletStateHolder(
|
||||
onBackClick = onBackClick,
|
||||
|
|
@ -88,7 +88,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheetConfig,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -109,7 +109,7 @@ internal sealed class WalletStateHolder(
|
|||
override val walletsListConfig: WalletsListConfig,
|
||||
override val pullToRefreshConfig: WalletPullToRefreshConfig,
|
||||
override val notifications: ImmutableList<WalletNotification>,
|
||||
override val bottomSheet: WalletBottomSheetConfig? = null,
|
||||
override val bottomSheetConfig: WalletBottomSheetConfig? = null,
|
||||
val buttons: ImmutableList<ActionButtonConfig>,
|
||||
val marketPriceBlockState: MarketPriceBlockState,
|
||||
val txHistoryState: WalletTxHistoryState,
|
||||
|
|
@ -119,7 +119,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheetConfig,
|
||||
)
|
||||
|
||||
/**
|
||||
|
|
@ -151,7 +151,7 @@ internal sealed class WalletStateHolder(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = persistentListOf(WalletNotification.UnlockWallets(onUnlockWalletsNotificationClick)),
|
||||
bottomSheet = WalletBottomSheetConfig(
|
||||
bottomSheetConfig = WalletBottomSheetConfig(
|
||||
isShow = false,
|
||||
onDismissRequest = onBottomSheetDismissRequest,
|
||||
content = WalletBottomSheetConfig.BottomSheetContentConfig.UnlockWallets(
|
||||
|
|
@ -183,6 +183,6 @@ internal sealed class WalletStateHolder(
|
|||
),
|
||||
pullToRefreshConfig = WalletPullToRefreshConfig(isRefreshing = false, onRefresh = {}),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
bottomSheetConfig = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ internal class WalletSkeletonStateConverter(
|
|||
onOrganizeTokensClick = clickIntents::onOrganizeTokensClick,
|
||||
),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
bottomSheetConfig = null,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ internal class WalletSkeletonStateConverter(
|
|||
walletsListConfig = createWalletsListConfig(wallets),
|
||||
pullToRefreshConfig = createPullToRefreshConfig(),
|
||||
notifications = persistentListOf(),
|
||||
bottomSheet = null,
|
||||
bottomSheetConfig = null,
|
||||
buttons = WalletPreviewData.singleWalletScreenState.buttons, // TODO: create buttons
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(
|
||||
currencyName = cardTypeResolver.getBlockchain().currency,
|
||||
|
|
|
|||
|
|
@ -93,7 +93,9 @@ internal class WalletStateFactory(
|
|||
state.copySealed(
|
||||
bottomSheet = WalletBottomSheetConfig(
|
||||
isShow = true,
|
||||
onDismissRequest = { state.copySealed(bottomSheet = state.bottomSheet?.copy(isShow = false)) },
|
||||
onDismissRequest = {
|
||||
state.copySealed(bottomSheet = state.bottomSheetConfig?.copy(isShow = false))
|
||||
},
|
||||
content = content,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ internal class WalletLoadedTxHistoryConverter(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheetConfig,
|
||||
buttons = getButtons(),
|
||||
marketPriceBlockState = getLoadingMarketPriceBlockState(),
|
||||
txHistoryState = txHistoryState,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ internal class WalletLoadingTxHistoryConverter(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheetConfig,
|
||||
buttons = getButtons(),
|
||||
marketPriceBlockState = getLoadingMarketPriceBlockState(),
|
||||
txHistoryState = txHistoryState,
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import androidx.compose.foundation.*
|
|||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.*
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.PullRefreshState
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material3.*
|
||||
|
|
@ -17,22 +15,16 @@ import androidx.compose.ui.Modifier
|
|||
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 com.tangem.core.ui.components.buttons.HorizontalActionChips
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
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.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.multicurrency.OrganizeTokensButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.tokensListItems
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.txHistoryItems
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.ScrollOffsetCollector
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency.organizeButton
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.controlButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.marketPriceBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||
|
||||
/**
|
||||
|
|
@ -43,10 +35,10 @@ import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimat
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
internal fun WalletScreen(state: WalletStateHolder) {
|
||||
BackHandler(onBack = state.onBackClick)
|
||||
|
||||
val walletsListState = rememberLazyListState()
|
||||
|
||||
Scaffold(
|
||||
|
|
@ -54,7 +46,7 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
containerColor = TangemTheme.colors.background.secondary,
|
||||
) { scaffoldPaddings ->
|
||||
|
||||
val changeableItemModifier = Modifier.changeWalletAnimator(walletsListState)
|
||||
val movableItemModifier = Modifier.changeWalletAnimator(walletsListState)
|
||||
val pullRefreshState = rememberPullRefreshState(
|
||||
refreshing = state.pullToRefreshConfig.isRefreshing,
|
||||
onRefresh = state.pullToRefreshConfig.onRefresh,
|
||||
|
|
@ -65,76 +57,50 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
.padding(paddingValues = scaffoldPaddings)
|
||||
.pullRefresh(pullRefreshState),
|
||||
) {
|
||||
val txHistoryItems = if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
if (state.txHistoryState is WalletTxHistoryState.ContentState) {
|
||||
state.txHistoryState.items.collectAsLazyPagingItems()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val txHistoryItems = if (state is WalletStateHolder.SingleCurrencyContent &&
|
||||
state.txHistoryState is WalletTxHistoryState.ContentState
|
||||
) {
|
||||
(state.txHistoryState as? WalletTxHistoryState.ContentState)?.items?.collectAsLazyPagingItems()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val betweenItemsPadding = TangemTheme.dimens.spacing14
|
||||
val horizontalPadding = TangemTheme.dimens.spacing16
|
||||
val itemModifier = movableItemModifier
|
||||
.padding(top = betweenItemsPadding)
|
||||
.padding(horizontal = horizontalPadding)
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = PaddingValues(vertical = TangemTheme.dimens.spacing8),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
item {
|
||||
WalletsList(
|
||||
config = state.walletsListConfig,
|
||||
lazyListState = walletsListState,
|
||||
WalletsList(config = state.walletsListConfig, lazyListState = walletsListState)
|
||||
}
|
||||
|
||||
if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
controlButtons(
|
||||
configs = state.buttons,
|
||||
modifier = movableItemModifier.padding(top = betweenItemsPadding),
|
||||
)
|
||||
}
|
||||
|
||||
if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
item {
|
||||
HorizontalActionChips(
|
||||
buttons = state.buttons,
|
||||
modifier = changeableItemModifier.padding(top = TangemTheme.dimens.spacing14),
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
items(
|
||||
items = state.notifications,
|
||||
itemContent = { item ->
|
||||
Notification(
|
||||
state = item.state,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
},
|
||||
)
|
||||
notifications(configs = state.notifications, modifier = itemModifier)
|
||||
|
||||
if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
item {
|
||||
MarketPriceBlock(
|
||||
state = state.marketPriceBlockState,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
marketPriceBlock(state = state.marketPriceBlockState, modifier = itemModifier)
|
||||
}
|
||||
|
||||
contentItems(state = state, txHistoryItems = txHistoryItems, modifier = changeableItemModifier)
|
||||
contentItems(state = state, txHistoryItems = txHistoryItems, modifier = movableItemModifier)
|
||||
|
||||
if (state is WalletStateHolder.MultiCurrencyContent) {
|
||||
item {
|
||||
OrganizeTokensButton(
|
||||
onClick = state.tokensListState.onOrganizeTokensClick,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
organizeButton(onClick = state.tokensListState.onOrganizeTokensClick, modifier = itemModifier)
|
||||
}
|
||||
}
|
||||
|
||||
PullToRefreshIndicator(
|
||||
WalletPullToRefreshIndicator(
|
||||
isRefreshing = state.pullToRefreshConfig.isRefreshing,
|
||||
state = pullRefreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
|
|
@ -142,46 +108,12 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
}
|
||||
}
|
||||
|
||||
state.bottomSheet?.let { bottomSheetConfig ->
|
||||
if (bottomSheetConfig.isShow) WalletBottomSheet(config = bottomSheetConfig)
|
||||
val bottomSheetConfig = state.bottomSheetConfig
|
||||
if (bottomSheetConfig != null && bottomSheetConfig.isShow) {
|
||||
WalletBottomSheet(config = bottomSheetConfig)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = walletsListState, key2 = state.walletsListConfig.onWalletChange) {
|
||||
snapshotFlow { walletsListState.layoutInfo.visibleItemsInfo }
|
||||
.collect(collector = ScrollOffsetCollector(callback = state.walletsListConfig.onWalletChange))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun PullToRefreshIndicator(isRefreshing: Boolean, state: PullRefreshState, modifier: Modifier = Modifier) {
|
||||
PullRefreshIndicator(
|
||||
refreshing = isRefreshing,
|
||||
state = state,
|
||||
modifier = modifier,
|
||||
)
|
||||
WalletSideEffects(lazyListState = walletsListState, walletsListConfig = state.walletsListConfig)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import androidx.compose.foundation.lazy.LazyRow
|
|||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -18,23 +21,25 @@ import androidx.compose.ui.unit.dp
|
|||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletsListConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.WalletCard
|
||||
|
||||
/**
|
||||
* Wallets list component
|
||||
*
|
||||
* @param config config
|
||||
* @param modifier modifier
|
||||
* @param config config
|
||||
* @param lazyListState main content container list state
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState, modifier: Modifier = Modifier) {
|
||||
internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState) {
|
||||
val horizontalCardPadding = TangemTheme.dimens.spacing16
|
||||
val itemWidth = LocalConfiguration.current.screenWidthDp.dp - horizontalCardPadding * 2
|
||||
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
|
||||
val itemWidth by remember(screenWidth) { derivedStateOf { screenWidth - horizontalCardPadding * 2 } }
|
||||
|
||||
LazyRow(
|
||||
modifier = modifier.background(color = TangemTheme.colors.background.secondary),
|
||||
modifier = Modifier.background(color = TangemTheme.colors.background.secondary),
|
||||
state = lazyListState,
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing8),
|
||||
|
|
@ -48,22 +53,16 @@ internal fun WalletsList(config: WalletsListConfig, lazyListState: LazyListState
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletHeader_LightTheme() {
|
||||
private fun Preview_WalletsList_LightTheme() {
|
||||
TangemTheme(isDark = false) {
|
||||
WalletsList(
|
||||
config = WalletPreviewData.walletListConfig,
|
||||
lazyListState = rememberLazyListState(),
|
||||
)
|
||||
WalletsList(config = WalletPreviewData.walletListConfig, lazyListState = rememberLazyListState())
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_WalletHeader_DarkTheme() {
|
||||
private fun Preview_WalletsList_DarkTheme() {
|
||||
TangemTheme(isDark = true) {
|
||||
WalletsList(
|
||||
config = WalletPreviewData.walletListConfig,
|
||||
lazyListState = rememberLazyListState(),
|
||||
)
|
||||
WalletsList(config = WalletPreviewData.walletListConfig, lazyListState = rememberLazyListState())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components
|
||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components
|
||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
|
|
@ -31,6 +31,8 @@ private const val DOTS = "•••"
|
|||
*
|
||||
* @param state state
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletCard(state: WalletCardState, modifier: Modifier = Modifier) {
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
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.ui.components.multicurrency.tokensListItems
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.txHistoryItems
|
||||
|
||||
/**
|
||||
* Wallet content
|
||||
*
|
||||
* @param state wallet state
|
||||
* @param txHistoryItems transaction history items
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal fun LazyListScope.contentItems(
|
||||
state: WalletStateHolder,
|
||||
txHistoryItems: LazyPagingItems<WalletTxHistoryState.TxHistoryItemState>?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
when (state) {
|
||||
is WalletStateHolder.MultiCurrencyContent -> tokensListItems(state.tokensListState, modifier)
|
||||
is WalletStateHolder.SingleCurrencyContent -> txHistoryItems(state.txHistoryState, txHistoryItems, modifier)
|
||||
is WalletStateHolder.Loading,
|
||||
is WalletStateHolder.UnlockWalletContent,
|
||||
-> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletNotification
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
* Wallet notifications
|
||||
*
|
||||
* @param configs list of notifications
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal fun LazyListScope.notifications(configs: ImmutableList<WalletNotification>, modifier: Modifier = Modifier) {
|
||||
items(items = configs, itemContent = { Notification(state = it.state, modifier = modifier) })
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.PullRefreshState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
/**
|
||||
* "Pull to refresh" indicator
|
||||
*
|
||||
* @param isRefreshing indicator is currently refreshing or not
|
||||
* @param state indicator state
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
internal fun WalletPullToRefreshIndicator(
|
||||
isRefreshing: Boolean,
|
||||
state: PullRefreshState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
PullRefreshIndicator(refreshing = isRefreshing, state = state, modifier = modifier)
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletsListConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.ScrollOffsetCollector
|
||||
|
||||
/**
|
||||
* Wallet screen side effects
|
||||
*
|
||||
* @param lazyListState lazy list state
|
||||
* @param walletsListConfig wallets list config
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletSideEffects(lazyListState: LazyListState, walletsListConfig: WalletsListConfig) {
|
||||
LaunchedEffect(key1 = walletsListConfig.selectedWalletIndex) {
|
||||
lazyListState.scrollToItem(walletsListConfig.selectedWalletIndex)
|
||||
}
|
||||
|
||||
val dragInteraction = lazyListState.interactionSource.interactions.collectAsState(initial = null)
|
||||
LaunchedEffect(key1 = lazyListState, key2 = walletsListConfig.onWalletChange) {
|
||||
snapshotFlow { lazyListState.layoutInfo.visibleItemsInfo }
|
||||
.collect(
|
||||
collector = ScrollOffsetCollector(
|
||||
lazyListState = lazyListState,
|
||||
dragInteraction = dragInteraction,
|
||||
callback = walletsListConfig.onWalletChange,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components
|
||||
package com.tangem.feature.wallet.presentation.wallet.ui.components.common
|
||||
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.multicurrency
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
/**
|
||||
* Organize tokens button
|
||||
*
|
||||
* @param onClick callback is invoked when button is clicked
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal fun LazyListScope.organizeButton(onClick: (() -> Unit)?, modifier: Modifier = Modifier) {
|
||||
item { OrganizeTokensButton(onClick = onClick, modifier = modifier) }
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.buttons.HorizontalActionChips
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
* Single currency control buttons. Like, "Buy", "Sell", etc
|
||||
*
|
||||
* @param configs list of buttons
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal fun LazyListScope.controlButtons(configs: ImmutableList<ActionButtonConfig>, modifier: Modifier = Modifier) {
|
||||
item {
|
||||
HorizontalActionChips(
|
||||
buttons = configs,
|
||||
modifier = modifier,
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing16),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
|
||||
/**
|
||||
* Single currency market price block
|
||||
*
|
||||
* @param state component state
|
||||
* @param modifier modifier
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal fun LazyListScope.marketPriceBlock(state: MarketPriceBlockState, modifier: Modifier = Modifier) {
|
||||
item { MarketPriceBlock(state = state, modifier = modifier) }
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.utils
|
||||
|
||||
import androidx.compose.foundation.interaction.Interaction
|
||||
import androidx.compose.foundation.lazy.LazyListItemInfo
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.State
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlin.math.abs
|
||||
|
||||
|
|
@ -9,17 +12,22 @@ import kotlin.math.abs
|
|||
* If first visible item offset is greater than half item size, then [callback] be invoked.
|
||||
* If last visible item offset is greater than half item size, then [callback] be invoked.
|
||||
*
|
||||
* @property callback lambda be invoked when current scroll items is changed
|
||||
* @property lazyListState lazy list state
|
||||
* @property dragInteraction current drag interaction
|
||||
* @property callback lambda be invoked when current scroll items is changed
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal class ScrollOffsetCollector(
|
||||
private val lazyListState: LazyListState,
|
||||
private val dragInteraction: State<Interaction?>,
|
||||
private val callback: (Int) -> Unit,
|
||||
) : FlowCollector<List<LazyListItemInfo>> {
|
||||
|
||||
private val LazyListItemInfo.halfItemSize get() = size.div(other = 2)
|
||||
|
||||
override suspend fun emit(value: List<LazyListItemInfo>) {
|
||||
if (!lazyListState.isScrollInProgress || dragInteraction.value == null || value.size <= 1) return
|
||||
val firstItem = value.firstOrNull() ?: return
|
||||
val lastItem = value.lastOrNull() ?: return
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ internal class TokenListErrorToWalletStateConverter(
|
|||
walletsListConfig = state.walletsListConfig,
|
||||
pullToRefreshConfig = state.pullToRefreshConfig,
|
||||
notifications = state.notifications,
|
||||
bottomSheet = state.bottomSheet,
|
||||
bottomSheetConfig = state.bottomSheetConfig,
|
||||
tokensListState = WalletTokensListState.Content(items = persistentListOf(), onOrganizeTokensClick = null),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal class TokenListToWalletStateConverter(
|
|||
walletsListConfig = walletsListConfig,
|
||||
pullToRefreshConfig = pullToRefreshConfig,
|
||||
notifications = notifications,
|
||||
bottomSheet = bottomSheet,
|
||||
bottomSheetConfig = bottomSheetConfig,
|
||||
tokensListState = tokenListToContentConverter.convert(value = tokenList),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue