Skip to content

Commit

Permalink
Update sorting in Platform page
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelekol committed Jun 4, 2024
1 parent 8255368 commit a290d9e
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.compose.animation.Crossfade
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.height
Expand Down Expand Up @@ -32,24 +31,23 @@ import io.horizontalsystems.bankwallet.core.slideFromRight
import io.horizontalsystems.bankwallet.core.stats.StatEvent
import io.horizontalsystems.bankwallet.core.stats.StatPage
import io.horizontalsystems.bankwallet.core.stats.stat
import io.horizontalsystems.bankwallet.core.stats.statField
import io.horizontalsystems.bankwallet.core.stats.statSortType
import io.horizontalsystems.bankwallet.entities.ViewState
import io.horizontalsystems.bankwallet.modules.chart.ChartViewModel
import io.horizontalsystems.bankwallet.modules.coin.CoinFragment
import io.horizontalsystems.bankwallet.modules.coin.overview.ui.Chart
import io.horizontalsystems.bankwallet.modules.coin.overview.ui.Loading
import io.horizontalsystems.bankwallet.modules.market.ImageSource
import io.horizontalsystems.bankwallet.modules.market.topcoins.SelectorDialogState
import io.horizontalsystems.bankwallet.modules.market.topcoins.OptionController
import io.horizontalsystems.bankwallet.modules.market.topplatforms.Platform
import io.horizontalsystems.bankwallet.ui.compose.ComposeAppTheme
import io.horizontalsystems.bankwallet.ui.compose.HSSwipeRefresh
import io.horizontalsystems.bankwallet.ui.compose.Select
import io.horizontalsystems.bankwallet.ui.compose.components.AlertGroup
import io.horizontalsystems.bankwallet.ui.compose.components.ButtonSecondaryToggle
import io.horizontalsystems.bankwallet.ui.compose.components.CoinList
import io.horizontalsystems.bankwallet.ui.compose.components.HSpacer
import io.horizontalsystems.bankwallet.ui.compose.components.HeaderSorting
import io.horizontalsystems.bankwallet.ui.compose.components.ListErrorView
import io.horizontalsystems.bankwallet.ui.compose.components.SortMenu
import io.horizontalsystems.bankwallet.ui.compose.components.TopCloseButton
import io.horizontalsystems.bankwallet.ui.compose.components.subhead2_grey
import io.horizontalsystems.bankwallet.ui.compose.components.title3_leah
Expand Down Expand Up @@ -91,21 +89,23 @@ private fun PlatformScreen(
chartViewModel: ChartViewModel = viewModel(factory = factory),
) {

val uiState = viewModel.uiState
var scrollToTopAfterUpdate by rememberSaveable { mutableStateOf(false) }
var openSortingSelector by rememberSaveable { mutableStateOf(false) }

Surface(color = ComposeAppTheme.colors.tyler) {
Column {
TopCloseButton(onCloseButtonClick)

HSSwipeRefresh(
refreshing = viewModel.isRefreshing,
refreshing = uiState.isRefreshing,
onRefresh = {
viewModel.refresh()

stat(page = StatPage.TopPlatform, event = StatEvent.Refresh)
}
) {
Crossfade(viewModel.viewState) { state ->
Crossfade(uiState.viewState, label = "") { state ->
when (state) {
ViewState.Loading -> {
Loading()
Expand All @@ -119,19 +119,25 @@ private fun PlatformScreen(
}

ViewState.Success -> {
viewModel.viewItems.let { viewItems ->
uiState.viewItems.let { viewItems ->
CoinList(
items = viewItems,
scrollToTop = scrollToTopAfterUpdate,
onAddFavorite = { uid ->
viewModel.onAddFavorite(uid)

stat(page = StatPage.TopPlatform, event = StatEvent.AddToWatchlist(uid))
stat(
page = StatPage.TopPlatform,
event = StatEvent.AddToWatchlist(uid)
)
},
onRemoveFavorite = { uid ->
viewModel.onRemoveFavorite(uid)

stat(page = StatPage.TopPlatform, event = StatEvent.RemoveFromWatchlist(uid))
stat(
page = StatPage.TopPlatform,
event = StatEvent.RemoveFromWatchlist(uid)
)
},
onCoinClick = onCoinClick,
preItems = {
Expand All @@ -145,27 +151,13 @@ private fun PlatformScreen(
}
stickyHeader {
HeaderSorting(borderTop = true, borderBottom = true) {
Box(modifier = Modifier.weight(1f)) {
SortMenu(
viewModel.menu.sortingFieldSelect.selected.titleResId,
viewModel::showSelectorMenu
)
}
Box(
modifier = Modifier.padding(
start = 8.dp,
end = 16.dp
)
) {
ButtonSecondaryToggle(
select = viewModel.menu.marketFieldSelect,
onSelect = {
viewModel.onSelectMarketField(it)

stat(page = StatPage.TopPlatform, event = StatEvent.SwitchField(it.statField))
}
)
}
HSpacer(width = 16.dp)
OptionController(
uiState.sortingField.titleResId,
onOptionClick = {
openSortingSelector = true
}
)
}
}
}
Expand All @@ -179,24 +171,22 @@ private fun PlatformScreen(
}
}
}
//Dialog
when (val option = viewModel.selectorDialogState) {
is SelectorDialogState.Opened -> {
AlertGroup(
R.string.Market_Sort_PopupTitle,
option.select,
{ selected ->
viewModel.onSelectSortingField(selected)
scrollToTopAfterUpdate = true

stat(page = StatPage.TopPlatform, event = StatEvent.SwitchSortType(selected.statSortType))
},
{ viewModel.onSelectorDialogDismiss() }
}
if (openSortingSelector) {
AlertGroup(
R.string.Market_Sort_PopupTitle,
Select(uiState.sortingField, viewModel.sortingFields),
{ selected ->
scrollToTopAfterUpdate = true
viewModel.onSelectSortingField(selected)
openSortingSelector = false
stat(
page = StatPage.TopPlatforms,
event = StatEvent.SwitchSortType(selected.statSortType)
)
}

else -> {}
}
},
{ openSortingSelector = false }
)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,43 @@
package io.horizontalsystems.bankwallet.modules.market.platform

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.horizontalsystems.bankwallet.R
import io.horizontalsystems.bankwallet.core.App
import io.horizontalsystems.bankwallet.core.ViewModelUiState
import io.horizontalsystems.bankwallet.core.iconUrl
import io.horizontalsystems.bankwallet.core.managers.MarketFavoritesManager
import io.horizontalsystems.bankwallet.core.providers.Translator
import io.horizontalsystems.bankwallet.entities.ViewState
import io.horizontalsystems.bankwallet.modules.market.ImageSource
import io.horizontalsystems.bankwallet.modules.market.MarketField
import io.horizontalsystems.bankwallet.modules.market.MarketDataValue
import io.horizontalsystems.bankwallet.modules.market.MarketItem
import io.horizontalsystems.bankwallet.modules.market.MarketModule
import io.horizontalsystems.bankwallet.modules.market.MarketViewItem
import io.horizontalsystems.bankwallet.modules.market.SortingField
import io.horizontalsystems.bankwallet.modules.market.topcoins.SelectorDialogState
import io.horizontalsystems.bankwallet.modules.market.sort
import io.horizontalsystems.bankwallet.modules.market.topplatforms.Platform
import io.horizontalsystems.bankwallet.ui.compose.Select
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MarketPlatformViewModel(
platform: Platform,
private val repository: MarketPlatformCoinsRepository,
private val favoritesManager: MarketFavoritesManager,
) : ViewModel() {
) : ViewModelUiState<MarketPlatformUiState>() {

private val sortingFields = SortingField.entries

private val marketFields = MarketField.entries

var sortingField: SortingField = SortingField.HighestCap
private set

var marketField: MarketField = MarketField.PriceDiff
private set

var viewState by mutableStateOf<ViewState>(ViewState.Loading)
private set
val sortingFields = listOf(
SortingField.HighestCap,
SortingField.LowestCap,
SortingField.TopGainers,
SortingField.TopLosers,
)

var viewItems by mutableStateOf<List<MarketViewItem>>(listOf())
private set
private var sortingField: SortingField = SortingField.HighestCap
private var viewState: ViewState = ViewState.Loading
private var viewItems: List<MarketViewItem> = listOf()
private var cache: List<MarketItem> = emptyList()
private var isRefreshing = false

val header = MarketModule.Header(
Translator.getString(R.string.MarketPlatformCoins_PlatformEcosystem, platform.name),
Expand All @@ -52,24 +48,17 @@ class MarketPlatformViewModel(
ImageSource.Remote(platform.iconUrl)
)

var isRefreshing by mutableStateOf(false)
private set

var selectorDialogState by mutableStateOf<SelectorDialogState>(SelectorDialogState.Closed)
private set

var menu by mutableStateOf(
MarketPlatformModule.Menu(
sortingFieldSelect = Select(sortingField, sortingFields),
marketFieldSelect = Select(marketField, marketFields)
)
)
private set

init {
sync()
}

override fun createState() = MarketPlatformUiState(
viewItems = viewItems,
viewState = viewState,
sortingField = sortingField,
isRefreshing = isRefreshing,
)

fun refresh() {
refreshWithMinLoadingSpinnerPeriod()
}
Expand All @@ -80,25 +69,7 @@ class MarketPlatformViewModel(

fun onSelectSortingField(sortingField: SortingField) {
this.sortingField = sortingField
selectorDialogState = SelectorDialogState.Closed
sync()
updateMenu()
}

fun onSelectMarketField(marketField: MarketField) {
this.marketField = marketField
sync()
updateMenu()
}

fun onSelectorDialogDismiss() {
selectorDialogState = SelectorDialogState.Closed
}

fun showSelectorMenu() {
selectorDialogState = SelectorDialogState.Opened(
Select(sortingField, sortingFields)
)
}

fun onAddFavorite(coinUid: String) {
Expand All @@ -111,39 +82,70 @@ class MarketPlatformViewModel(
sync()
}

private fun updateMenu() {
menu = MarketPlatformModule.Menu(
sortingFieldSelect = Select(sortingField, sortingFields),
marketFieldSelect = Select(marketField, marketFields)
)
}

private fun sync(forceRefresh: Boolean = false) {
viewModelScope.launch {
try {
val marketItems = repository.get(sortingField, forceRefresh)
val favorites = favoritesManager.getAll().map { it.coinUid }
viewItems = marketItems?.map {
MarketViewItem.create(
it,
marketField,
favorites.contains(it.fullCoin.coin.uid)
)
} ?: listOf()
viewModelScope.launch(Dispatchers.IO) {
if (!forceRefresh && cache.isNotEmpty()) {
viewItems = cache
.sort(sortingField)
.map { item ->
marketViewItem(item)
}
viewState = ViewState.Success
} catch (e: Throwable) {
viewState = ViewState.Error(e)
emitState()
} else {
fetchFromRepository(forceRefresh)
}
}
}

private suspend fun fetchFromRepository(forceRefresh: Boolean) {
try {
viewItems = repository.get(sortingField, forceRefresh)?.map {
marketViewItem(it)
} ?: listOf()

viewState = ViewState.Success
} catch (e: Throwable) {
viewState = ViewState.Error(e)
}
emitState()
}

private fun marketViewItem(item: MarketItem): MarketViewItem {
val marketCap = App.numberFormatter.formatFiatShort(
item.marketCap.value,
item.marketCap.currency.symbol,
2
)
return MarketViewItem(
fullCoin = item.fullCoin,
subtitle = marketCap,
value = App.numberFormatter.formatFiatFull(
item.rate.value,
item.rate.currency.symbol
),
marketDataValue = MarketDataValue.Diff(item.diff),
rank = item.rank?.toString(),
favorited = favoritesManager.getAll().map { it.coinUid }
.contains(item.fullCoin.coin.uid)
)
}

private fun refreshWithMinLoadingSpinnerPeriod() {
viewModelScope.launch {
sync(true)

isRefreshing = true
delay(1000)
isRefreshing = false
emitState()
}
}
}

data class MarketPlatformUiState(
val viewItems: List<MarketViewItem>,
val viewState: ViewState,
val sortingField: SortingField,
val isRefreshing: Boolean,
)

0 comments on commit a290d9e

Please sign in to comment.