Skip to content

Commit

Permalink
Simplify MarketViewModel
Browse files Browse the repository at this point in the history
  • Loading branch information
abdrasulov committed Oct 28, 2024
1 parent fd80dee commit c2344b6
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import io.horizontalsystems.bankwallet.core.App
import io.horizontalsystems.bankwallet.entities.Currency
import io.horizontalsystems.bankwallet.entities.CurrencyValue
import io.horizontalsystems.bankwallet.modules.market.filters.TimePeriod
import io.horizontalsystems.bankwallet.modules.metricchart.MetricsType
import io.horizontalsystems.bankwallet.modules.settings.appearance.PriceChangeInterval
import io.horizontalsystems.bankwallet.ui.compose.TranslatableString
import io.horizontalsystems.bankwallet.ui.compose.WithTranslatableTitle
import io.horizontalsystems.marketkit.models.FullCoin
import io.horizontalsystems.marketkit.models.MarketGlobal
import io.horizontalsystems.marketkit.models.MarketInfo
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
Expand All @@ -42,15 +42,8 @@ object MarketModule {

data class UiState(
val selectedTab: Tab,
val marketOverviewItems: List<MarketOverviewViewItem>
)

data class MarketOverviewViewItem(
val title: String,
val value: String?,
val change: String?,
val changePositive: Boolean?,
val metricsType: MetricsType,
val marketGlobal: MarketGlobal?,
val currency: Currency
)

enum class Tab(@StringRes val titleResId: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
Expand All @@ -28,6 +29,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.App
import io.horizontalsystems.bankwallet.core.slideFromBottom
import io.horizontalsystems.bankwallet.core.slideFromRight
import io.horizontalsystems.bankwallet.core.stats.StatEvent
Expand All @@ -36,6 +38,7 @@ import io.horizontalsystems.bankwallet.core.stats.StatSection
import io.horizontalsystems.bankwallet.core.stats.stat
import io.horizontalsystems.bankwallet.core.stats.statPage
import io.horizontalsystems.bankwallet.core.stats.statTab
import io.horizontalsystems.bankwallet.entities.Currency
import io.horizontalsystems.bankwallet.modules.coin.CoinFragment
import io.horizontalsystems.bankwallet.modules.market.MarketModule.Tab
import io.horizontalsystems.bankwallet.modules.market.favorites.MarketFavoritesScreen
Expand All @@ -56,6 +59,8 @@ import io.horizontalsystems.bankwallet.ui.compose.components.caption_grey
import io.horizontalsystems.bankwallet.ui.compose.components.caption_lucian
import io.horizontalsystems.bankwallet.ui.compose.components.caption_remus
import io.horizontalsystems.bankwallet.ui.compose.components.micro_grey
import io.horizontalsystems.marketkit.models.MarketGlobal
import java.math.BigDecimal

@Composable
fun MarketScreen(navController: NavController) {
Expand Down Expand Up @@ -103,8 +108,8 @@ fun MarketScreen(navController: NavController) {
.padding(it)
.background(ComposeAppTheme.colors.tyler)
) {
Crossfade(uiState.marketOverviewItems) {
MetricsBoard(navController, it)
Crossfade(uiState.marketGlobal, label = "") {
MetricsBoard(navController, it, uiState.currency)
}
Divider(
color = ComposeAppTheme.colors.steel10,
Expand Down Expand Up @@ -168,11 +173,22 @@ fun TabsSection(
}
}

private fun formatFiatShortened(value: BigDecimal, symbol: String): String {
return App.numberFormatter.formatFiatShort(value, symbol, 2)
}

private fun getDiff(it: BigDecimal): String {
val sign = if (it >= BigDecimal.ZERO) "+" else "-"
return App.numberFormatter.format(it.abs(), 0, 2, sign, "%")
}


@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MetricsBoard(
navController: NavController,
marketOverviewItems: List<MarketModule.MarketOverviewViewItem>
marketGlobal: MarketGlobal?,
currency: Currency
) {
Row(
modifier = Modifier
Expand All @@ -182,55 +198,110 @@ fun MetricsBoard(
.clip(RoundedCornerShape(12.dp))
.background(ComposeAppTheme.colors.lawrence)
) {
marketOverviewItems.forEachIndexed { index, item ->
if (index != 0) {
Box(
Modifier
.fillMaxHeight()
.width(1.dp)
.background(color = ComposeAppTheme.colors.steel10)
)
MarketTotalCard(
title = stringResource(R.string.MarketGlobalMetrics_TotalMarketCap),
value = marketGlobal?.marketCap,
change = marketGlobal?.marketCapChange,
currency = currency,
onClick = {
openMetricsPage(MetricsType.TotalMarketCap, navController)
}
Column(
modifier = Modifier
.clickable {
openMetricsPage(item.metricsType, navController)
}
.padding(12.dp)
.weight(1f)
) {
micro_grey(
text = item.title,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
VSpacer(4.dp)
caption_bran(
text = item.value ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
VSpacer(4.dp)
if (item.changePositive == null) {
caption_grey(
text = item.change ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
} else if (item.changePositive) {
caption_remus(
text = item.change ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
} else {
caption_lucian(
text = item.change ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
}
)

VDivider()

MarketTotalCard(
title = stringResource(R.string.MarketGlobalMetrics_Volume),
value = marketGlobal?.volume,
change = marketGlobal?.volumeChange,
currency = currency,
onClick = {
openMetricsPage(MetricsType.Volume24h, navController)
}
)

VDivider()

MarketTotalCard(
title = stringResource(R.string.MarketGlobalMetrics_TvlInDefi),
value = marketGlobal?.tvl,
change = marketGlobal?.tvlChange,
currency = currency,
onClick = {
openMetricsPage(MetricsType.TvlInDefi, navController)
}
)

VDivider()

MarketTotalCard(
title = stringResource(R.string.MarketGlobalMetrics_EtfInflow),
value = marketGlobal?.etfTotalInflow,
change = marketGlobal?.etfDailyInflow,
currency = currency,
onClick = {
openMetricsPage(MetricsType.Etf, navController)
}
)
}
}

@Composable
private fun VDivider() {
Box(
Modifier
.fillMaxHeight()
.width(1.dp)
.background(color = ComposeAppTheme.colors.steel10)
)
}

@Composable
private fun RowScope.MarketTotalCard(
title: String,
value: BigDecimal?,
change: BigDecimal?,
currency: Currency,
onClick: () -> Unit,
) {
val changeStr = change?.let { getDiff(it) }
val changePositive = change?.let { it > BigDecimal.ZERO }
Column(
modifier = Modifier
.weight(1f)
.padding(12.dp)
.clickable(onClick = onClick)
) {
micro_grey(
text = title,
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
VSpacer(4.dp)
caption_bran(
text = value?.let { formatFiatShortened(it, currency.symbol) } ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
VSpacer(4.dp)
if (changePositive == null) {
caption_grey(
text = changeStr ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
} else if (changePositive) {
caption_remus(
text = changeStr ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
} else {
caption_lucian(
text = changeStr ?: "---",
overflow = TextOverflow.Ellipsis,
maxLines = 1
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,17 @@ package io.horizontalsystems.bankwallet.modules.market

import android.util.Log
import androidx.lifecycle.viewModelScope
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.App
import io.horizontalsystems.bankwallet.core.ILocalStorage
import io.horizontalsystems.bankwallet.core.IMarketStorage
import io.horizontalsystems.bankwallet.core.ViewModelUiState
import io.horizontalsystems.bankwallet.core.managers.CurrencyManager
import io.horizontalsystems.bankwallet.core.managers.MarketKitWrapper
import io.horizontalsystems.bankwallet.core.providers.Translator
import io.horizontalsystems.bankwallet.entities.Currency
import io.horizontalsystems.bankwallet.entities.LaunchPage
import io.horizontalsystems.bankwallet.modules.market.MarketModule.MarketOverviewViewItem
import io.horizontalsystems.bankwallet.modules.market.MarketModule.Tab
import io.horizontalsystems.bankwallet.modules.metricchart.MetricsType
import io.horizontalsystems.marketkit.models.MarketGlobal
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.rx2.await
import java.math.BigDecimal

class MarketViewModel(
private val marketStorage: IMarketStorage,
Expand All @@ -30,101 +22,41 @@ class MarketViewModel(
) : ViewModelUiState<MarketModule.UiState>() {

val tabs = Tab.entries.toTypedArray()
private var marketOverviewJob: Job? = null
private var marketOverviewItems = getMarketMetrics(null, currencyManager.baseCurrency)
private var currency = currencyManager.baseCurrency

private var marketGlobal: MarketGlobal? = null
private var selectedTab: Tab = getInitialTab(localStorage.launchPage)

init {
updateMarketOverview()

viewModelScope.launch {
currencyManager.baseCurrencyUpdatedFlow.collect {
updateMarketOverview()
currency = currencyManager.baseCurrency
emitState()
}
}
}

override fun createState(): MarketModule.UiState {
return MarketModule.UiState(
selectedTab,
marketOverviewItems
)
}

private fun updateMarketOverview() {
marketOverviewJob?.cancel()
marketOverviewJob = viewModelScope.launch(Dispatchers.IO) {
viewModelScope.launch(Dispatchers.IO) {
try {
val marketGlobal =
marketKit.marketGlobalSingle(currencyManager.baseCurrency.code).await()
marketOverviewItems = getMarketMetrics(marketGlobal, currencyManager.baseCurrency)
marketGlobal = marketKit.marketGlobalSingle(currency.code).await()
emitState()
} catch (e: Throwable) {
Log.e("TAG", "updateMarketOverview: ", e)
}
}
}

override fun createState() = MarketModule.UiState(
selectedTab = selectedTab,
marketGlobal = marketGlobal,
currency = currency
)

fun onSelect(tab: Tab) {
selectedTab = tab
marketStorage.currentMarketTab = tab
emitState()
}

private fun getMarketMetrics(
globalMarket: MarketGlobal?,
baseCurrency: Currency,
): List<MarketOverviewViewItem> {
return listOf(
MarketOverviewViewItem(
Translator.getString(R.string.MarketGlobalMetrics_TotalMarketCap),
globalMarket?.marketCap?.let { formatFiatShortened(it, baseCurrency.symbol) },
globalMarket?.marketCapChange?.let { getDiff(it) },
globalMarket?.marketCapChange?.let { it > BigDecimal.ZERO },
MetricsType.TotalMarketCap
),
MarketOverviewViewItem(
Translator.getString(R.string.MarketGlobalMetrics_Volume),
globalMarket?.volume?.let { formatFiatShortened(it, baseCurrency.symbol) },
globalMarket?.volumeChange?.let { getDiff(it) },
globalMarket?.volumeChange?.let { it > BigDecimal.ZERO },
MetricsType.Volume24h
),
MarketOverviewViewItem(
Translator.getString(R.string.MarketGlobalMetrics_TvlInDefi),
globalMarket?.tvl?.let { formatFiatShortened(it, baseCurrency.symbol) },
globalMarket?.tvlChange?.let { getDiff(it) },
globalMarket?.tvlChange?.let { it > BigDecimal.ZERO },
MetricsType.TvlInDefi
),
MarketOverviewViewItem(
Translator.getString(R.string.MarketGlobalMetrics_EtfInflow),
globalMarket?.etfTotalInflow?.let { formatFiatShortened(it, baseCurrency.symbol) },
globalMarket?.etfDailyInflow?.let {
val sign = if (it >= BigDecimal.ZERO) "+" else "-"
"$sign${formatFiatShortened(it.abs(), baseCurrency.symbol)}"
},
globalMarket?.etfDailyInflow?.let { it > BigDecimal.ZERO },
MetricsType.Etf
)
)
}

private fun getDiff(it: BigDecimal): String {
val sign = if (it >= BigDecimal.ZERO) "+" else "-"
return App.numberFormatter.format(it.abs(), 0, 2, sign, "%")
}

private fun formatFiatShortened(value: BigDecimal, symbol: String): String {
return App.numberFormatter.formatFiatShort(value, symbol, 2)
}

private fun diff(sourceValue: BigDecimal, targetValue: BigDecimal): BigDecimal =
if (sourceValue.compareTo(BigDecimal.ZERO) != 0)
((targetValue - sourceValue) * BigDecimal(100)) / sourceValue
else BigDecimal.ZERO


private fun getInitialTab(launchPage: LaunchPage?) = when (launchPage) {
LaunchPage.Watchlist -> Tab.Watchlist
else -> marketStorage.currentMarketTab ?: Tab.Coins
Expand Down

0 comments on commit c2344b6

Please sign in to comment.