diff --git a/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt b/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt index d98019cf..9b3e886a 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/MainViewModel.kt @@ -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 } } } diff --git a/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt b/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt index daea6710..ea080b55 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt @@ -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))