mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 08:45:27 +02:00
Sorting settings for units list
- Favorites are now always first (except for search) closes #32
This commit is contained in:
parent
82a4f4ad0a
commit
89036b6ea6
@ -1245,6 +1245,8 @@
|
|||||||
<string name="enable_vibrations_support">Haptic feedback when clicking keyboard buttons</string>
|
<string name="enable_vibrations_support">Haptic feedback when clicking keyboard buttons</string>
|
||||||
<string name="format_time">Format time</string>
|
<string name="format_time">Format time</string>
|
||||||
<string name="format_time_support">Example: Show 130 minutes as 2h 10m</string>
|
<string name="format_time_support">Example: Show 130 minutes as 2h 10m</string>
|
||||||
|
<string name="units_sorting">Units list sorting</string>
|
||||||
|
<string name="units_sorting_support">Change units order</string>
|
||||||
<string name="currency_rates_note_setting">Wrong currency rates?</string>
|
<string name="currency_rates_note_setting">Wrong currency rates?</string>
|
||||||
<string name="currency_rates_note_title">Note</string>
|
<string name="currency_rates_note_title">Note</string>
|
||||||
<string name="currency_rates_note_text">Currency rates are updated daily. There\'s no real-time market monitoring in the app</string>
|
<string name="currency_rates_note_text">Currency rates are updated daily. There\'s no real-time market monitoring in the app</string>
|
||||||
@ -1303,6 +1305,12 @@
|
|||||||
<string name="allow_engineering">Allow engineering</string>
|
<string name="allow_engineering">Allow engineering</string>
|
||||||
<string name="force_engineering">Force engineering</string>
|
<string name="force_engineering">Force engineering</string>
|
||||||
|
|
||||||
|
<!--Units list sorting-->
|
||||||
|
<string name="sort_by_usage">Usage</string>
|
||||||
|
<string name="sort_by_alphabetical">Alphabetical</string>
|
||||||
|
<string name="sort_by_scale_desc">Scale (Desc.)</string>
|
||||||
|
<string name="sort_by_scale_asc">Scale (Asc.)</string>
|
||||||
|
|
||||||
<!--Theme-->
|
<!--Theme-->
|
||||||
<string name="theme_setting_support">App look and feel</string>
|
<string name="theme_setting_support">App look and feel</string>
|
||||||
<string name="force_auto_mode">Auto</string>
|
<string name="force_auto_mode">Auto</string>
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a unit converter for Android
|
||||||
|
* Copyright (c) 2023 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.data.model
|
||||||
|
|
||||||
|
enum class UnitsListSorting { USAGE, ALPHABETICAL, SCALE_DESC, SCALE_ASC }
|
@ -23,6 +23,7 @@ import com.sadellie.unitto.core.base.MAX_PRECISION
|
|||||||
import com.sadellie.unitto.data.database.UnitsEntity
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import com.sadellie.unitto.data.model.AbstractUnit
|
import com.sadellie.unitto.data.model.AbstractUnit
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.sortByLev
|
import com.sadellie.unitto.data.model.sortByLev
|
||||||
import com.sadellie.unitto.data.units.collections.accelerationCollection
|
import com.sadellie.unitto.data.units.collections.accelerationCollection
|
||||||
import com.sadellie.unitto.data.units.collections.angleCollection
|
import com.sadellie.unitto.data.units.collections.angleCollection
|
||||||
@ -129,6 +130,8 @@ class AllUnitsRepository @Inject constructor() {
|
|||||||
* set to True.
|
* set to True.
|
||||||
* @param searchQuery When not empty, will search by [AbstractUnit.renderedName] using [sortByLev].
|
* @param searchQuery When not empty, will search by [AbstractUnit.renderedName] using [sortByLev].
|
||||||
* @param allUnitsGroups All [UnitGroup]s. Determines which units will be used for filtering.
|
* @param allUnitsGroups All [UnitGroup]s. Determines which units will be used for filtering.
|
||||||
|
* @param sorting Sorting mode from [UnitsListSorting]
|
||||||
|
*
|
||||||
* @return Grouped by [UnitGroup] list of [AbstractUnit]s.
|
* @return Grouped by [UnitGroup] list of [AbstractUnit]s.
|
||||||
*/
|
*/
|
||||||
fun filterUnits(
|
fun filterUnits(
|
||||||
@ -136,9 +139,11 @@ class AllUnitsRepository @Inject constructor() {
|
|||||||
chosenUnitGroup: UnitGroup?,
|
chosenUnitGroup: UnitGroup?,
|
||||||
favoritesOnly: Boolean,
|
favoritesOnly: Boolean,
|
||||||
searchQuery: String,
|
searchQuery: String,
|
||||||
allUnitsGroups: List<UnitGroup>
|
allUnitsGroups: List<UnitGroup>,
|
||||||
|
sorting: UnitsListSorting = UnitsListSorting.USAGE
|
||||||
): Map<UnitGroup, List<AbstractUnit>> {
|
): Map<UnitGroup, List<AbstractUnit>> {
|
||||||
var basicFilteredUnits: Sequence<AbstractUnit> = if (chosenUnitGroup == null) {
|
// Leave only shown unit groups
|
||||||
|
var units: Sequence<AbstractUnit> = if (chosenUnitGroup == null) {
|
||||||
allUnits.filter { it.group in allUnitsGroups }
|
allUnits.filter { it.group in allUnitsGroups }
|
||||||
} else {
|
} else {
|
||||||
val collection = getCollectionByGroup(chosenUnitGroup)
|
val collection = getCollectionByGroup(chosenUnitGroup)
|
||||||
@ -146,20 +151,27 @@ class AllUnitsRepository @Inject constructor() {
|
|||||||
}.asSequence()
|
}.asSequence()
|
||||||
|
|
||||||
if (favoritesOnly) {
|
if (favoritesOnly) {
|
||||||
basicFilteredUnits = basicFilteredUnits.filter { it.isFavorite }
|
units = units.filter { it.isFavorite }
|
||||||
}
|
}
|
||||||
if (hideBrokenCurrencies) {
|
if (hideBrokenCurrencies) {
|
||||||
basicFilteredUnits = basicFilteredUnits.filter { it.isEnabled }
|
units = units.filter { it.isEnabled }
|
||||||
}
|
|
||||||
val unitsToShow = if (searchQuery.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 sort by popularity and Levenshtein distance (short and long name).
|
|
||||||
basicFilteredUnits.sortedByDescending { it.counter }.sortByLev(searchQuery)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return unitsToShow.groupBy { it.group }
|
units = when (sorting) {
|
||||||
|
UnitsListSorting.USAGE -> units.sortedByDescending { it.counter }
|
||||||
|
UnitsListSorting.ALPHABETICAL -> units.sortedBy { it.renderedName }
|
||||||
|
UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit }
|
||||||
|
UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit }
|
||||||
|
}
|
||||||
|
|
||||||
|
units = if (searchQuery.isEmpty()) {
|
||||||
|
units.sortedByDescending { it.isFavorite }
|
||||||
|
} else {
|
||||||
|
// For search we sort by popularity and Levenshtein distance (short and long name).
|
||||||
|
units.sortByLev(searchQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
return units.groupBy { it.group }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,6 +31,7 @@ import com.sadellie.unitto.core.base.TopLevelDestinations
|
|||||||
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
||||||
import com.sadellie.unitto.data.model.AbstractUnit
|
import com.sadellie.unitto.data.model.AbstractUnit
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.units.MyUnitIDS
|
import com.sadellie.unitto.data.units.MyUnitIDS
|
||||||
import io.github.sadellie.themmo.ThemingMode
|
import io.github.sadellie.themmo.ThemingMode
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@ -56,7 +57,8 @@ import javax.inject.Inject
|
|||||||
* @property enableToolsExperiment When true will enable experimental Tools screen.
|
* @property enableToolsExperiment When true will enable experimental Tools screen.
|
||||||
* @property radianMode AngleMode in mxParser. When true - Radian, when False - Degree.
|
* @property radianMode AngleMode in mxParser. When true - Radian, when False - Degree.
|
||||||
* @property unitConverterFavoritesOnly If true will show only units that are marked as favorite.
|
* @property unitConverterFavoritesOnly If true will show only units that are marked as favorite.
|
||||||
* @property unitConverterFormatTime If true will format time to be more human readable
|
* @property unitConverterFormatTime If true will format time to be more human readable.
|
||||||
|
* @property unitConverterSorting Units list sorting mode.
|
||||||
*/
|
*/
|
||||||
data class UserPreferences(
|
data class UserPreferences(
|
||||||
val themingMode: ThemingMode? = null,
|
val themingMode: ThemingMode? = null,
|
||||||
@ -74,6 +76,7 @@ data class UserPreferences(
|
|||||||
val radianMode: Boolean = true,
|
val radianMode: Boolean = true,
|
||||||
val unitConverterFavoritesOnly: Boolean = false,
|
val unitConverterFavoritesOnly: Boolean = false,
|
||||||
val unitConverterFormatTime: Boolean = false,
|
val unitConverterFormatTime: Boolean = false,
|
||||||
|
val unitConverterSorting: UnitsListSorting = UnitsListSorting.USAGE,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,6 +102,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
val RADIAN_MODE = booleanPreferencesKey("RADIAN_MODE_PREF_KEY")
|
val RADIAN_MODE = booleanPreferencesKey("RADIAN_MODE_PREF_KEY")
|
||||||
val UNIT_CONVERTER_FAVORITES_ONLY = booleanPreferencesKey("UNIT_CONVERTER_FAVORITES_ONLY_PREF_KEY")
|
val UNIT_CONVERTER_FAVORITES_ONLY = booleanPreferencesKey("UNIT_CONVERTER_FAVORITES_ONLY_PREF_KEY")
|
||||||
val UNIT_CONVERTER_FORMAT_TIME = booleanPreferencesKey("UNIT_CONVERTER_FORMAT_TIME_PREF_KEY")
|
val UNIT_CONVERTER_FORMAT_TIME = booleanPreferencesKey("UNIT_CONVERTER_FORMAT_TIME_PREF_KEY")
|
||||||
|
val UNIT_CONVERTER_SORTING = stringPreferencesKey("UNIT_CONVERTER_SORTING_PREF_KEY")
|
||||||
}
|
}
|
||||||
|
|
||||||
val userPreferencesFlow: Flow<UserPreferences> = dataStore.data
|
val userPreferencesFlow: Flow<UserPreferences> = dataStore.data
|
||||||
@ -146,6 +150,8 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
val radianMode: Boolean = preferences[PrefsKeys.RADIAN_MODE] ?: true
|
val radianMode: Boolean = preferences[PrefsKeys.RADIAN_MODE] ?: true
|
||||||
val unitConverterFavoritesOnly: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] ?: false
|
val unitConverterFavoritesOnly: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] ?: false
|
||||||
val unitConverterFormatTime: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false
|
val unitConverterFormatTime: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false
|
||||||
|
val unitConverterSorting: UnitsListSorting = preferences[PrefsKeys.UNIT_CONVERTER_SORTING]?.let { UnitsListSorting.valueOf(it) }
|
||||||
|
?: UnitsListSorting.USAGE
|
||||||
|
|
||||||
UserPreferences(
|
UserPreferences(
|
||||||
themingMode = themingMode,
|
themingMode = themingMode,
|
||||||
@ -163,6 +169,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
radianMode = radianMode,
|
radianMode = radianMode,
|
||||||
unitConverterFavoritesOnly = unitConverterFavoritesOnly,
|
unitConverterFavoritesOnly = unitConverterFavoritesOnly,
|
||||||
unitConverterFormatTime = unitConverterFormatTime,
|
unitConverterFormatTime = unitConverterFormatTime,
|
||||||
|
unitConverterSorting = unitConverterSorting
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,4 +324,15 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] = enabled
|
preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update [UserPreferences.unitConverterSorting].
|
||||||
|
*
|
||||||
|
* @see UserPreferences.unitConverterSorting
|
||||||
|
*/
|
||||||
|
suspend fun updateUnitConverterSorting(sorting: UnitsListSorting) {
|
||||||
|
dataStore.edit { preferences ->
|
||||||
|
preferences[PrefsKeys.UNIT_CONVERTER_SORTING] = sorting.name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import androidx.compose.material.icons.filled.Info
|
|||||||
import androidx.compose.material.icons.filled.Palette
|
import androidx.compose.material.icons.filled.Palette
|
||||||
import androidx.compose.material.icons.filled.RateReview
|
import androidx.compose.material.icons.filled.RateReview
|
||||||
import androidx.compose.material.icons.filled.Rule
|
import androidx.compose.material.icons.filled.Rule
|
||||||
|
import androidx.compose.material.icons.filled.Sort
|
||||||
import androidx.compose.material.icons.filled.Timer
|
import androidx.compose.material.icons.filled.Timer
|
||||||
import androidx.compose.material.icons.filled.Vibration
|
import androidx.compose.material.icons.filled.Vibration
|
||||||
import androidx.compose.material.icons.filled._123
|
import androidx.compose.material.icons.filled._123
|
||||||
@ -51,9 +52,10 @@ import com.sadellie.unitto.core.base.TOP_LEVEL_DESTINATIONS
|
|||||||
import com.sadellie.unitto.core.ui.R
|
import com.sadellie.unitto.core.ui.R
|
||||||
import com.sadellie.unitto.core.ui.common.Header
|
import com.sadellie.unitto.core.ui.common.Header
|
||||||
import com.sadellie.unitto.core.ui.common.MenuButton
|
import com.sadellie.unitto.core.ui.common.MenuButton
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
|
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
import com.sadellie.unitto.core.ui.common.UnittoListItem
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.core.ui.openLink
|
import com.sadellie.unitto.core.ui.openLink
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
||||||
import com.sadellie.unitto.feature.settings.navigation.aboutRoute
|
import com.sadellie.unitto.feature.settings.navigation.aboutRoute
|
||||||
import com.sadellie.unitto.feature.settings.navigation.themesRoute
|
import com.sadellie.unitto.feature.settings.navigation.themesRoute
|
||||||
@ -165,6 +167,21 @@ internal fun SettingsScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UNITS LIST SORTING
|
||||||
|
item {
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Sort,
|
||||||
|
stringResource(R.string.units_sorting)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineText = { Text(stringResource(R.string.units_sorting)) },
|
||||||
|
supportingText = { Text(stringResource(R.string.units_sorting_support)) },
|
||||||
|
modifier = Modifier.clickable { dialogState = DialogState.UNIT_LIST_SORTING }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// FORMAT TIME
|
// FORMAT TIME
|
||||||
item {
|
item {
|
||||||
UnittoListItem(
|
UnittoListItem(
|
||||||
@ -280,6 +297,20 @@ internal fun SettingsScreen(
|
|||||||
dismissAction = { resetDialog() }
|
dismissAction = { resetDialog() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
DialogState.UNIT_LIST_SORTING -> {
|
||||||
|
AlertDialogWithList(
|
||||||
|
title = stringResource(R.string.units_sorting),
|
||||||
|
listItems = mapOf(
|
||||||
|
UnitsListSorting.USAGE to R.string.sort_by_usage,
|
||||||
|
UnitsListSorting.ALPHABETICAL to R.string.sort_by_alphabetical,
|
||||||
|
UnitsListSorting.SCALE_DESC to R.string.sort_by_scale_desc,
|
||||||
|
UnitsListSorting.SCALE_ASC to R.string.sort_by_scale_asc,
|
||||||
|
),
|
||||||
|
selectedItemIndex = userPrefs.value.unitConverterSorting,
|
||||||
|
selectAction = viewModel::updateUnitConverterSorting,
|
||||||
|
dismissAction = { resetDialog() }
|
||||||
|
)
|
||||||
|
}
|
||||||
// Dismissing alert dialog
|
// Dismissing alert dialog
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
@ -289,5 +320,5 @@ internal fun SettingsScreen(
|
|||||||
* All possible states for alert dialog that opens when user clicks on settings.
|
* All possible states for alert dialog that opens when user clicks on settings.
|
||||||
*/
|
*/
|
||||||
private enum class DialogState {
|
private enum class DialogState {
|
||||||
NONE, PRECISION, SEPARATOR, OUTPUT_FORMAT, START_SCREEN
|
NONE, PRECISION, SEPARATOR, OUTPUT_FORMAT, START_SCREEN, UNIT_LIST_SORTING
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.core.ui.Formatter
|
import com.sadellie.unitto.core.ui.Formatter
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.unitgroups.UnitGroupsRepository
|
import com.sadellie.unitto.data.unitgroups.UnitGroupsRepository
|
||||||
import com.sadellie.unitto.data.userprefs.UserPreferencesRepository
|
import com.sadellie.unitto.data.userprefs.UserPreferencesRepository
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
@ -177,6 +178,15 @@ class SettingsViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see UserPreferencesRepository.updateUnitConverterSorting
|
||||||
|
*/
|
||||||
|
fun updateUnitConverterSorting(sorting: UnitsListSorting) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateUnitConverterSorting(sorting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent from dragging over non-draggable items (headers and hidden)
|
* Prevent from dragging over non-draggable items (headers and hidden)
|
||||||
*
|
*
|
||||||
|
@ -134,7 +134,8 @@ class UnitsListViewModel @Inject constructor(
|
|||||||
chosenUnitGroup = _chosenUnitGroup.value,
|
chosenUnitGroup = _chosenUnitGroup.value,
|
||||||
favoritesOnly = _userPrefs.value.unitConverterFavoritesOnly,
|
favoritesOnly = _userPrefs.value.unitConverterFavoritesOnly,
|
||||||
searchQuery = _searchQuery.value,
|
searchQuery = _searchQuery.value,
|
||||||
allUnitsGroups = _shownUnitGroups.value
|
allUnitsGroups = _shownUnitGroups.value,
|
||||||
|
sorting = _userPrefs.value.unitConverterSorting
|
||||||
)
|
)
|
||||||
|
|
||||||
_unitsToShow.update { unitsToShow }
|
_unitsToShow.update { unitsToShow }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user