Updated on 2026-08-14
This commit is contained in:
parent
48b8c77f5d
commit
cb795ebf3d
27 changed files with 432 additions and 262 deletions
|
|
@ -13,11 +13,13 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation(projects.features.welcome.api)
|
||||
implementation(projects.features.wallet.api)
|
||||
|
||||
/** Core */
|
||||
implementation(projects.core.configToggles)
|
||||
implementation(projects.core.decompose)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.common.routing)
|
||||
implementation(projects.common.ui)
|
||||
|
||||
|
|
@ -30,6 +32,7 @@ dependencies {
|
|||
/** Domain */
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.card)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
|
|
@ -54,4 +57,5 @@ dependencies {
|
|||
implementation(deps.timber)
|
||||
implementation(tangemDeps.card.core)
|
||||
implementation(tangemDeps.blockchain)
|
||||
implementation(tangemDeps.hot.core)
|
||||
}
|
||||
|
|
@ -1,18 +1,233 @@
|
|||
package com.tangem.features.welcome.impl.model
|
||||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.decompose.ui.UiMessageSender
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.core.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.core.wallets.error.UnlockWalletError
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetIsBiometricsEnabledUseCase
|
||||
import com.tangem.features.wallet.utils.UserWalletsFetcher
|
||||
import com.tangem.features.welcome.impl.R
|
||||
import com.tangem.features.welcome.impl.ui.state.AddWalletBottomSheetContentUM
|
||||
import com.tangem.features.welcome.impl.ui.state.AddWalletBottomSheetContentUM.Option.*
|
||||
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
|
||||
import com.tangem.hot.sdk.model.HotWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ModelScoped
|
||||
internal class WelcomeModel @Inject constructor(
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val router: Router,
|
||||
private val uiMessageSender: UiMessageSender,
|
||||
private val userWalletsFetcherFactory: UserWalletsFetcher.Factory,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val getIsBiometricsEnabledUseCase: GetIsBiometricsEnabledUseCase,
|
||||
) : Model() {
|
||||
|
||||
// TODO add intent handling
|
||||
// val params
|
||||
val uiState: StateFlow<WelcomeUM>
|
||||
field = MutableStateFlow(WelcomeUM.Plain)
|
||||
field = MutableStateFlow<WelcomeUM>(WelcomeUM.Plain)
|
||||
|
||||
private val walletsFetcher = userWalletsFetcherFactory.create(
|
||||
messageSender = uiMessageSender,
|
||||
onlyMultiCurrency = false,
|
||||
authMode = true,
|
||||
onWalletClick = { walletId ->
|
||||
modelScope.launch {
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
val userWallet = userWallets.first { it.walletId == walletId }
|
||||
onUserWalletClick(userWallet)
|
||||
}
|
||||
},
|
||||
)
|
||||
private val walletsFetcherJobHolder = JobHolder()
|
||||
private val wallets = MutableStateFlow<ImmutableList<UserWalletItemUM>>(persistentListOf())
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
userWalletsListRepository.load()
|
||||
wallets.value = walletsFetcher.userWallets.first()
|
||||
|
||||
launch {
|
||||
walletsFetcher.userWallets
|
||||
.collectLatest { wallets.value = it }
|
||||
}
|
||||
|
||||
tryToUnlockRightAway()
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryToUnlockRightAway() {
|
||||
modelScope.launch {
|
||||
if (canUnlockWithBiometrics()) {
|
||||
userWalletsListRepository.unlockAllWallets()
|
||||
.onRight {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
.onLeft {
|
||||
it.handle(null, onUserCancelled = { tryToUnlockWithAccessCodeRightAway() })
|
||||
setSelectWalletState()
|
||||
}
|
||||
} else {
|
||||
tryToUnlockWithAccessCodeRightAway()
|
||||
setSelectWalletState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryToUnlockWithAccessCodeRightAway() = modelScope.launch {
|
||||
if (onlyOneHotWalletWithAccessCode()) {
|
||||
val userWallets = userWalletsListRepository.userWalletsSync()
|
||||
val userWallet = userWallets.first()
|
||||
unlockWallet(userWallet.walletId, UserWalletsListRepository.UnlockMethod.AccessCode)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSelectWalletState() {
|
||||
modelScope.launch {
|
||||
uiState.value = WelcomeUM.SelectWallet(
|
||||
wallets = walletsFetcher.userWallets.first(),
|
||||
showUnlockWithBiometricButton = canUnlockWithBiometrics(),
|
||||
addWalletClick = ::addWalletClick,
|
||||
onUnlockWithBiometricClick = {
|
||||
modelScope.launch {
|
||||
userWalletsListRepository.unlockAllWallets()
|
||||
.onRight {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
.onLeft {
|
||||
it.handle(null, onUserCancelled = { /* ignore */ })
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
wallets.collectLatest { wallets ->
|
||||
updateSelectState {
|
||||
it.copy(wallets = wallets)
|
||||
}
|
||||
}
|
||||
}.saveIn(walletsFetcherJobHolder)
|
||||
}
|
||||
|
||||
private fun addWalletClick() {
|
||||
updateSelectState { currentState ->
|
||||
currentState.copy(
|
||||
addWalletBottomSheet = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
content = AddWalletBottomSheetContentUM(
|
||||
onOptionClick = ::onAddWalletOptionClick,
|
||||
),
|
||||
onDismissRequest = {
|
||||
updateSelectState {
|
||||
it.copy(addWalletBottomSheet = it.addWalletBottomSheet.copy(isShown = false))
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onAddWalletOptionClick(option: AddWalletBottomSheetContentUM.Option) {
|
||||
when (option) {
|
||||
Create -> router.push(AppRoute.CreateWalletSelection)
|
||||
Add -> router.push(AppRoute.AddExistingWallet)
|
||||
Buy -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun onlyOneHotWalletWithAccessCode(): Boolean {
|
||||
val userWalletsWithLock = userWalletsListRepository.userWalletsSync().filter { it.isLocked }
|
||||
if (userWalletsWithLock.size != 1) return false
|
||||
val wallet = userWalletsWithLock.first()
|
||||
return wallet is UserWallet.Hot && wallet.hotWalletId.authType != HotWalletId.AuthType.NoPassword
|
||||
}
|
||||
|
||||
private fun onUserWalletClick(userWallet: UserWallet) = modelScope.launch {
|
||||
if (userWallet.isLocked.not()) {
|
||||
// If the wallet is not locked, we can proceed to the wallet screen directly
|
||||
userWalletsListRepository.select(userWallet.walletId)
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val unlockMethod = when (userWallet) {
|
||||
is UserWallet.Cold -> UserWalletsListRepository.UnlockMethod.Scan
|
||||
is UserWallet.Hot -> UserWalletsListRepository.UnlockMethod.AccessCode
|
||||
}
|
||||
|
||||
unlockWallet(userWallet.walletId, unlockMethod)
|
||||
}
|
||||
|
||||
private fun canUnlockWithBiometrics(): Boolean {
|
||||
return getIsBiometricsEnabledUseCase.canUseBiometry()
|
||||
}
|
||||
|
||||
suspend fun unlockWallet(userWalletId: UserWalletId, unlockMethod: UserWalletsListRepository.UnlockMethod) {
|
||||
userWalletsListRepository.unlock(userWalletId, unlockMethod)
|
||||
.onRight {
|
||||
userWalletsListRepository.select(userWalletId)
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
.onLeft { error ->
|
||||
error.handle(specificWalletId = userWalletId, onUserCancelled = { /* ignore*/ })
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun UnlockWalletError.handle(specificWalletId: UserWalletId?, onUserCancelled: () -> Unit = { }) {
|
||||
when (this) {
|
||||
UnlockWalletError.AlreadyUnlocked -> {
|
||||
// this should not happen, as we check for locked state before this
|
||||
specificWalletId?.let { userWalletsListRepository.select(it) }
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
UnlockWalletError.ScannedCardWalletNotMatched -> {
|
||||
// TODO Scanned card does not match the wallet
|
||||
}
|
||||
UnlockWalletError.UnableToUnlock -> {
|
||||
// TODO Unable to unlock the wallet"
|
||||
}
|
||||
UnlockWalletError.UserCancelled -> onUserCancelled()
|
||||
UnlockWalletError.UserWalletNotFound -> {
|
||||
// This should never happen in this flow, as we always check for the wallet existence before unlocking
|
||||
Timber.e("User wallet not found for unlock: $specificWalletId")
|
||||
uiMessageSender.send(
|
||||
SnackbarMessage(TextReference.Res(R.string.generic_error)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSelectState(block: (WelcomeUM.SelectWallet) -> WelcomeUM.SelectWallet) {
|
||||
uiState.update { currentState ->
|
||||
if (currentState is WelcomeUM.SelectWallet) {
|
||||
block(currentState)
|
||||
} else {
|
||||
currentState
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,10 +10,11 @@ import androidx.compose.runtime.*
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.welcome.impl.ui.state.WalletUM
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
|
|
@ -34,10 +35,6 @@ internal fun Welcome(state: WelcomeUM, modifier: Modifier = Modifier) {
|
|||
state = st,
|
||||
modifier = modifier,
|
||||
)
|
||||
is WelcomeUM.EnterAccessCode -> WelcomeEnterAccessCode(
|
||||
state = st,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,22 +46,30 @@ private fun Preview() {
|
|||
TangemThemePreview {
|
||||
val state = WelcomeUM.SelectWallet(
|
||||
wallets = persistentListOf(
|
||||
WalletUM(
|
||||
name = TextReference.Str("Wallet 1"),
|
||||
subtitle = TextReference.Str("3 cards"),
|
||||
imageState = WalletUM.ImageState.Loading,
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = UserWalletItemUM.Information.Loading,
|
||||
balance = UserWalletItemUM.Balance.Loaded(
|
||||
value = "1.2345 BTC",
|
||||
isFlickering = false,
|
||||
),
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
WalletUM(
|
||||
name = TextReference.Str("Wallet 1"),
|
||||
subtitle = TextReference.Str("Mobile wallet"),
|
||||
imageState = WalletUM.ImageState.MobileWallet,
|
||||
UserWalletItemUM(
|
||||
id = UserWalletId("user_wallet_3".encodeToByteArray()),
|
||||
name = stringReference("Multi Card"),
|
||||
information = UserWalletItemUM.Information.Failed,
|
||||
imageState = UserWalletItemUM.ImageState.MobileWallet,
|
||||
balance = UserWalletItemUM.Balance.Locked,
|
||||
isEnabled = true,
|
||||
onClick = {},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
var currentState by remember { mutableStateOf<WelcomeUM>(WelcomeUM.EnterAccessCode()) }
|
||||
var currentState by remember { mutableStateOf<WelcomeUM>(WelcomeUM.SelectWallet()) }
|
||||
|
||||
Box {
|
||||
Welcome(currentState)
|
||||
|
|
@ -74,11 +79,7 @@ private fun Preview() {
|
|||
onClick = {
|
||||
currentState = when (currentState) {
|
||||
is WelcomeUM.Plain -> state
|
||||
is WelcomeUM.SelectWallet -> WelcomeUM.EnterAccessCode(
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
)
|
||||
is WelcomeUM.EnterAccessCode -> WelcomeUM.Plain
|
||||
is WelcomeUM.SelectWallet -> WelcomeUM.Plain
|
||||
}
|
||||
},
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
package com.tangem.features.welcome.impl.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedContentScope
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH24
|
||||
import com.tangem.core.ui.components.appbar.TopAppBarButton
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.fields.PinTextField
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
internal fun AnimatedContentScope.WelcomeEnterAccessCode(
|
||||
state: WelcomeUM.EnterAccessCode,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.statusBarsPadding(),
|
||||
) {
|
||||
Column {
|
||||
TopAppBarButton(
|
||||
modifier = Modifier
|
||||
.padding(12.dp),
|
||||
button = TopAppBarButtonUM.Back(onBackClicked = state.onBackClick),
|
||||
tint = TangemTheme.colors.icon.primary1,
|
||||
)
|
||||
|
||||
SpacerH(68.dp)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.animateEnterExit(
|
||||
enter = slideInVertically(
|
||||
tween(delayMillis = 300),
|
||||
initialOffsetY = { it + 200 },
|
||||
) + fadeIn(tween(delayMillis = 300)),
|
||||
exit = fadeOut(),
|
||||
)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
text = "Enter Access Code",
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
SpacerH24()
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.animateEnterExit(
|
||||
enter = slideInVertically(
|
||||
tween(delayMillis = 300),
|
||||
initialOffsetY = { it + 200 },
|
||||
) + fadeIn(tween(delayMillis = 300)),
|
||||
exit = fadeOut(),
|
||||
)
|
||||
.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
PinTextField(
|
||||
length = 6,
|
||||
isPasswordVisual = true,
|
||||
value = state.value,
|
||||
onValueChange = state.onValueChange,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SecondaryButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.navigationBarsPadding()
|
||||
.imePadding()
|
||||
.animateEnterExit(fadeIn(), fadeOut()),
|
||||
text = "Log in with biometric",
|
||||
onClick = state.onUnlockWithBiometricClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,8 +9,10 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.welcome.impl.R
|
||||
|
||||
@Composable
|
||||
|
|
@ -26,4 +28,14 @@ internal fun WelcomePlain(modifier: Modifier = Modifier) {
|
|||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
TangemThemePreview {
|
||||
WelcomePlain(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,12 +5,9 @@ import androidx.compose.animation.core.tween
|
|||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
|
|
@ -20,14 +17,13 @@ import androidx.compose.ui.draw.clip
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.common.ui.userwallet.CardImage
|
||||
import com.tangem.common.ui.userwallet.UserWalletItem
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.block.TangemBlockCardColors
|
||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.welcome.impl.R
|
||||
import com.tangem.features.welcome.impl.ui.state.WalletUM
|
||||
import com.tangem.features.welcome.impl.ui.state.WelcomeUM
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -45,7 +41,7 @@ internal fun AnimatedContentScope.WelcomeSelectWallet(state: WelcomeUM.SelectWal
|
|||
TitleText()
|
||||
SpacerH12()
|
||||
|
||||
var actualWallets by remember { mutableStateOf<ImmutableList<WalletUM>>(persistentListOf()) }
|
||||
var actualWallets by remember { mutableStateOf<ImmutableList<UserWalletItemUM>>(persistentListOf()) }
|
||||
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
LazyColumn(
|
||||
|
|
@ -62,9 +58,12 @@ internal fun AnimatedContentScope.WelcomeSelectWallet(state: WelcomeUM.SelectWal
|
|||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
itemsIndexed(actualWallets) { index, walletState ->
|
||||
WalletItem(
|
||||
UserWalletItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = walletState,
|
||||
modifier = Modifier,
|
||||
blockColors = TangemBlockCardColors.copy(
|
||||
containerColor = TangemTheme.colors.field.primary,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -165,66 +164,4 @@ private fun AnimatedContentScope.TitleText(modifier: Modifier = Modifier) {
|
|||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
||||
private fun WalletItem(state: WalletUM, modifier: Modifier = Modifier) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.clip(TangemTheme.shapes.roundedCornersXMedium)
|
||||
.background(TangemTheme.colors.background.secondary, TangemTheme.shapes.roundedCornersXMedium)
|
||||
.clickable(onClick = state.onClick)
|
||||
.padding(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
WalletImage(state.imageState)
|
||||
|
||||
SpacerW12()
|
||||
|
||||
Column(Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = state.name.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = state.subtitle.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WalletImage(state: WalletUM.ImageState, modifier: Modifier = Modifier) {
|
||||
when (state) {
|
||||
WalletUM.ImageState.MobileWallet -> {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(36.dp)
|
||||
.background(TangemTheme.colors.icon.accent.copy(alpha = 0.1f), CircleShape),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(R.drawable.ic_wallet_filled_24),
|
||||
tint = TangemTheme.colors.icon.accent,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
CardImage(
|
||||
imageState = when (state) {
|
||||
is WalletUM.ImageState.Image -> UserWalletItemUM.ImageState.Image(state.artwork)
|
||||
WalletUM.ImageState.Loading -> UserWalletItemUM.ImageState.Loading
|
||||
else -> error("")
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
package com.tangem.features.welcome.impl.ui.state
|
||||
|
||||
import com.tangem.core.ui.components.artwork.ArtworkUM
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import javax.annotation.concurrent.Immutable
|
||||
|
||||
internal data class WalletUM(
|
||||
val name: TextReference,
|
||||
val subtitle: TextReference,
|
||||
val imageState: ImageState,
|
||||
val onClick: () -> Unit,
|
||||
) {
|
||||
|
||||
@Immutable
|
||||
sealed class ImageState {
|
||||
data object MobileWallet : ImageState()
|
||||
data object Loading : ImageState()
|
||||
data class Image(
|
||||
val artwork: ArtworkUM,
|
||||
) : ImageState()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.features.welcome.impl.ui.state
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.common.ui.userwallet.state.UserWalletItemUM
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -11,17 +12,10 @@ internal sealed class WelcomeUM {
|
|||
data object Plain : WelcomeUM()
|
||||
|
||||
data class SelectWallet(
|
||||
val wallets: ImmutableList<WalletUM> = persistentListOf(),
|
||||
val wallets: ImmutableList<UserWalletItemUM> = persistentListOf(),
|
||||
val showUnlockWithBiometricButton: Boolean = false,
|
||||
val addWalletBottomSheet: TangemBottomSheetConfig = TangemBottomSheetConfig.Empty,
|
||||
val onUnlockWithBiometricClick: () -> Unit = {},
|
||||
val addWalletClick: () -> Unit = {},
|
||||
) : WelcomeUM()
|
||||
|
||||
data class EnterAccessCode(
|
||||
val value: String = "",
|
||||
val onUnlockWithBiometricClick: () -> Unit = {},
|
||||
val onValueChange: (String) -> Unit = {},
|
||||
val onBackClick: () -> Unit = {},
|
||||
) : WelcomeUM()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue