mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 00:35:26 +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="format_time">Format time</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_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>
|
||||
@ -1303,6 +1305,12 @@
|
||||
<string name="allow_engineering">Allow 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-->
|
||||
<string name="theme_setting_support">App look and feel</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.model.AbstractUnit
|
||||
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.units.collections.accelerationCollection
|
||||
import com.sadellie.unitto.data.units.collections.angleCollection
|
||||
@ -129,6 +130,8 @@ class AllUnitsRepository @Inject constructor() {
|
||||
* set to True.
|
||||
* @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 sorting Sorting mode from [UnitsListSorting]
|
||||
*
|
||||
* @return Grouped by [UnitGroup] list of [AbstractUnit]s.
|
||||
*/
|
||||
fun filterUnits(
|
||||
@ -136,9 +139,11 @@ class AllUnitsRepository @Inject constructor() {
|
||||
chosenUnitGroup: UnitGroup?,
|
||||
favoritesOnly: Boolean,
|
||||
searchQuery: String,
|
||||
allUnitsGroups: List<UnitGroup>
|
||||
allUnitsGroups: List<UnitGroup>,
|
||||
sorting: UnitsListSorting = UnitsListSorting.USAGE
|
||||
): 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 }
|
||||
} else {
|
||||
val collection = getCollectionByGroup(chosenUnitGroup)
|
||||
@ -146,20 +151,27 @@ class AllUnitsRepository @Inject constructor() {
|
||||
}.asSequence()
|
||||
|
||||
if (favoritesOnly) {
|
||||
basicFilteredUnits = basicFilteredUnits.filter { it.isFavorite }
|
||||
units = units.filter { it.isFavorite }
|
||||
}
|
||||
if (hideBrokenCurrencies) {
|
||||
basicFilteredUnits = basicFilteredUnits.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)
|
||||
units = units.filter { it.isEnabled }
|
||||
}
|
||||
|
||||
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.AbstractUnit
|
||||
import com.sadellie.unitto.data.model.UnitGroup
|
||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||
import com.sadellie.unitto.data.units.MyUnitIDS
|
||||
import io.github.sadellie.themmo.ThemingMode
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@ -56,7 +57,8 @@ import javax.inject.Inject
|
||||
* @property enableToolsExperiment When true will enable experimental Tools screen.
|
||||
* @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 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(
|
||||
val themingMode: ThemingMode? = null,
|
||||
@ -74,6 +76,7 @@ data class UserPreferences(
|
||||
val radianMode: Boolean = true,
|
||||
val unitConverterFavoritesOnly: 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 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_SORTING = stringPreferencesKey("UNIT_CONVERTER_SORTING_PREF_KEY")
|
||||
}
|
||||
|
||||
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 unitConverterFavoritesOnly: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] ?: 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(
|
||||
themingMode = themingMode,
|
||||
@ -163,6 +169,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
||||
radianMode = radianMode,
|
||||
unitConverterFavoritesOnly = unitConverterFavoritesOnly,
|
||||
unitConverterFormatTime = unitConverterFormatTime,
|
||||
unitConverterSorting = unitConverterSorting
|
||||
)
|
||||
}
|
||||
|
||||
@ -317,4 +324,15 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
||||
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.RateReview
|
||||
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.Vibration
|
||||
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.common.Header
|
||||
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.UnittoScreenWithLargeTopBar
|
||||
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.navigation.aboutRoute
|
||||
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
|
||||
item {
|
||||
UnittoListItem(
|
||||
@ -280,6 +297,20 @@ internal fun SettingsScreen(
|
||||
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
|
||||
else -> {}
|
||||
}
|
||||
@ -289,5 +320,5 @@ internal fun SettingsScreen(
|
||||
* All possible states for alert dialog that opens when user clicks on settings.
|
||||
*/
|
||||
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 com.sadellie.unitto.core.ui.Formatter
|
||||
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.userprefs.UserPreferencesRepository
|
||||
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)
|
||||
*
|
||||
|
@ -134,7 +134,8 @@ class UnitsListViewModel @Inject constructor(
|
||||
chosenUnitGroup = _chosenUnitGroup.value,
|
||||
favoritesOnly = _userPrefs.value.unitConverterFavoritesOnly,
|
||||
searchQuery = _searchQuery.value,
|
||||
allUnitsGroups = _shownUnitGroups.value
|
||||
allUnitsGroups = _shownUnitGroups.value,
|
||||
sorting = _userPrefs.value.unitConverterSorting
|
||||
)
|
||||
|
||||
_unitsToShow.update { unitsToShow }
|
||||
|
Loading…
x
Reference in New Issue
Block a user