Better (?) units list loading

Moved from LaunchedEffect to another approach. Basically list is updated in onClick methods (not observing value in LaunchedEffect anymore)
This commit is contained in:
Sad Ellie 2022-05-12 21:39:49 +03:00
parent 0f92d24732
commit d119c94b0a
2 changed files with 63 additions and 42 deletions

View File

@ -413,49 +413,53 @@ class MainViewModel @Inject constructor(
* @param leftSide Decide whether or not we are on left side. Need it because right side requires
* us to mark disabled currency units
*/
suspend fun loadUnitToShow(
fun loadUnitsToShow(
query: String,
chosenUnitGroup: UnitGroup?,
leftSide: Boolean
) {
val filterGroup: Boolean = chosenUnitGroup != null
viewModelScope.launch {
val filterGroup: Boolean = chosenUnitGroup != null
withContext(Dispatchers.Default) {
// Basic filtering
var basicFilteredUnits = ALL_UNITS.asSequence()
basicFilteredUnits = when {
// Both sides, Chip is selected, Only favorites
(filterGroup) and (favoritesOnly) -> {
basicFilteredUnits.filter { (it.group == chosenUnitGroup) and it.isFavorite }
// This is mostly not UI related stuff and viewModelScope.launch uses Dispatchers.Main
// So we switch to Default
withContext(Dispatchers.Default) {
// Basic filtering
var basicFilteredUnits = ALL_UNITS.asSequence()
basicFilteredUnits = when {
// Both sides, Chip is selected, Only favorites
(filterGroup) and (favoritesOnly) -> {
basicFilteredUnits.filter { (it.group == chosenUnitGroup) and it.isFavorite }
}
// Both sides, Chip is selected, NOT Only favorites
(filterGroup) and (!favoritesOnly) -> {
basicFilteredUnits.filter { it.group == chosenUnitGroup }
}
// Chip is NOT selected, Only favorites
(!filterGroup) and (favoritesOnly) -> {
basicFilteredUnits.filter { it.isFavorite }
}
// Chip is NOT selected, NOT Only favorites
else -> basicFilteredUnits
}
// Both sides, Chip is selected, NOT Only favorites
(filterGroup) and (!favoritesOnly) -> {
basicFilteredUnits.filter { it.group == chosenUnitGroup }
}
// Chip is NOT selected, Only favorites
(!filterGroup) and (favoritesOnly) -> {
basicFilteredUnits.filter { it.isFavorite }
}
// Chip is NOT selected, NOT Only favorites
else -> basicFilteredUnits
}
// Hiding broken currency units
if (leftSide) {
basicFilteredUnits = basicFilteredUnits.filter { it.isEnabled }
}
// Hiding broken currency units
if (leftSide) {
basicFilteredUnits = basicFilteredUnits.filter { it.isEnabled }
}
unitsToShow = if (query.isEmpty()) {
// Query is empty, i.e. we want to see all units and they need to be sorted by usage
basicFilteredUnits
.sortedByDescending { it.counter }
} else {
// We are searching for a specific unit, we don't care about popularity
// We need search accuracy
basicFilteredUnits.sortByLev(query)
unitsToShow = if (query.isEmpty()) {
// Query is empty, i.e. we want to see all units and they need to be sorted by usage
basicFilteredUnits
.sortedByDescending { it.counter }
} else {
// We are searching for a specific unit, we don't care about popularity
// We need search accuracy
basicFilteredUnits.sortByLev(query)
}
// Group by unit group
.groupBy { it.group }
}
// Group by unit group
.groupBy { it.group }
}
}

View File

@ -46,9 +46,15 @@ fun SecondScreen(
.padding(8.dp),
title = stringResource(id = if (leftSide) R.string.units_screen_from else R.string.units_screen_to),
value = searchQuery,
onValueChange = { searchQuery = it },
onValueChange = {
searchQuery = it
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
},
favoritesOnly = favoritesOnly,
favoriteAction = { viewModel.toggleFavoritesOnly() },
favoriteAction = {
viewModel.toggleFavoritesOnly()
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
},
navigateUpAction = navigateUp,
focusManager = focusManager
)
@ -58,7 +64,10 @@ fun SecondScreen(
lazyListState = chipsRowLazyListState,
items = ALL_UNIT_GROUPS,
chosenUnitGroup = chosenUnitGroup,
selectAction = { chosenUnitGroup = if (it == chosenUnitGroup) null else it }
selectAction = {
chosenUnitGroup = if (it == chosenUnitGroup) null else it
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
}
)
UnitsList(
groupedUnits = unitsList,
@ -77,12 +86,20 @@ fun SecondScreen(
)
}
}
LaunchedEffect(searchQuery, favoritesOnly, chosenUnitGroup) {
// Everytime we change query, toggle favorites or click chip, this block will be called
viewModel.loadUnitToShow(searchQuery, chosenUnitGroup, leftSide)
}
// This block is called only once on initial composition
LaunchedEffect(Unit) {
// This block is called only once on initial composition
/**
* Telling viewModel that it needs to update the list
* Also while the below is being computed user will composable will use cached list from viewModel
*
* User actually doesn't see cached list. Computation takes few milliseconds since we don't
* compute any Levenshtein distance when the screen is launched and the list is limited
* to a specific [UnitGroup]
*
* Adding animation/spinners will cause flickering and confuse user
*/
viewModel.loadUnitsToShow(searchQuery, chosenUnitGroup, leftSide)
// Scrolling chips to current group
chosenUnitGroup?.let {
chipsRowLazyListState.animateScrollToItem(ALL_UNIT_GROUPS.indexOf(chosenUnitGroup))