Updated on 2026-08-14

This commit is contained in:
Tangem 2022-12-01 14:54:01 +03:00
parent 41dea25009
commit 4b08a5f605
7 changed files with 148 additions and 162 deletions

View file

@ -5,15 +5,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
import androidx.fragment.app.viewModels
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
import com.tangem.core.ui.res.TangemTheme
@ -29,6 +26,7 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
return viewModel.state.collectAsState()
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
override fun ScreenContent(
modifier: Modifier,
@ -38,7 +36,10 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
val errorMessage by rememberUpdatedState(newValue = state.error?.customMessage)
val renameWalletDialog by rememberUpdatedState(newValue = state.renameWalletDialog)
Box(modifier = modifier) {
Box(
modifier = modifier
.nestedScroll(connection = rememberNestedScrollInteropConnection()),
) {
WalletSelectorScreenContent(
state = state,
onWalletClick = viewModel::walletClicked,

View file

@ -2,16 +2,16 @@ package com.tangem.tap.features.walletSelector.ui
import androidx.compose.runtime.Immutable
import com.tangem.common.core.TangemError
import com.tangem.tap.common.entities.FiatCurrency
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
import com.tangem.tap.features.walletSelector.ui.model.RenameWalletDialog
import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
@Immutable
internal data class WalletSelectorScreenState(
val wallets: List<UserWalletItem> = listOf(),
val multiCurrencyWallets: List<MultiCurrencyUserWalletItem> = emptyList(),
val singleCurrencyWallets: List<SingleCurrencyUserWalletItem> = emptyList(),
val selectedWalletId: String? = null,
val fiatCurrency: FiatCurrency = FiatCurrency.Default,
val isLocked: Boolean = true,
val isLocked: Boolean = false,
val editingWalletsIds: List<String> = listOf(),
val renameWalletDialog: RenameWalletDialog? = null,
val showAddCardProgress: Boolean = false,

View file

@ -60,7 +60,8 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber<WalletSele
fun renameWallet() = with(state.value) {
if (editingWalletsIds.isNotEmpty() && renameWalletDialog == null) {
val editedWalletId = editingWalletsIds.first()
val editedWallet = wallets.find { it.id == editedWalletId }
val editedWallet = (multiCurrencyWallets + singleCurrencyWallets)
.find { it.id == editedWalletId }
if (editedWallet != null) {
val dialog = RenameWalletDialog(

View file

@ -1,10 +1,12 @@
package com.tangem.tap.features.walletSelector.ui.components
import com.tangem.tap.features.walletSelector.ui.WalletSelectorScreenState
import com.tangem.tap.features.walletSelector.ui.model.MultiCurrencyUserWalletItem
import com.tangem.tap.features.walletSelector.ui.model.SingleCurrencyUserWalletItem
import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem
internal object MockData {
private val userWallet = UserWalletItem(
private val multiCurrencyUserWallet = MultiCurrencyUserWalletItem(
id = "wallet_1",
balance = UserWalletItem.Balance(
amount = "6781.05 $",
@ -12,19 +14,29 @@ internal object MockData {
),
name = "Wallet",
imageUrl = "https://app.tangem.com/cards/card_default.png",
type = UserWalletItem.Type.MultiCurrency(tokensCount = 12, cardsInWallet = 3),
tokensCount = 12,
cardsInWallet = 3,
)
val userWalletList = listOf(
userWallet,
userWallet.copy(id = "wallet_2"),
userWallet.copy(id = "wallet_3", type = UserWalletItem.Type.MultiCurrency(tokensCount = 2, cardsInWallet = 1)),
userWallet.copy(id = "wallet_4", type = UserWalletItem.Type.SingleCurrency(tokenName = "Ethereum")),
private val singleCurrencyUserWallet = SingleCurrencyUserWalletItem(
id = "wallet_4",
balance = UserWalletItem.Balance(
amount = "6781.05 $",
isLoading = false,
),
name = "Wallet",
imageUrl = "https://app.tangem.com/cards/card_default.png",
tokenName = "Ethereum",
)
val state = WalletSelectorScreenState(
wallets = userWalletList,
selectedWalletId = userWalletList[0].id,
multiCurrencyWallets = listOf(
multiCurrencyUserWallet,
multiCurrencyUserWallet.copy(id = "wallet_2"),
multiCurrencyUserWallet.copy(id = "wallet_3", tokensCount = 2, cardsInWallet = 1),
),
singleCurrencyWallets = listOf(singleCurrencyUserWallet),
selectedWalletId = multiCurrencyUserWallet.id,
isLocked = false,
)
}

View file

@ -1,11 +1,7 @@
package com.tangem.tap.features.walletSelector.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
@ -19,17 +15,12 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.SecondaryButtonIconRight
import com.tangem.core.ui.components.SpacerH12
import com.tangem.core.ui.components.SpacerH16
import com.tangem.core.ui.components.SpacerH24
import com.tangem.core.ui.components.SpacerW16
import com.tangem.core.ui.components.SpacerW8
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.*
import com.tangem.core.ui.components.atoms.Hand
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
import com.tangem.tap.features.walletSelector.ui.WalletSelectorScreenState
import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem
import com.tangem.wallet.R
@Composable
@ -69,36 +60,44 @@ internal fun WalletSelectorScreenContent(
)
}
SpacerH12()
WalletList(
wallets = state.wallets,
selectedWalletId = state.selectedWalletId,
checkedWalletIds = state.editingWalletsIds,
isLocked = state.isLocked,
onWalletClick = onWalletClick,
onWalletLongClick = onWalletLongClick,
)
SpacerH24()
if (state.isLocked) {
PrimaryButton(
Column(
modifier = Modifier
.verticalScroll(
state = rememberScrollState(),
),
) {
WalletsList(
multiCurrencyWallets = state.multiCurrencyWallets,
singleCurrencyWallets = state.singleCurrencyWallets,
selectedWalletId = state.selectedWalletId,
checkedWalletIds = state.editingWalletsIds,
isLocked = state.isLocked,
onWalletClick = onWalletClick,
onWalletLongClick = onWalletLongClick,
)
SpacerH24()
if (state.isLocked) {
PrimaryButton(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth(),
text = stringResource(R.string.user_wallet_list_unlock_all_face_id),
showProgress = state.showUnlockProgress,
onClick = onUnlockClick,
)
SpacerH12()
}
SecondaryButtonIconRight(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth(),
text = stringResource(R.string.user_wallet_list_unlock_all_face_id),
showProgress = state.showUnlockProgress,
onClick = onUnlockClick,
text = stringResource(R.string.user_wallet_list_add_button),
showProgress = state.showAddCardProgress,
icon = painterResource(id = R.drawable.ic_tangem),
onClick = onAddCardClick,
)
SpacerH12()
SpacerH16()
}
SecondaryButtonIconRight(
modifier = Modifier
.padding(horizontal = TangemTheme.dimens.spacing16)
.fillMaxWidth(),
text = stringResource(R.string.user_wallet_list_add_button),
showProgress = state.showAddCardProgress,
icon = painterResource(id = R.drawable.ic_tangem),
onClick = onAddCardClick,
)
SpacerH16()
}
}
@ -163,6 +162,49 @@ private fun EditWalletsBar(
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun WalletsList(
modifier: Modifier = Modifier,
multiCurrencyWallets: List<UserWalletItem>,
singleCurrencyWallets: List<UserWalletItem>,
selectedWalletId: String?,
checkedWalletIds: List<String>,
isLocked: Boolean,
onWalletClick: (walletId: String) -> Unit,
onWalletLongClick: (walletId: String) -> Unit,
) {
Column(modifier = modifier) {
val walletsSection = @Composable { wallets: List<UserWalletItem> ->
wallets.forEachIndexed { index, wallet ->
if (index == 0) {
Text(
modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
text = wallet.headerText.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
}
WalletItem(
modifier = Modifier
.combinedClickable(
onClick = { onWalletClick(wallet.id) },
onLongClick = { onWalletLongClick(wallet.id) },
)
.padding(all = TangemTheme.dimens.spacing16),
wallet = wallet,
isSelected = wallet.id == selectedWalletId,
isChecked = wallet.id in checkedWalletIds,
isLocked = isLocked && wallet.id != selectedWalletId,
)
}
}
walletsSection(multiCurrencyWallets)
walletsSection(singleCurrencyWallets)
}
}
// region Preview
@Composable
private fun WalletSelectorScreenContentSample(
@ -221,7 +263,7 @@ private fun WalletSelectorScreenContent_EditWallets_Sample(
shape = TangemTheme.shapes.bottomSheet,
),
state = MockData.state
.copy(editingWalletsIds = listOf(MockData.userWalletList[2].id)),
.copy(editingWalletsIds = listOf(MockData.state.multiCurrencyWallets[2].id)),
onWalletClick = { /* no-op */ },
onWalletLongClick = { /* no-op */ },
onUnlockClick = { /* no-op */ },

View file

@ -1,66 +0,0 @@
@file:OptIn(ExperimentalFoundationApi::class)
package com.tangem.tap.features.walletSelector.ui.components
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.tangem.core.ui.res.TangemTheme
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
import com.tangem.tap.features.walletSelector.ui.model.UserWalletItem
@Composable
internal fun WalletList(
modifier: Modifier = Modifier,
wallets: List<UserWalletItem>,
selectedWalletId: String?,
checkedWalletIds: List<String>,
isLocked: Boolean,
onWalletClick: (walletId: String) -> Unit,
onWalletLongClick: (walletId: String) -> Unit,
) {
val multiCurrencyWallets = remember(wallets) {
wallets.filter { it.type is UserWalletItem.Type.MultiCurrency }
}
val singleCurrencyWallets = remember(wallets) {
wallets.filter { it.type is UserWalletItem.Type.SingleCurrency }
}
LazyColumn(modifier = modifier) {
val walletSection: (List<UserWalletItem>) -> Unit = { wallets ->
itemsIndexed(
items = wallets,
key = { _, item -> item.id },
) { index, wallet ->
if (index == 0) {
Text(
modifier = Modifier.padding(start = TangemTheme.dimens.spacing16),
text = wallet.type.headerText.resolveReference(),
style = TangemTheme.typography.subtitle2,
color = TangemTheme.colors.text.tertiary,
)
}
WalletItem(
modifier = Modifier
.combinedClickable(
onClick = { onWalletClick(wallet.id) },
onLongClick = { onWalletLongClick(wallet.id) },
)
.padding(all = TangemTheme.dimens.spacing16),
wallet = wallet,
isSelected = wallet.id == selectedWalletId,
isChecked = wallet.id in checkedWalletIds,
isLocked = isLocked && wallet.id != selectedWalletId,
)
}
}
walletSection(multiCurrencyWallets)
walletSection(singleCurrencyWallets)
}
}

View file

@ -5,42 +5,38 @@ import com.tangem.tap.features.details.ui.cardsettings.TextReference
import com.tangem.wallet.R
@Immutable
internal data class UserWalletItem(
val id: String,
val name: String,
val imageUrl: String,
val balance: Balance,
val type: Type,
) {
internal sealed interface UserWalletItem {
val id: String
val name: String
val imageUrl: String
val balance: Balance
val headerText: TextReference
get() = when (this) {
is MultiCurrencyUserWalletItem -> TextReference.Res(R.string.user_wallet_list_multi_header)
is SingleCurrencyUserWalletItem -> TextReference.Res(R.string.user_wallet_list_single_header)
}
@Immutable
data class Balance(
val amount: String,
val isLoading: Boolean,
) {
companion object {
val Loading = Balance(
amount = "0.00",
isLoading = true,
)
}
}
)
}
sealed interface Type {
val headerText: TextReference
internal data class MultiCurrencyUserWalletItem(
override val id: String,
override val name: String,
override val imageUrl: String,
override val balance: UserWalletItem.Balance,
val tokensCount: Int,
val cardsInWallet: Int,
) : UserWalletItem
@Immutable
class MultiCurrency(
val tokensCount: Int,
val cardsInWallet: Int,
) : Type {
override val headerText: TextReference
get() = TextReference.Res(R.string.user_wallet_list_multi_header)
}
@Immutable
class SingleCurrency(val tokenName: String) : Type {
override val headerText: TextReference
get() = TextReference.Res(R.string.user_wallet_list_single_header)
}
}
}
internal data class SingleCurrencyUserWalletItem(
override val id: String,
override val name: String,
override val imageUrl: String,
override val balance: UserWalletItem.Balance,
val tokenName: String,
) : UserWalletItem