Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-19 17:03:45 +08:00
parent 0a09db0da8
commit b90a305734
12 changed files with 75 additions and 49 deletions

View file

@ -17,7 +17,7 @@ interface CardTypesResolver {
fun isStart2Coin(): Boolean
fun isDev(): Boolean
fun isDevKit(): Boolean
fun isMultiwalletAllowed(): Boolean

View file

@ -37,7 +37,7 @@ internal class TangemCardTypesResolver(
override fun isStart2Coin(): Boolean = card.isStart2Coin
override fun isDev(): Boolean = card.firmwareVersion.type != FirmwareVersion.FirmwareType.Release
override fun isDevKit(): Boolean = card.batchId == DEV_KIT_CARD_BATCH_ID
override fun isMultiwalletAllowed(): Boolean {
return !isTangemTwins() && !card.isStart2Coin && !isTangemNote() &&
@ -109,4 +109,9 @@ internal class TangemCardTypesResolver(
}
}
}
private companion object {
const val DEV_KIT_CARD_BATCH_ID = "CB83"
}
}

View file

@ -32,7 +32,7 @@ import java.util.UUID
@Suppress("LargeClass")
internal object WalletPreviewData {
val walletTopBarConfig by lazy { WalletTopBarConfig(onScanCardClick = {}, onMoreClick = {}) }
val topBarConfig by lazy { WalletTopBarConfig(onDetailsClick = {}) }
val walletCardContentState by lazy {
WalletCardState.Content(
@ -326,7 +326,7 @@ internal object WalletPreviewData {
val multicurrencyWalletScreenState by lazy {
WalletMultiCurrencyState.Content(
onBackClick = {},
topBarConfig = walletTopBarConfig,
topBarConfig = topBarConfig,
walletsListConfig = walletListConfig,
tokensListState = WalletTokensListState.Content(
persistentListOf(
@ -390,7 +390,7 @@ internal object WalletPreviewData {
val singleWalletScreenState by lazy {
WalletSingleCurrencyState.Content(
onBackClick = {},
topBarConfig = walletTopBarConfig,
topBarConfig = topBarConfig,
walletsListConfig = walletListConfig,
pullToRefreshConfig = WalletPullToRefreshConfig(
isRefreshing = false,

View file

@ -21,13 +21,13 @@ internal object WalletImageResolver {
fun resolve(userWallet: UserWallet): Int? {
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
return when {
cardTypesResolver.isDev() -> R.drawable.ill_dev_120_106
cardTypesResolver.isWallet2() -> userWallet.resolveWallet2()
cardTypesResolver.isTangemWallet() -> R.drawable.ill_wallet_120_106
cardTypesResolver.isWhiteWallet() -> R.drawable.ill_old_wallet_120_106
cardTypesResolver.isTangemTwins() -> R.drawable.ill_twin_120_106
cardTypesResolver.isStart2Coin() -> R.drawable.ill_start2coin_120_106
cardTypesResolver.isTangemNote() -> resolveNote(blockchain = cardTypesResolver.getBlockchain())
cardTypesResolver.isDevKit() -> R.drawable.ill_dev_120_106
else -> null
}
}

View file

@ -2,7 +2,10 @@ package com.tangem.feature.wallet.presentation.wallet.state
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.event.StateEvent
import com.tangem.feature.wallet.presentation.wallet.state.components.*
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletPullToRefreshConfig
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTopBarConfig
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletsListConfig
import kotlinx.collections.immutable.ImmutableList
/**

View file

@ -3,7 +3,6 @@ package com.tangem.feature.wallet.presentation.wallet.state.components
/**
* Wallet screen top bar config
*
* @property onScanCardClick lambda be invoked when scan card button is clicked
* @property onMoreClick lambda be invoked when more button is clicked
* @property onDetailsClick lambda be invoked when details button is clicked
*/
data class WalletTopBarConfig(val onScanCardClick: () -> Unit, val onMoreClick: () -> Unit)
internal data class WalletTopBarConfig(val onDetailsClick: () -> Unit)

View file

@ -55,7 +55,7 @@ internal class WalletLockedConverter(
}
private fun WalletTopBarConfig.updateCallback(): WalletTopBarConfig {
return copy(onMoreClick = clickIntents::onUnlockWalletNotificationClick)
return copy(onDetailsClick = clickIntents::onUnlockWalletNotificationClick)
}
private fun WalletPullToRefreshConfig.stopRefreshing(): WalletPullToRefreshConfig {

View file

@ -81,10 +81,7 @@ internal class WalletSkeletonStateConverter(
}
private fun createTopBarConfig(): WalletTopBarConfig {
return WalletTopBarConfig(
onScanCardClick = clickIntents::onScanCardClick,
onMoreClick = clickIntents::onDetailsClick,
)
return WalletTopBarConfig(onDetailsClick = clickIntents::onDetailsClick)
}
private fun createWalletsListConfig(value: SkeletonModel): WalletsListConfig {

View file

@ -80,7 +80,7 @@ internal class WalletsUnlockStateConverter(
}
private fun WalletTopBarConfig.updateCallback(): WalletTopBarConfig {
return copy(onMoreClick = clickIntents::onDetailsClick)
return copy(onDetailsClick = clickIntents::onDetailsClick)
}
private fun WalletsListConfig.unlockWallets(action: UnlockWalletAction): WalletsListConfig {

View file

@ -8,7 +8,6 @@ import com.tangem.core.ui.event.EventEffect
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.extensions.resolveReference
import com.tangem.feature.wallet.presentation.wallet.state.WalletEvent
import kotlinx.coroutines.delay
@Composable
internal fun WalletEventEffect(
@ -24,7 +23,6 @@ internal fun WalletEventEffect(
when (value) {
is WalletEvent.ChangeWallet -> {
onAutoScrollSet()
delay(timeMillis = 800)
walletsListState.animateScrollToItem(index = value.index)
}
is WalletEvent.ShowError -> {

View file

@ -12,7 +12,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTopB
/**
* Wallet screen top bar
*
* @param config top bar config
* @param config component config
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -22,11 +22,8 @@ internal fun WalletTopBar(config: WalletTopBarConfig) {
Icon(painter = painterResource(id = R.drawable.img_tangem_logo_90_24), contentDescription = null)
},
actions = {
IconButton(onClick = config.onScanCardClick) {
Icon(painter = painterResource(id = R.drawable.ic_tap_card_24), contentDescription = "Scan card")
}
IconButton(onClick = config.onMoreClick) {
Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = "More")
IconButton(onClick = config.onDetailsClick) {
Icon(painter = painterResource(id = R.drawable.ic_more_vertical_24), contentDescription = null)
}
},
colors = TopAppBarDefaults.topAppBarColors(
@ -42,7 +39,7 @@ internal fun WalletTopBar(config: WalletTopBarConfig) {
@Composable
private fun Preview_WalletTopBar_LightTheme() {
TangemTheme(isDark = false) {
WalletTopBar(config = WalletPreviewData.walletTopBarConfig)
WalletTopBar(config = WalletPreviewData.topBarConfig)
}
}
@ -50,6 +47,6 @@ private fun Preview_WalletTopBar_LightTheme() {
@Composable
private fun Preview_WalletTopBar_DarkTheme() {
TangemTheme(isDark = true) {
WalletTopBar(config = WalletPreviewData.walletTopBarConfig)
WalletTopBar(config = WalletPreviewData.topBarConfig)
}
}

View file

@ -164,7 +164,7 @@ internal class WalletViewModel @Inject constructor(
when (val action = walletsUpdateActionResolver.resolve(sourceList)) {
is WalletsUpdateActionResolver.Action.Initialize -> {
loadAndUpdateState(action.selectedWalletIndex)
initializeAndLoadState(selectedWalletIndex = action.selectedWalletIndex)
}
is WalletsUpdateActionResolver.Action.UpdateWalletName -> {
uiState = stateFactory.getStateWithUpdatedWalletName(name = action.name)
@ -178,12 +178,18 @@ internal class WalletViewModel @Inject constructor(
deleteWalletAndUpdateState(action = action)
}
is WalletsUpdateActionResolver.Action.AddWallet -> {
loadAndUpdateState(action.selectedWalletIndex)
scrollAndUpdateState(action.selectedWalletIndex)
}
is WalletsUpdateActionResolver.Action.Unknown -> Unit
}
}
private fun initializeAndLoadState(selectedWalletIndex: Int) {
uiState = stateFactory.getSkeletonState(wallets = wallets, selectedWalletIndex = selectedWalletIndex)
getContentItemsUpdates(index = selectedWalletIndex)
}
private fun deleteWalletAndUpdateState(action: WalletsUpdateActionResolver.Action.DeleteWallet) {
val cacheState = WalletStateCache.getState(userWalletId = action.selectedWalletId)
if (cacheState != null) {
@ -198,12 +204,22 @@ internal class WalletViewModel @Inject constructor(
getContentItemsUpdates(action.selectedWalletIndex)
}
} else {
loadAndUpdateState(selectedWalletIndex = action.selectedWalletIndex)
/* It's impossible case because user can delete only visible state, but we support this case */
scrollAndUpdateState(selectedWalletIndex = action.selectedWalletIndex)
}
}
private fun loadAndUpdateState(selectedWalletIndex: Int) {
uiState = stateFactory.getSkeletonState(wallets = wallets, selectedWalletIndex = selectedWalletIndex)
private fun scrollAndUpdateState(selectedWalletIndex: Int) {
uiState = stateFactory.getSkeletonState(
wallets = wallets,
selectedWalletIndex = selectedWalletIndex,
)
uiState = stateFactory.getStateAndTriggerEvent(
state = uiState,
event = WalletEvent.ChangeWallet(index = selectedWalletIndex),
setUiState = { uiState = it },
)
getContentItemsUpdates(index = selectedWalletIndex)
}
@ -224,30 +240,42 @@ internal class WalletViewModel @Inject constructor(
if (userWallet != null) {
saveWalletUseCase(userWallet = userWallet, canOverride = false)
.onLeft { saveWalletError ->
when (saveWalletError) {
is SaveWalletError.DataError -> Unit
is SaveWalletError.WalletAlreadySaved -> {
uiState = stateFactory.getStateAndTriggerEvent(
state = uiState,
event = WalletEvent.ShowError(
text = TextReference.Res(saveWalletError.messageId),
),
setUiState = { uiState = it },
)
}
}
showErrorIfWalletNotSaved(
error = saveWalletError,
scannedWalletId = userWallet.walletId,
)
}
}
}
.doOnFailure { tangemError ->
}
}
private fun showErrorIfWalletNotSaved(error: SaveWalletError, scannedWalletId: UserWalletId) {
when (error) {
is SaveWalletError.DataError -> Unit
is SaveWalletError.WalletAlreadySaved -> {
viewModelScope.launch(dispatchers.main) {
val alreadySavedWalletIndex = (uiState as? WalletState.ContentState)?.walletsListConfig
?.wallets?.indexOfFirst { it.id == scannedWalletId }
if (alreadySavedWalletIndex != null && alreadySavedWalletIndex != -1) {
uiState = stateFactory.getStateAndTriggerEvent(
state = uiState,
event = WalletEvent.ChangeWallet(index = alreadySavedWalletIndex),
setUiState = { uiState = it },
)
// Delay between events
delay(timeMillis = 500L)
}
uiState = stateFactory.getStateAndTriggerEvent(
state = uiState,
event = WalletEvent.ShowError(
text = TextReference.Str(tangemError.customMessage),
),
event = WalletEvent.ShowError(text = TextReference.Res(error.messageId)),
setUiState = { uiState = it },
)
}
}
}
}
@ -372,8 +400,7 @@ internal class WalletViewModel @Inject constructor(
getContentItemsUpdates(index)
}
} else {
uiState = stateFactory.getSkeletonState(wallets = wallets, selectedWalletIndex = index)
getContentItemsUpdates(index = index)
initializeAndLoadState(selectedWalletIndex = index)
}
}
.saveIn(onWalletChangeJobHolder)