Updated on 2026-08-14
This commit is contained in:
parent
3c59214c76
commit
4c903fc654
73 changed files with 886 additions and 190 deletions
|
|
@ -9,11 +9,15 @@ plugins {
|
|||
|
||||
dependencies {
|
||||
/** Core modules */
|
||||
implementation(project(":core:analytics"))
|
||||
implementation(projects.core.analytics)
|
||||
implementation(projects.core.analytics.models)
|
||||
implementation(project(":core:featuretoggles"))
|
||||
implementation(project(":core:utils"))
|
||||
implementation(project(":core:ui"))
|
||||
implementation(projects.core.featuretoggles)
|
||||
implementation(projects.core.utils)
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.common)
|
||||
|
||||
/** Domain modules **/
|
||||
implementation(projects.domain.balanceHiding)
|
||||
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.activity.compose)
|
||||
|
|
@ -30,10 +34,11 @@ dependencies {
|
|||
implementation(deps.compose.constraintLayout)
|
||||
|
||||
/** Api */
|
||||
implementation(project(":features:swap:api"))
|
||||
implementation(projects.features.swap.api)
|
||||
|
||||
/** Domain */
|
||||
implementation(project(":features:swap:domain"))
|
||||
implementation(projects.features.swap.domain)
|
||||
implementation(projects.domain.settings)
|
||||
|
||||
/** Other libraries */
|
||||
implementation(deps.compose.shimmer)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ data class SwapCardData(
|
|||
val tokenIconUrl: String,
|
||||
val tokenCurrency: String,
|
||||
val balance: String,
|
||||
val isBalanceHidden: Boolean,
|
||||
val isNotNativeToken: Boolean,
|
||||
val canSelectAnotherToken: Boolean = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@ class SwapFragment : Fragment() {
|
|||
|
||||
private val viewModel by viewModels<SwapViewModel>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
lifecycle.addObserver(viewModel)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
viewModel.setRouter(
|
||||
SwapRouter(
|
||||
|
|
@ -70,6 +75,11 @@ class SwapFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
lifecycle.removeObserver(viewModel)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CURRENCY_BUNDLE_KEY = "swap_currency"
|
||||
const val DERIVATION_PATH = "DERIVATION_STYLE"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.swap.ui
|
|||
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.states.Item
|
||||
import com.tangem.core.ui.components.states.SelectableItemsState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
|
@ -21,7 +22,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
* State builder creates a specific states for SwapScreen
|
||||
*/
|
||||
@Suppress("LargeClass")
|
||||
internal class StateBuilder(val actions: UiActions) {
|
||||
internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider: Provider<Boolean>) {
|
||||
|
||||
private val tokensDataConverter = TokensDataConverter(actions.onSearchEntered, actions.onTokenSelected)
|
||||
|
||||
|
|
@ -39,6 +40,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
canSelectAnotherToken = false,
|
||||
isNotNativeToken = initialCurrency.isNonNative(),
|
||||
balance = "",
|
||||
isBalanceHidden = true,
|
||||
),
|
||||
receiveCardData = SwapCardData(
|
||||
type = TransactionCardType.ReceiveCard(),
|
||||
|
|
@ -50,6 +52,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
balance = "",
|
||||
isNotNativeToken = false,
|
||||
coinId = null,
|
||||
isBalanceHidden = true,
|
||||
),
|
||||
fee = FeeState.Loading,
|
||||
networkCurrency = networkInfo.blockchainCurrency,
|
||||
|
|
@ -84,6 +87,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
isNotNativeToken = fromToken.isNonNative(),
|
||||
canSelectAnotherToken = canSelectSendToken,
|
||||
balance = if (!canSelectSendToken) uiStateHolder.sendCardData.balance else "",
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
receiveCardData = SwapCardData(
|
||||
type = TransactionCardType.ReceiveCard(),
|
||||
|
|
@ -95,6 +99,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
isNotNativeToken = toToken.isNonNative(),
|
||||
canSelectAnotherToken = canSelectReceiveToken,
|
||||
balance = if (!canSelectReceiveToken) uiStateHolder.receiveCardData.balance else "",
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
fee = FeeState.Loading,
|
||||
swapButton = SwapButton(enabled = false, loading = true, onClick = {}),
|
||||
|
|
@ -144,6 +149,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
tokenCurrency = uiStateHolder.sendCardData.tokenCurrency,
|
||||
canSelectAnotherToken = uiStateHolder.sendCardData.canSelectAnotherToken,
|
||||
balance = quoteModel.fromTokenInfo.tokenWalletBalance,
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
receiveCardData = SwapCardData(
|
||||
type = TransactionCardType.ReceiveCard(),
|
||||
|
|
@ -155,6 +161,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
tokenCurrency = uiStateHolder.receiveCardData.tokenCurrency,
|
||||
canSelectAnotherToken = uiStateHolder.receiveCardData.canSelectAnotherToken,
|
||||
balance = quoteModel.toTokenInfo.tokenWalletBalance,
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
networkCurrency = quoteModel.networkCurrency,
|
||||
warnings = warnings,
|
||||
|
|
@ -192,6 +199,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
tokenCurrency = uiStateHolder.sendCardData.tokenCurrency,
|
||||
canSelectAnotherToken = uiStateHolder.sendCardData.canSelectAnotherToken,
|
||||
balance = emptyAmountState.fromTokenWalletBalance,
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
receiveCardData = SwapCardData(
|
||||
type = TransactionCardType.ReceiveCard(),
|
||||
|
|
@ -203,6 +211,7 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
tokenCurrency = uiStateHolder.receiveCardData.tokenCurrency,
|
||||
canSelectAnotherToken = uiStateHolder.receiveCardData.canSelectAnotherToken,
|
||||
balance = emptyAmountState.toTokenWalletBalance,
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
warnings = emptyList(),
|
||||
fee = FeeState.Empty,
|
||||
|
|
@ -254,6 +263,19 @@ internal class StateBuilder(val actions: UiActions) {
|
|||
)
|
||||
}
|
||||
|
||||
fun updateBalanceHiddenState(uiState: SwapStateHolder, isBalanceHidden: Boolean): SwapStateHolder {
|
||||
val patchedSendCardData = uiState.sendCardData.copy(
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
val patchedReceiveCardData = uiState.receiveCardData.copy(
|
||||
isBalanceHidden = isBalanceHidden,
|
||||
)
|
||||
return uiState.copy(
|
||||
sendCardData = patchedSendCardData,
|
||||
receiveCardData = patchedReceiveCardData,
|
||||
)
|
||||
}
|
||||
|
||||
fun updateApproveType(uiState: SwapStateHolder, approveType: ApproveType): SwapStateHolder {
|
||||
return if (uiState.permissionState is SwapPermissionState.ReadyForRequest) {
|
||||
uiState.copy(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import com.tangem.common.Strings.STARS
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
||||
import com.tangem.core.ui.components.states.Item
|
||||
|
|
@ -143,7 +144,11 @@ private fun MainInfo(state: SwapStateHolder) {
|
|||
val priceImpactWarning = state.warnings.filterIsInstance<SwapWarning.HighPriceImpact>().firstOrNull()
|
||||
TransactionCard(
|
||||
type = state.sendCardData.type,
|
||||
balance = state.sendCardData.balance,
|
||||
balance = if (state.sendCardData.isBalanceHidden) {
|
||||
STARS
|
||||
} else {
|
||||
state.sendCardData.balance
|
||||
},
|
||||
textFieldValue = state.sendCardData.amountTextFieldValue,
|
||||
amountEquivalent = state.sendCardData.amountEquivalent,
|
||||
tokenIconUrl = state.sendCardData.tokenIconUrl,
|
||||
|
|
@ -161,7 +166,7 @@ private fun MainInfo(state: SwapStateHolder) {
|
|||
val marginCard = TangemTheme.dimens.spacing16
|
||||
TransactionCard(
|
||||
type = state.receiveCardData.type,
|
||||
balance = state.receiveCardData.balance,
|
||||
balance = if (state.receiveCardData.isBalanceHidden) STARS else state.receiveCardData.balance,
|
||||
textFieldValue = state.receiveCardData.amountTextFieldValue,
|
||||
amountEquivalent = state.receiveCardData.amountEquivalent,
|
||||
tokenIconUrl = state.receiveCardData.tokenIconUrl,
|
||||
|
|
@ -371,6 +376,7 @@ private val sendCard = SwapCardData(
|
|||
canSelectAnotherToken = false,
|
||||
balance = "123",
|
||||
coinId = "",
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
private val receiveCard = SwapCardData(
|
||||
|
|
@ -383,6 +389,7 @@ private val receiveCard = SwapCardData(
|
|||
canSelectAnotherToken = true,
|
||||
balance = "33333",
|
||||
coinId = "",
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
|
||||
val stateSelectable = SelectableItemsState(
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ package com.tangem.feature.swap.viewmodels
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.*
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.utils.InputNumberFormatter
|
||||
import com.tangem.domain.balancehiding.IsBalanceHiddenUseCase
|
||||
import com.tangem.domain.balancehiding.ListenToFlipsUseCase
|
||||
import com.tangem.feature.swap.analytics.SwapEvents
|
||||
import com.tangem.feature.swap.domain.BlockchainInteractor
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
|
|
@ -27,8 +28,9 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
|||
import com.tangem.utils.coroutines.Debouncer
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import timber.log.Timber
|
||||
import java.text.DecimalFormat
|
||||
|
|
@ -37,15 +39,17 @@ import java.util.*
|
|||
import javax.inject.Inject
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@Suppress("LargeClass")
|
||||
@Suppress("LargeClass", "LongParameterList")
|
||||
@HiltViewModel
|
||||
internal class SwapViewModel @Inject constructor(
|
||||
private val swapInteractor: SwapInteractor,
|
||||
private val blockchainInteractor: BlockchainInteractor,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase,
|
||||
private val listenToFlipsUseCase: ListenToFlipsUseCase,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
) : ViewModel(), DefaultLifecycleObserver {
|
||||
|
||||
private val currency = Json.decodeFromString<Currency>(
|
||||
savedStateHandle[SwapFragment.CURRENCY_BUNDLE_KEY]
|
||||
|
|
@ -53,15 +57,20 @@ internal class SwapViewModel @Inject constructor(
|
|||
)
|
||||
private val derivationPath = savedStateHandle.get<String>(SwapFragment.DERIVATION_PATH)
|
||||
|
||||
private var isBalanceHidden = true
|
||||
|
||||
private val stateBuilder = StateBuilder(
|
||||
actions = createUiActions(),
|
||||
isBalanceHiddenProvider = Provider { isBalanceHidden },
|
||||
)
|
||||
|
||||
private val inputNumberFormatter =
|
||||
InputNumberFormatter(NumberFormat.getInstance(Locale.getDefault()) as DecimalFormat)
|
||||
private val amountDebouncer = Debouncer()
|
||||
private val singleTaskScheduler = SingleTaskScheduler<SwapState>()
|
||||
|
||||
private var dataState by mutableStateOf(SwapProcessDataState(networkId = currency.networkId))
|
||||
|
||||
var uiState: SwapStateHolder by mutableStateOf(
|
||||
stateBuilder.createInitialLoadingState(
|
||||
initialCurrency = currency,
|
||||
|
|
@ -82,6 +91,24 @@ internal class SwapViewModel @Inject constructor(
|
|||
initTokens(currency)
|
||||
}
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
isBalanceHiddenUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.onEach { hidden ->
|
||||
isBalanceHidden = hidden
|
||||
withContext(dispatchers.main) {
|
||||
uiState = stateBuilder.updateBalanceHiddenState(uiState, isBalanceHidden)
|
||||
}
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
viewModelScope.launch {
|
||||
listenToFlipsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
singleTaskScheduler.cancelTask()
|
||||
super.onCleared()
|
||||
|
|
|
|||
|
|
@ -53,12 +53,14 @@ dependencies {
|
|||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.legacy)
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.tokens)
|
||||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.tokendetails.api)
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ internal object TokenDetailsPreviewData {
|
|||
actionButtons = actionButtons,
|
||||
fiatBalance = "123,00$",
|
||||
cryptoBalance = "866,96 USDT",
|
||||
isBalanceHidden = false,
|
||||
)
|
||||
val balanceError = TokenDetailsBalanceBlockState.Error(actionButtons = actionButtons)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ internal sealed class TokenDetailsBalanceBlockState {
|
|||
override val actionButtons: ImmutableList<TokenDetailsActionButton>,
|
||||
val fiatBalance: String,
|
||||
val cryptoBalance: String,
|
||||
val isBalanceHidden: Boolean,
|
||||
) : TokenDetailsBalanceBlockState()
|
||||
|
||||
data class Error(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import java.math.BigDecimal
|
|||
internal class TokenDetailsLoadedBalanceConverter(
|
||||
private val currentStateProvider: Provider<TokenDetailsState>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val symbol: String,
|
||||
private val decimals: Int,
|
||||
) : Converter<Either<CurrencyStatusError, CryptoCurrencyStatus>, TokenDetailsState> {
|
||||
|
|
@ -57,6 +58,7 @@ internal class TokenDetailsLoadedBalanceConverter(
|
|||
actionButtons = currentState.actionButtons,
|
||||
fiatBalance = formatFiatAmount(status.value, appCurrencyProvider()),
|
||||
cryptoBalance = formatCryptoAmount(status),
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
)
|
||||
}
|
||||
is CryptoCurrencyStatus.Loading -> {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.tangem.domain.tokens.models.CryptoCurrency
|
|||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsBalanceBlockState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsDialogConfig
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
|
||||
|
|
@ -25,6 +26,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
internal class TokenDetailsStateFactory(
|
||||
private val currentStateProvider: Provider<TokenDetailsState>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val clickIntents: TokenDetailsClickIntents,
|
||||
symbol: String,
|
||||
decimals: Int,
|
||||
|
|
@ -38,6 +40,7 @@ internal class TokenDetailsStateFactory(
|
|||
TokenDetailsLoadedBalanceConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
symbol = symbol,
|
||||
decimals = decimals,
|
||||
)
|
||||
|
|
@ -162,4 +165,16 @@ internal class TokenDetailsStateFactory(
|
|||
bottomSheetConfig = state.bottomSheetConfig?.copy(isShow = false),
|
||||
)
|
||||
}
|
||||
|
||||
fun getStateWithUpdatedHidden(isBalanceHidden: Boolean): TokenDetailsState {
|
||||
val currentState = currentStateProvider()
|
||||
val possibleTokenBalanceBlockState = currentState.tokenBalanceBlockState as?
|
||||
TokenDetailsBalanceBlockState.Content
|
||||
|
||||
possibleTokenBalanceBlockState?.let {
|
||||
return currentState.copy(
|
||||
tokenBalanceBlockState = possibleTokenBalanceBlockState.copy(isBalanceHidden = isBalanceHidden),
|
||||
)
|
||||
} ?: return currentState
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@ private fun FiatBalance(state: TokenDetailsBalanceBlockState, modifier: Modifier
|
|||
)
|
||||
is TokenDetailsBalanceBlockState.Content -> Text(
|
||||
modifier = modifier,
|
||||
text = state.fiatBalance,
|
||||
text = if (state.isBalanceHidden) DOTS else state.fiatBalance,
|
||||
style = TangemTheme.typography.h2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
|
@ -96,7 +96,7 @@ private fun CryptoBalance(state: TokenDetailsBalanceBlockState, modifier: Modifi
|
|||
)
|
||||
is TokenDetailsBalanceBlockState.Content -> Text(
|
||||
modifier = modifier,
|
||||
text = state.cryptoBalance,
|
||||
text = if (state.isBalanceHidden) DOTS else state.cryptoBalance,
|
||||
style = TangemTheme.typography.caption,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
|
@ -135,4 +135,6 @@ private class TokenDetailsBalanceBlockStateProvider : CollectionPreviewParameter
|
|||
TokenDetailsPreviewData.balanceContent,
|
||||
TokenDetailsPreviewData.balanceError,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
const val DOTS = "***"
|
||||
|
|
@ -9,6 +9,8 @@ import arrow.core.getOrElse
|
|||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.IsBalanceHiddenUseCase
|
||||
import com.tangem.domain.balancehiding.ListenToFlipsUseCase
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
|
|
@ -49,6 +51,8 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase,
|
||||
private val listenToFlipsUseCase: ListenToFlipsUseCase,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
|
|
@ -65,19 +69,24 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private var wallet by Delegates.notNull<UserWallet>()
|
||||
|
||||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
private var isBalanceHidden = true
|
||||
|
||||
private val stateFactory = TokenDetailsStateFactory(
|
||||
currentStateProvider = Provider { uiState },
|
||||
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
|
||||
isBalanceHiddenProvider = Provider { isBalanceHidden },
|
||||
clickIntents = this,
|
||||
symbol = cryptoCurrency.symbol,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
)
|
||||
|
||||
var uiState: TokenDetailsState by mutableStateOf(stateFactory.getInitialState(cryptoCurrency))
|
||||
private set
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
getWallet()
|
||||
updateContent(selectedWallet = wallet)
|
||||
handleBalanceHiding(owner)
|
||||
}
|
||||
|
||||
private fun getWallet() {
|
||||
|
|
@ -93,6 +102,22 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
updateTxHistory()
|
||||
}
|
||||
|
||||
private fun handleBalanceHiding(owner: LifecycleOwner) {
|
||||
isBalanceHiddenUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.onEach { hidden ->
|
||||
isBalanceHidden = hidden
|
||||
uiState = stateFactory.getStateWithUpdatedHidden(isBalanceHidden = hidden)
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
viewModelScope.launch {
|
||||
listenToFlipsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateButtons(userWalletId: UserWalletId, currencyStatus: CryptoCurrencyStatus) {
|
||||
getCryptoCurrencyActionsUseCase(userWalletId = userWalletId, cryptoCurrencyStatus = currencyStatus)
|
||||
.distinctUntilChanged()
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ dependencies {
|
|||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.appCurrency)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.balanceHiding)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.wallet.api)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ internal object WalletPreviewData {
|
|||
imageResId = R.drawable.ill_businessman_3d,
|
||||
onRenameClick = { _, _ -> },
|
||||
onDeleteClick = {},
|
||||
balance = "8923,05 $",
|
||||
additionalInfo = TextReference.Str("3 cards • Seed phrase"),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -125,12 +127,13 @@ internal object WalletPreviewData {
|
|||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Visible(
|
||||
tokenOptions = TokenOptionsState(
|
||||
fiatAmount = "321 $",
|
||||
config = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
isBalanceHidden = false,
|
||||
),
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
|
|
@ -151,11 +154,14 @@ internal object WalletPreviewData {
|
|||
name = "Polygon",
|
||||
amount = "5,412 MATIC",
|
||||
hasPending = true,
|
||||
tokenOptions = TokenOptionsState.Hidden(
|
||||
tokenOptions = TokenOptionsState(
|
||||
config = PriceChangeConfig(
|
||||
valueInPercent = "2%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
fiatAmount = "321 $",
|
||||
isBalanceHidden = false,
|
||||
|
||||
),
|
||||
onItemClick = {},
|
||||
onItemLongClick = {},
|
||||
|
|
|
|||
|
|
@ -9,14 +9,13 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.common.Strings.STARS
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.Companion.DOTS
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
|
||||
|
||||
@Composable
|
||||
internal fun TokenCryptoInfoBlock(state: TokenItemState, modifier: Modifier = Modifier) {
|
||||
|
|
@ -40,7 +39,7 @@ private fun ContentBlock(state: TokenItemState.ContentState, modifier: Modifier
|
|||
|
||||
AmountText(
|
||||
amount = when (state) {
|
||||
is TokenItemState.Content -> if (state.tokenOptions is TokenOptionsState.Hidden) DOTS else state.amount
|
||||
is TokenItemState.Content -> if (state.tokenOptions.isBalanceHidden) STARS else state.amount
|
||||
is TokenItemState.Draggable -> state.info.resolveReference()
|
||||
is TokenItemState.Unreachable -> null
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.tangem.common.Strings.STARS
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.components.SpacerW4
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
|
|
@ -18,7 +19,6 @@ import com.tangem.core.ui.res.TangemTheme
|
|||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.Companion.DOTS
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
import org.burnoutcrew.reorderable.detectReorder
|
||||
|
|
@ -56,9 +56,10 @@ private fun ContentBlock(state: TokenOptionsState, modifier: Modifier = Modifier
|
|||
modifier = Modifier.align(Alignment.End),
|
||||
) {
|
||||
Text(
|
||||
text = when (it) {
|
||||
is TokenOptionsState.Visible -> it.fiatAmount
|
||||
is TokenOptionsState.Hidden -> DOTS
|
||||
text = if (it.isBalanceHidden) {
|
||||
STARS
|
||||
} else {
|
||||
it.fiatAmount
|
||||
},
|
||||
style = TangemTypography.body2,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
|
|
|
|||
|
|
@ -146,30 +146,9 @@ internal sealed interface TokenItemState {
|
|||
|
||||
/** Token options state */
|
||||
@Immutable
|
||||
sealed interface TokenOptionsState {
|
||||
|
||||
val config: PriceChangeConfig
|
||||
|
||||
/**
|
||||
* Visible token options state
|
||||
*
|
||||
* @property fiatAmount fiat amount of token
|
||||
* @property config value of price changing
|
||||
*/
|
||||
data class Visible(
|
||||
override val config: PriceChangeConfig,
|
||||
val fiatAmount: String,
|
||||
) : TokenOptionsState
|
||||
|
||||
/**
|
||||
* Hidden token options state
|
||||
*
|
||||
* @property config value of price changing
|
||||
*/
|
||||
data class Hidden(override val config: PriceChangeConfig) : TokenOptionsState
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DOTS = "•••"
|
||||
}
|
||||
data class TokenOptionsState(
|
||||
val config: PriceChangeConfig,
|
||||
val fiatAmount: String,
|
||||
val isBalanceHidden: Boolean,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.tangem.feature.wallet.presentation.organizetokens.utils.converter
|
||||
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
|
||||
internal class TokenItemHiddenStateConverter {
|
||||
|
||||
fun updateHiddenState(
|
||||
optionsState: TokenItemState.TokenOptionsState,
|
||||
isBalanceHidden: Boolean,
|
||||
): TokenItemState.TokenOptionsState {
|
||||
return when {
|
||||
!optionsState.isBalanceHidden && isBalanceHidden -> {
|
||||
optionsState.copy(isBalanceHidden = true)
|
||||
}
|
||||
optionsState.isBalanceHidden && !isBalanceHidden -> {
|
||||
optionsState.copy(isBalanceHidden = false)
|
||||
}
|
||||
else -> optionsState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -49,11 +49,13 @@ internal sealed interface WalletCardState {
|
|||
/**
|
||||
* Wallet card hidden content state
|
||||
*
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||
* @property id wallet id
|
||||
* @property title wallet name
|
||||
* @property imageResId wallet image resource id
|
||||
* @property onRenameClick lambda be invoked when Rename button is clicked
|
||||
* @property onDeleteClick lambda be invoked when Delete button is clicked
|
||||
* @property additionalInfo wallet additional info
|
||||
* @property balance wallet balance
|
||||
*/
|
||||
data class HiddenContent(
|
||||
override val id: UserWalletId,
|
||||
|
|
@ -61,6 +63,8 @@ internal sealed interface WalletCardState {
|
|||
override val imageResId: Int?,
|
||||
override val onRenameClick: (UserWalletId, String) -> Unit,
|
||||
override val onDeleteClick: (UserWalletId) -> Unit,
|
||||
val additionalInfo: TextReference,
|
||||
val balance: String,
|
||||
) : WalletCardState
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import com.tangem.utils.converter.Converter
|
|||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
internal class WalletLoadedTokensListConverter(
|
||||
private val currentStateProvider: Provider<WalletState>,
|
||||
private val tokenListErrorConverter: TokenListErrorConverter,
|
||||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
currentWalletProvider: Provider<UserWallet>,
|
||||
isBalanceHiddenProvider: Provider<Boolean>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) : Converter<Either<TokenListError, TokenList>, WalletState> {
|
||||
|
||||
|
|
@ -36,7 +38,7 @@ internal class WalletLoadedTokensListConverter(
|
|||
currentStateProvider = currentStateProvider,
|
||||
currentWalletProvider = currentWalletProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
isWalletContentHidden = false, // TODO: [REDACTED_JIRA]
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,16 @@ import com.tangem.domain.txhistory.models.TxHistoryItem
|
|||
import com.tangem.domain.txhistory.models.TxHistoryListError
|
||||
import com.tangem.domain.txhistory.models.TxHistoryStateError
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.ActionsBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNotification
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory.WalletLoadedTxHistoryConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.factory.txhistory.WalletLoadingTxHistoryConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.CurrencyStatusErrorConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.HiddenStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.TokenListErrorConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletsUpdateActionResolver
|
||||
|
|
@ -44,6 +49,7 @@ internal class WalletStateFactory(
|
|||
private val currentCardTypeResolverProvider: Provider<CardTypesResolver>,
|
||||
private val currentWalletProvider: Provider<UserWallet>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) {
|
||||
|
||||
|
|
@ -57,6 +63,8 @@ internal class WalletStateFactory(
|
|||
|
||||
private val walletDeleteStateConverter by lazy { WalletDeleteStateConverter(currentStateProvider) }
|
||||
|
||||
private val hiddenStateConverter by lazy { HiddenStateConverter(currentStateProvider) }
|
||||
|
||||
private val tokenListErrorConverter by lazy {
|
||||
TokenListErrorConverter(currentStateProvider)
|
||||
}
|
||||
|
|
@ -69,6 +77,7 @@ internal class WalletStateFactory(
|
|||
tokenListErrorConverter = tokenListErrorConverter,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
currentWalletProvider = currentWalletProvider,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
}
|
||||
|
|
@ -242,6 +251,10 @@ internal class WalletStateFactory(
|
|||
return currencyStatusErrorConverter.convert(error)
|
||||
}
|
||||
|
||||
fun getHiddenBalanceState(isBalanceHidden: Boolean): WalletState {
|
||||
return hiddenStateConverter.convert(isBalanceHidden)
|
||||
}
|
||||
|
||||
fun getStateAndTriggerEvent(
|
||||
state: WalletState,
|
||||
event: WalletEvent,
|
||||
|
|
|
|||
|
|
@ -241,15 +241,6 @@ private fun Title(state: WalletCardState, modifier: Modifier = Modifier) {
|
|||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4),
|
||||
) {
|
||||
TitleText(title = state.title)
|
||||
|
||||
AnimatedVisibility(visible = state is WalletCardState.HiddenContent, label = "Update the hidden icon") {
|
||||
Icon(
|
||||
modifier = Modifier.size(size = TangemTheme.dimens.size20),
|
||||
painter = painterResource(id = R.drawable.ic_eye_off_24),
|
||||
contentDescription = null,
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import java.math.BigDecimal
|
|||
|
||||
internal class CryptoCurrencyStatusToTokenItemConverter(
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isWalletContentHidden: Boolean,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : Converter<CryptoCurrencyStatus, TokenItemState> {
|
||||
|
||||
|
|
@ -42,14 +42,11 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
icon = iconStateConverter.convert(value = this),
|
||||
amount = getFormattedAmount(),
|
||||
hasPending = value.hasCurrentNetworkTransactions,
|
||||
tokenOptions = if (isWalletContentHidden) {
|
||||
TokenItemState.TokenOptionsState.Hidden(getPriceChangeConfig())
|
||||
} else {
|
||||
TokenItemState.TokenOptionsState.Visible(
|
||||
fiatAmount = getFormattedFiatAmount(),
|
||||
config = getPriceChangeConfig(),
|
||||
)
|
||||
},
|
||||
tokenOptions = TokenItemState.TokenOptionsState(
|
||||
fiatAmount = getFormattedFiatAmount(),
|
||||
config = getPriceChangeConfig(),
|
||||
isBalanceHidden = isBalanceHiddenProvider(),
|
||||
),
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ internal class FiatBalanceToWalletCardConverter(
|
|||
private val currentState: WalletCardState,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val currentWalletProvider: Provider<UserWallet>,
|
||||
private val isWalletContentHidden: Boolean,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
) : Converter<FiatBalance, WalletCardState> {
|
||||
|
||||
override fun convert(value: FiatBalance): WalletCardState {
|
||||
|
|
@ -39,17 +39,23 @@ internal class FiatBalanceToWalletCardConverter(
|
|||
}
|
||||
|
||||
private fun FiatBalance.Loaded.convertToWalletCardState(): WalletCardState {
|
||||
return if (isWalletContentHidden) {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
return if (isBalanceHiddenProvider()) {
|
||||
WalletCardState.HiddenContent(
|
||||
id = currentState.id,
|
||||
title = currentState.title,
|
||||
imageResId = currentState.imageResId,
|
||||
onRenameClick = currentState.onRenameClick,
|
||||
onDeleteClick = currentState.onDeleteClick,
|
||||
balance = formatFiatAmount(
|
||||
fiatAmount = this.amount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
),
|
||||
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = currentWalletProvider()),
|
||||
)
|
||||
} else {
|
||||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
WalletCardState.Content(
|
||||
id = currentState.id,
|
||||
title = currentState.title,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.common.Converter
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.utils.converter.TokenItemHiddenStateConverter
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMultiCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletSingleCurrencyState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletTokensListState
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
internal class HiddenStateConverter(
|
||||
private val currentStateProvider: Provider<WalletState>,
|
||||
) : Converter<Boolean, WalletState> {
|
||||
|
||||
private val walletHiddenBalanceStateConverter by lazy { WalletHiddenBalanceStateConverter() }
|
||||
|
||||
private val tokenItemHiddenStateConverter by lazy { TokenItemHiddenStateConverter() }
|
||||
|
||||
override fun convert(value: Boolean): WalletState {
|
||||
return when (val state = currentStateProvider() as? WalletState.ContentState) {
|
||||
is WalletMultiCurrencyState.Content -> {
|
||||
val updatedTokensList = (state.tokensListState as? WalletTokensListState.Content)?.let { content ->
|
||||
content.copy(
|
||||
items = content.items.map { tokenListItemState ->
|
||||
if (tokenListItemState is WalletTokensListState.TokensListItemState.Token) {
|
||||
if (tokenListItemState.state is TokenItemState.Content) {
|
||||
tokenListItemState.copy(
|
||||
state = tokenListItemState.state.copy(
|
||||
tokenOptions = tokenItemHiddenStateConverter.updateHiddenState(
|
||||
optionsState = tokenListItemState.state.tokenOptions,
|
||||
isBalanceHidden = value,
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
tokenListItemState
|
||||
}
|
||||
} else {
|
||||
tokenListItemState
|
||||
}
|
||||
}.toImmutableList(),
|
||||
)
|
||||
} ?: state.tokensListState
|
||||
|
||||
state.copy(
|
||||
walletsListConfig = state.walletsListConfig.copy(
|
||||
wallets = state.walletsListConfig.wallets.map {
|
||||
walletHiddenBalanceStateConverter.updateHiddenState(it, value)
|
||||
}.toImmutableList(),
|
||||
),
|
||||
tokensListState = updatedTokensList,
|
||||
)
|
||||
}
|
||||
|
||||
is WalletSingleCurrencyState.Content -> {
|
||||
state.copy(
|
||||
walletsListConfig = state.walletsListConfig.copy(
|
||||
wallets = state.walletsListConfig.wallets.map {
|
||||
walletHiddenBalanceStateConverter.updateHiddenState(it, value)
|
||||
}.toImmutableList(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
else -> currentStateProvider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,12 +17,12 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
|
||||
internal class TokenListToContentItemsConverter(
|
||||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
isWalletContentHidden: Boolean,
|
||||
isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val clickIntents: WalletClickIntents,
|
||||
) : Converter<TokenList, WalletTokensListState> {
|
||||
|
||||
private val tokenStatusConverter = CryptoCurrencyStatusToTokenItemConverter(
|
||||
isWalletContentHidden = isWalletContentHidden,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ internal class TokenListToWalletStateConverter(
|
|||
private val currentStateProvider: Provider<WalletState>,
|
||||
private val currentWalletProvider: Provider<UserWallet>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isWalletContentHidden: Boolean,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
clickIntents: WalletClickIntents,
|
||||
) : Converter<TokenList, WalletState> {
|
||||
|
||||
private val tokenListToContentConverter = TokenListToContentItemsConverter(
|
||||
isWalletContentHidden = isWalletContentHidden,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
clickIntents = clickIntents,
|
||||
)
|
||||
|
|
@ -48,9 +48,9 @@ internal class TokenListToWalletStateConverter(
|
|||
val selectedWalletCard = walletsListConfig.wallets[selectedWalletIndex]
|
||||
val converter = FiatBalanceToWalletCardConverter(
|
||||
currentState = selectedWalletCard,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
currentWalletProvider = currentWalletProvider,
|
||||
isWalletContentHidden = isWalletContentHidden,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
)
|
||||
|
||||
return walletsListConfig.copy(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.utils
|
||||
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletCardState
|
||||
|
||||
internal class WalletHiddenBalanceStateConverter {
|
||||
|
||||
fun updateHiddenState(walletCardState: WalletCardState, hiddenBalance: Boolean): WalletCardState {
|
||||
return when {
|
||||
walletCardState is WalletCardState.Content && hiddenBalance -> {
|
||||
contentToHidden(walletCardState)
|
||||
}
|
||||
walletCardState is WalletCardState.HiddenContent && !hiddenBalance -> {
|
||||
hiddenToContent(walletCardState)
|
||||
}
|
||||
else -> walletCardState
|
||||
}
|
||||
}
|
||||
|
||||
private fun contentToHidden(content: WalletCardState.Content): WalletCardState.HiddenContent {
|
||||
return WalletCardState.HiddenContent(
|
||||
id = content.id,
|
||||
title = content.title,
|
||||
additionalInfo = content.additionalInfo,
|
||||
imageResId = content.imageResId,
|
||||
onRenameClick = content.onRenameClick,
|
||||
onDeleteClick = content.onDeleteClick,
|
||||
balance = content.balance,
|
||||
)
|
||||
}
|
||||
|
||||
private fun hiddenToContent(hiddenContent: WalletCardState.HiddenContent): WalletCardState.Content {
|
||||
return WalletCardState.Content(
|
||||
id = hiddenContent.id,
|
||||
title = hiddenContent.title,
|
||||
additionalInfo = hiddenContent.additionalInfo,
|
||||
imageResId = hiddenContent.imageResId,
|
||||
onRenameClick = hiddenContent.onRenameClick,
|
||||
onDeleteClick = hiddenContent.onDeleteClick,
|
||||
balance = hiddenContent.balance,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,14 +14,14 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.IsBalanceHiddenUseCase
|
||||
import com.tangem.domain.balancehiding.ListenToFlipsUseCase
|
||||
import com.tangem.domain.card.*
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.settings.CanUseBiometryUseCase
|
||||
import com.tangem.domain.settings.IsUserAlreadyRateAppUseCase
|
||||
import com.tangem.domain.settings.ShouldShowSaveWalletScreenUseCase
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
|
@ -93,6 +93,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val shouldShowSaveWalletScreenUseCase: ShouldShowSaveWalletScreenUseCase,
|
||||
private val canUseBiometryUseCase: CanUseBiometryUseCase,
|
||||
private val shouldSaveUserWalletsUseCase: ShouldSaveUserWalletsUseCase,
|
||||
private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase,
|
||||
private val listenToFlipsUseCase: ListenToFlipsUseCase,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
|
|
@ -104,6 +106,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
var router: InnerWalletRouter by Delegates.notNull()
|
||||
|
||||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
private var isBalanceHidden = true
|
||||
|
||||
private val notificationsListFactory = WalletNotificationsListFactory(
|
||||
wasCardScannedCallback = getCardWasScannedUseCase::invoke,
|
||||
|
|
@ -123,6 +126,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
wallets[requireNotNull(uiState as? WalletState.ContentState).walletsListConfig.selectedWalletIndex]
|
||||
},
|
||||
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
|
||||
isBalanceHiddenProvider = Provider { isBalanceHidden },
|
||||
clickIntents = this,
|
||||
)
|
||||
|
||||
|
|
@ -161,6 +165,20 @@ internal class WalletViewModel @Inject constructor(
|
|||
.onEach(::updateWallets)
|
||||
.flowOn(dispatchers.io)
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
isBalanceHiddenUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.onEach { hidden ->
|
||||
isBalanceHidden = hidden
|
||||
uiState = stateFactory.getHiddenBalanceState(isBalanceHidden = hidden)
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
viewModelScope.launch {
|
||||
listenToFlipsUseCase()
|
||||
.flowWithLifecycle(owner.lifecycle)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWallets(sourceList: List<UserWallet>) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue