Updated on 2026-08-14
This commit is contained in:
parent
d73ab1aee6
commit
3c5c53ce92
17 changed files with 193 additions and 128 deletions
|
|
@ -2,52 +2,108 @@ package com.tangem.feature.swap.converters
|
|||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
|
||||
import com.tangem.core.ui.extensions.getTintForTokenIcon
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.extensions.tryGetBackgroundForTokenIcon
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.domain.models.domain.NetworkInfo
|
||||
import com.tangem.feature.swap.domain.models.ui.FoundTokensStateExpress
|
||||
import com.tangem.feature.swap.domain.models.ui.TokenWithBalanceExpress
|
||||
import com.tangem.feature.swap.models.Network
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.feature.swap.domain.models.domain.CryptoCurrencySwapInfo
|
||||
import com.tangem.feature.swap.domain.models.ui.CurrenciesGroup
|
||||
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
|
||||
import com.tangem.feature.swap.models.TokenBalanceData
|
||||
import com.tangem.feature.swap.models.TokenToSelectState
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
class TokensDataConverter(
|
||||
private val onSearchEntered: (String) -> Unit,
|
||||
private val onTokenSelected: (String) -> Unit,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
) {
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
) : Converter<CurrenciesGroup, SwapSelectTokenStateHolder> {
|
||||
|
||||
fun convertWithNetwork(value: FoundTokensStateExpress, network: NetworkInfo): SwapSelectTokenStateHolder {
|
||||
override fun convert(value: CurrenciesGroup): SwapSelectTokenStateHolder {
|
||||
val availableTitle = TokenToSelectState.Title(stringReference("My tokens")) // todo replace with resource
|
||||
val unavailableTitle = TokenToSelectState.Title(stringReference("My tokens")) // todo replace with resource
|
||||
return SwapSelectTokenStateHolder(
|
||||
availableTokens = value.tokensInWallet.map { tokenWithBalanceToTokenToSelect(it) }.toImmutableList(),
|
||||
unavailableTokens = value.loadedTokens.map { tokenWithBalanceToTokenToSelect(it) }.toImmutableList(),
|
||||
availableTokens = value.available.map { tokenWithBalanceToTokenToSelect(it, true) }
|
||||
.toMutableList()
|
||||
.apply {
|
||||
this.add(0, availableTitle)
|
||||
}
|
||||
.toImmutableList(),
|
||||
unavailableTokens = value.unavailable.map { tokenWithBalanceToTokenToSelect(it, false) }
|
||||
.toMutableList()
|
||||
.apply {
|
||||
this.add(0, unavailableTitle)
|
||||
}
|
||||
.toImmutableList(),
|
||||
onSearchEntered = onSearchEntered,
|
||||
onTokenSelected = onTokenSelected,
|
||||
network = Network(network.name, network.blockchainId),
|
||||
)
|
||||
}
|
||||
|
||||
private fun tokenWithBalanceToTokenToSelect(
|
||||
tokenWithBalance: TokenWithBalanceExpress,
|
||||
): TokenToSelectState.TokenToSelect {
|
||||
cryptoCurrencySwapInfo: CryptoCurrencySwapInfo,
|
||||
isAvailable: Boolean,
|
||||
): TokenToSelectState {
|
||||
val cryptoCurrencyStatus = cryptoCurrencySwapInfo.currencyStatus
|
||||
return TokenToSelectState.TokenToSelect(
|
||||
id = tokenWithBalance.token.id.value,
|
||||
name = tokenWithBalance.token.name,
|
||||
symbol = tokenWithBalance.token.symbol,
|
||||
isNative = tokenWithBalance.token is CryptoCurrency.Coin,
|
||||
// todo replace converting
|
||||
tokenIcon = TokenIconState.CoinIcon(
|
||||
url = "",
|
||||
fallbackResId = 0,
|
||||
isGrayscale = false,
|
||||
showCustomBadge = false,
|
||||
),
|
||||
id = cryptoCurrencyStatus.currency.id.value,
|
||||
name = cryptoCurrencyStatus.currency.name,
|
||||
symbol = cryptoCurrencyStatus.currency.symbol,
|
||||
available = isAvailable,
|
||||
tokenIcon = convertIcon(cryptoCurrencyStatus.currency, isAvailable),
|
||||
addedTokenBalanceData = TokenBalanceData(
|
||||
amount = tokenWithBalance.tokenBalanceData?.amount,
|
||||
amountEquivalent = tokenWithBalance.tokenBalanceData?.amountEquivalent,
|
||||
amount = formatCryptoAmount(cryptoCurrencyStatus),
|
||||
amountEquivalent = formatFiatAmount(cryptoCurrencyStatus, appCurrencyProvider.invoke()),
|
||||
isBalanceHidden = isBalanceHiddenProvider.invoke(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun convertIcon(currency: CryptoCurrency, isAvailable: Boolean): TokenIconState {
|
||||
return when (currency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
TokenIconState.CoinIcon(
|
||||
url = currency.iconUrl,
|
||||
fallbackResId = currency.networkIconResId,
|
||||
isGrayscale = !isAvailable,
|
||||
showCustomBadge = currency.isCustom,
|
||||
)
|
||||
}
|
||||
is CryptoCurrency.Token -> {
|
||||
val isGrayscale = currency.network.isTestnet
|
||||
val background = currency.tryGetBackgroundForTokenIcon(isGrayscale)
|
||||
val tint = getTintForTokenIcon(background)
|
||||
TokenIconState.TokenIcon(
|
||||
url = currency.iconUrl,
|
||||
isGrayscale = !isAvailable,
|
||||
showCustomBadge = currency.isCustom,
|
||||
networkBadgeIconResId = currency.networkIconResId,
|
||||
fallbackTint = tint,
|
||||
fallbackBackground = background,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatCryptoAmount(cryptoCurrencyStatus: CryptoCurrencyStatus): String {
|
||||
return BigDecimalFormatter.formatCryptoAmount(
|
||||
cryptoCurrencyStatus.value.amount,
|
||||
cryptoCurrencyStatus.currency.symbol,
|
||||
cryptoCurrencyStatus.currency.decimals,
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatFiatAmount(cryptoCurrencyStatus: CryptoCurrencyStatus, appCurrency: AppCurrency): String {
|
||||
return BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = cryptoCurrencyStatus.value.fiatAmount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,24 @@
|
|||
package com.tangem.feature.swap.models
|
||||
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class SwapSelectTokenStateHolder(
|
||||
val availableTokens: ImmutableList<TokenToSelectState>,
|
||||
val unavailableTokens: ImmutableList<TokenToSelectState>,
|
||||
val network: Network,
|
||||
val onSearchEntered: (String) -> Unit,
|
||||
val onTokenSelected: (String) -> Unit,
|
||||
)
|
||||
|
||||
data class Network(
|
||||
val name: String,
|
||||
val blockchainId: String,
|
||||
)
|
||||
|
||||
sealed class TokenToSelectState {
|
||||
|
||||
data class Title(val title: String) : TokenToSelectState()
|
||||
data class Title(val title: TextReference) : TokenToSelectState()
|
||||
|
||||
data class TokenToSelect(
|
||||
val id: String,
|
||||
val name: String,
|
||||
val symbol: String,
|
||||
val isNative: Boolean,
|
||||
val tokenIcon: TokenIconState,
|
||||
val available: Boolean = true,
|
||||
val addedTokenBalanceData: TokenBalanceData? = null,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.core.ui.components.states.SelectableItemsState
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.converters.TokensDataConverter
|
||||
import com.tangem.feature.swap.domain.models.DataError
|
||||
|
|
@ -24,12 +25,17 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
* State builder creates a specific states for SwapScreen
|
||||
*/
|
||||
@Suppress("LargeClass")
|
||||
internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider: Provider<Boolean>) {
|
||||
internal class StateBuilder(
|
||||
private val actions: UiActions,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
appCurrencyProvider: Provider<AppCurrency>,
|
||||
) {
|
||||
|
||||
private val tokensDataConverter = TokensDataConverter(
|
||||
onSearchEntered = actions.onSearchEntered,
|
||||
onTokenSelected = actions.onTokenSelected,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
)
|
||||
|
||||
fun createInitialLoadingState(initialCurrency: CryptoCurrency, networkInfo: NetworkInfo): SwapStateHolder {
|
||||
|
|
@ -247,15 +253,10 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider:
|
|||
)
|
||||
}
|
||||
|
||||
fun addTokensToState(
|
||||
uiState: SwapStateHolder,
|
||||
dataState: FoundTokensStateExpress,
|
||||
networkInfo: NetworkInfo,
|
||||
): SwapStateHolder {
|
||||
fun addTokensToState(uiState: SwapStateHolder, tokensDataState: CurrenciesGroup): SwapStateHolder {
|
||||
return uiState.copy(
|
||||
selectTokenState = tokensDataConverter.convertWithNetwork(
|
||||
value = dataState,
|
||||
network = networkInfo,
|
||||
selectTokenState = tokensDataConverter.convert(
|
||||
value = tokensDataState,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import androidx.compose.material.Text
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.common.Strings
|
||||
|
|
@ -20,7 +19,8 @@ import com.tangem.core.ui.components.appbar.ExpandableSearchView
|
|||
import com.tangem.core.ui.components.currency.tokenicon.TokenIcon
|
||||
import com.tangem.core.ui.components.currency.tokenicon.TokenIconState
|
||||
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
||||
import com.tangem.core.ui.extensions.getActiveIconRes
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.swap.models.*
|
||||
import com.tangem.feature.swap.presentation.R
|
||||
|
|
@ -43,8 +43,7 @@ fun SwapSelectTokenScreen(state: SwapSelectTokenStateHolder, onBack: () -> Unit)
|
|||
placeholderSearchText = stringResource(id = R.string.common_search_tokens),
|
||||
onSearchChange = state.onSearchEntered,
|
||||
onSearchDisplayClose = { state.onSearchEntered("") },
|
||||
subtitle = state.network.name,
|
||||
icon = painterResource(id = getActiveIconRes(state.network.blockchainId)),
|
||||
subtitle = "", // todo add title
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -112,7 +111,7 @@ private fun TitleHeader(item: TokenToSelectState.Title, modifier: Modifier = Mod
|
|||
.background(TangemTheme.colors.background.action),
|
||||
) {
|
||||
Text(
|
||||
text = item.title,
|
||||
text = item.title.resolveReference().uppercase(),
|
||||
style = TangemTheme.typography.overline,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
|
|
@ -134,7 +133,10 @@ private fun TokenItem(
|
|||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.height(TangemTheme.dimens.size72)
|
||||
.clickable(onClick = onTokenClick)
|
||||
.clickable(
|
||||
enabled = token.available,
|
||||
onClick = onTokenClick,
|
||||
)
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens.spacing14,
|
||||
horizontal = TangemTheme.dimens.spacing16,
|
||||
|
|
@ -170,13 +172,7 @@ private fun TokenItem(
|
|||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
if (!token.available) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.swapping_token_not_available),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
} else if (token.addedTokenBalanceData != null) {
|
||||
if (token.addedTokenBalanceData != null) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.End,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
|
|
@ -191,7 +187,11 @@ private fun TokenItem(
|
|||
token.addedTokenBalanceData.amountEquivalent.orEmpty()
|
||||
},
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
color = if (token.available) {
|
||||
TangemTheme.colors.text.primary1
|
||||
} else {
|
||||
TangemTheme.colors.text.tertiary
|
||||
},
|
||||
)
|
||||
SpacerW2()
|
||||
Text(
|
||||
|
|
@ -220,7 +220,6 @@ private val token = TokenToSelectState.TokenToSelect(
|
|||
id = "",
|
||||
name = "USDC",
|
||||
symbol = "USDC",
|
||||
isNative = false,
|
||||
addedTokenBalanceData = TokenBalanceData(
|
||||
amount = "15 000 $",
|
||||
amountEquivalent = "15 000 " +
|
||||
|
|
@ -230,7 +229,7 @@ private val token = TokenToSelectState.TokenToSelect(
|
|||
)
|
||||
|
||||
private val title = TokenToSelectState.Title(
|
||||
title = "MY TOKENS",
|
||||
title = stringReference("MY TOKENS"),
|
||||
)
|
||||
|
||||
@Preview
|
||||
|
|
@ -243,7 +242,6 @@ private fun TokenScreenPreview() {
|
|||
unavailableTokens = listOf(title, token, token, token).toImmutableList(),
|
||||
onSearchEntered = {},
|
||||
onTokenSelected = {},
|
||||
network = Network("Ethereum", "ETH"),
|
||||
),
|
||||
onBack = {},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.tangem.domain.tokens.model.CryptoCurrency
|
|||
import com.tangem.feature.swap.domain.models.domain.Currency
|
||||
import com.tangem.feature.swap.domain.models.ui.RequestApproveStateData
|
||||
import com.tangem.feature.swap.domain.models.ui.SwapStateData
|
||||
import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress
|
||||
import com.tangem.feature.swap.domain.models.ui.TxFee
|
||||
|
||||
data class SwapProcessDataState(
|
||||
|
|
@ -20,4 +21,5 @@ data class SwapProcessDataState(
|
|||
val approveDataModel: RequestApproveStateData? = null,
|
||||
val swapDataModel: SwapStateData? = null,
|
||||
val selectedFee: TxFee? = null,
|
||||
val tokensDataState: TokensDataStateExpress? = null,
|
||||
)
|
||||
|
|
@ -4,9 +4,12 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.*
|
||||
import arrow.core.getOrElse
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.ui.utils.InputNumberFormatter
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.swap.analytics.SwapEvents
|
||||
|
|
@ -27,11 +30,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.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.json.Json
|
||||
import timber.log.Timber
|
||||
import java.text.DecimalFormat
|
||||
import java.text.NumberFormat
|
||||
|
|
@ -47,6 +48,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver {
|
||||
|
||||
|
|
@ -55,9 +57,12 @@ internal class SwapViewModel @Inject constructor(
|
|||
|
||||
private var isBalanceHidden = true
|
||||
|
||||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
|
||||
private val stateBuilder = StateBuilder(
|
||||
actions = createUiActions(),
|
||||
isBalanceHiddenProvider = Provider { isBalanceHidden },
|
||||
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
|
||||
)
|
||||
|
||||
private val inputNumberFormatter =
|
||||
|
|
@ -87,7 +92,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
derivationPath = initialCryptoCurrency.network.derivationPath.value,
|
||||
network = initialCryptoCurrency.network,
|
||||
)
|
||||
initTokens(initialCryptoCurrency)
|
||||
initTokens()
|
||||
}
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
|
|
@ -126,7 +131,7 @@ internal class SwapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun initTokens(currency: CryptoCurrency) {
|
||||
private fun initTokens() {
|
||||
// new flow
|
||||
viewModelScope.launch(dispatchers.main) {
|
||||
runCatching(dispatchers.io) {
|
||||
|
|
@ -134,10 +139,11 @@ internal class SwapViewModel @Inject constructor(
|
|||
}.onSuccess { state ->
|
||||
dataState = dataState.copy(
|
||||
fromCryptoCurrency = initialCryptoCurrency,
|
||||
toCryptoCurrency = state.toGroup.available.first().currencyStatus.currency
|
||||
toCryptoCurrency = state.toGroup.available.first().currencyStatus.currency,
|
||||
tokensDataState = state,
|
||||
)
|
||||
|
||||
// updateTokensState(dataState = state.foundTokensState)
|
||||
updateTokensState(state)
|
||||
startLoadingQuotes(
|
||||
fromToken = initialCryptoCurrency,
|
||||
toToken = state.toGroup.available.first().currencyStatus.currency,
|
||||
|
|
@ -171,11 +177,11 @@ internal class SwapViewModel @Inject constructor(
|
|||
// }
|
||||
}
|
||||
|
||||
private fun updateTokensState(dataState: FoundTokensStateExpress) {
|
||||
private fun updateTokensState(dataState: TokensDataStateExpress) {
|
||||
val tokensDataState = if (!isOrderReversed) dataState.toGroup else dataState.fromGroup
|
||||
uiState = stateBuilder.addTokensToState(
|
||||
uiState = uiState,
|
||||
dataState = dataState,
|
||||
networkInfo = blockchainInteractor.getBlockchainInfo(initialCryptoCurrency.network.backendId),
|
||||
tokensDataState = tokensDataState,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -369,28 +375,31 @@ internal class SwapViewModel @Inject constructor(
|
|||
swapInteractor.searchTokens(dataState.networkId, searchQuery)
|
||||
}
|
||||
.onSuccess {
|
||||
updateTokensState(it)
|
||||
// updateTokensState(it)
|
||||
}
|
||||
.onFailure { }
|
||||
}
|
||||
}
|
||||
|
||||
private fun onTokenSelect(id: String) {
|
||||
val foundToken = swapInteractor.findTokenById(id)
|
||||
val tokens = dataState.tokensDataState ?: return
|
||||
|
||||
val foundToken = tokens.toGroup.available.firstOrNull {
|
||||
it.currencyStatus.currency.id.value == id
|
||||
}
|
||||
analyticsEventHandler.send(
|
||||
event = SwapEvents.SearchTokenClicked(currencySymbol = foundToken?.symbol),
|
||||
event = SwapEvents.SearchTokenClicked(currencySymbol = foundToken?.currencyStatus?.currency?.symbol),
|
||||
)
|
||||
|
||||
if (foundToken != null) {
|
||||
val fromToken: CryptoCurrency
|
||||
val toToken: CryptoCurrency
|
||||
if (isOrderReversed) {
|
||||
fromToken = foundToken
|
||||
fromToken = foundToken.currencyStatus.currency
|
||||
toToken = initialCryptoCurrency
|
||||
} else {
|
||||
fromToken = initialCryptoCurrency
|
||||
toToken = foundToken
|
||||
toToken = foundToken.currencyStatus.currency
|
||||
}
|
||||
dataState = dataState.copy(
|
||||
fromCryptoCurrency = fromToken,
|
||||
|
|
@ -532,6 +541,18 @@ internal class SwapViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun createSelectedAppCurrencyFlow(): StateFlow<AppCurrency> {
|
||||
return getSelectedAppCurrencyUseCase()
|
||||
.map { maybeAppCurrency ->
|
||||
maybeAppCurrency.getOrElse { AppCurrency.Default }
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = AppCurrency.Default,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val loggingTag = "SwapViewModel"
|
||||
private const val INITIAL_AMOUNT = ""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue