mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 00:35:26 +02:00
Format time as a separate setting
This commit is contained in:
parent
ff48ac6444
commit
82a4f4ad0a
@ -1243,6 +1243,8 @@
|
|||||||
<string name="unit_groups_setting">Unit groups</string>
|
<string name="unit_groups_setting">Unit groups</string>
|
||||||
<string name="enable_vibrations">Vibrations</string>
|
<string name="enable_vibrations">Vibrations</string>
|
||||||
<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_support">Example: Show 130 minutes as 2h 10m</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>
|
||||||
|
@ -21,7 +21,7 @@ package com.sadellie.unitto.data.units
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> combine(
|
fun <T1, T2, T3, T4, T5, T6, T7, T8, R> combine(
|
||||||
flow: Flow<T1>,
|
flow: Flow<T1>,
|
||||||
flow2: Flow<T2>,
|
flow2: Flow<T2>,
|
||||||
flow3: Flow<T3>,
|
flow3: Flow<T3>,
|
||||||
@ -30,10 +30,9 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> combine(
|
|||||||
flow6: Flow<T6>,
|
flow6: Flow<T6>,
|
||||||
flow7: Flow<T7>,
|
flow7: Flow<T7>,
|
||||||
flow8: Flow<T8>,
|
flow8: Flow<T8>,
|
||||||
flow9: Flow<T9>,
|
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R
|
||||||
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R
|
|
||||||
): Flow<R> =
|
): Flow<R> =
|
||||||
kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8, flow9) { args: Array<*> ->
|
kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8) { args: Array<*> ->
|
||||||
transform(
|
transform(
|
||||||
args[0] as T1,
|
args[0] as T1,
|
||||||
args[1] as T2,
|
args[1] as T2,
|
||||||
@ -43,6 +42,5 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> combine(
|
|||||||
args[5] as T6,
|
args[5] as T6,
|
||||||
args[6] as T7,
|
args[6] as T7,
|
||||||
args[7] as T8,
|
args[7] as T8,
|
||||||
args[8] as T9,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ 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
|
||||||
*/
|
*/
|
||||||
data class UserPreferences(
|
data class UserPreferences(
|
||||||
val themingMode: ThemingMode? = null,
|
val themingMode: ThemingMode? = null,
|
||||||
@ -71,7 +72,8 @@ data class UserPreferences(
|
|||||||
val enableToolsExperiment: Boolean = false,
|
val enableToolsExperiment: Boolean = false,
|
||||||
val startingScreen: String = TopLevelDestinations.Converter.route,
|
val startingScreen: String = TopLevelDestinations.Converter.route,
|
||||||
val radianMode: Boolean = true,
|
val radianMode: Boolean = true,
|
||||||
val unitConverterFavoritesOnly: Boolean = false
|
val unitConverterFavoritesOnly: Boolean = false,
|
||||||
|
val unitConverterFormatTime: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,6 +98,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
val STARTING_SCREEN = stringPreferencesKey("STARTING_SCREEN_PREF_KEY")
|
val STARTING_SCREEN = stringPreferencesKey("STARTING_SCREEN_PREF_KEY")
|
||||||
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 userPreferencesFlow: Flow<UserPreferences> = dataStore.data
|
val userPreferencesFlow: Flow<UserPreferences> = dataStore.data
|
||||||
@ -142,6 +145,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
val startingScreen: String = preferences[PrefsKeys.STARTING_SCREEN] ?: TopLevelDestinations.Converter.route
|
val startingScreen: String = preferences[PrefsKeys.STARTING_SCREEN] ?: TopLevelDestinations.Converter.route
|
||||||
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
|
||||||
|
|
||||||
UserPreferences(
|
UserPreferences(
|
||||||
themingMode = themingMode,
|
themingMode = themingMode,
|
||||||
@ -157,7 +161,8 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
enableToolsExperiment = enableToolsExperiment,
|
enableToolsExperiment = enableToolsExperiment,
|
||||||
startingScreen = startingScreen,
|
startingScreen = startingScreen,
|
||||||
radianMode = radianMode,
|
radianMode = radianMode,
|
||||||
unitConverterFavoritesOnly = unitConverterFavoritesOnly
|
unitConverterFavoritesOnly = unitConverterFavoritesOnly,
|
||||||
|
unitConverterFormatTime = unitConverterFormatTime,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,4 +306,15 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] = enabled
|
preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY] = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update [UserPreferences.unitConverterFormatTime].
|
||||||
|
*
|
||||||
|
* @see UserPreferences.unitConverterFormatTime
|
||||||
|
*/
|
||||||
|
suspend fun updateUnitConverterFormatTime(enabled: Boolean) {
|
||||||
|
dataStore.edit { preferences ->
|
||||||
|
preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] = enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ internal fun ConverterRoute(
|
|||||||
processInput = viewModel::processInput,
|
processInput = viewModel::processInput,
|
||||||
deleteDigit = viewModel::deleteDigit,
|
deleteDigit = viewModel::deleteDigit,
|
||||||
clearInput = viewModel::clearInput,
|
clearInput = viewModel::clearInput,
|
||||||
onOutputTextFieldClick = viewModel::toggleFormatTime
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +76,6 @@ private fun ConverterScreen(
|
|||||||
processInput: (String) -> Unit,
|
processInput: (String) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
deleteDigit: () -> Unit,
|
||||||
clearInput: () -> Unit,
|
clearInput: () -> Unit,
|
||||||
onOutputTextFieldClick: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
UnittoScreenWithTopBar(
|
UnittoScreenWithTopBar(
|
||||||
title = { Text(stringResource(R.string.unit_converter)) },
|
title = { Text(stringResource(R.string.unit_converter)) },
|
||||||
@ -109,8 +107,7 @@ private fun ConverterScreen(
|
|||||||
navigateToRightScreen = navigateToRightScreen,
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
swapUnits = swapMeasurements,
|
swapUnits = swapMeasurements,
|
||||||
converterMode = uiState.mode,
|
converterMode = uiState.mode,
|
||||||
formatTime = uiState.formatTime,
|
formatTime = uiState.formatTime
|
||||||
onOutputTextFieldClick = onOutputTextFieldClick
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
content2 = {
|
content2 = {
|
||||||
@ -156,6 +153,5 @@ private fun PreviewConverterScreen(
|
|||||||
processInput = {},
|
processInput = {},
|
||||||
deleteDigit = {},
|
deleteDigit = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
onOutputTextFieldClick = {}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -110,8 +110,6 @@ class ConverterViewModel @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
private val _showError: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
private val _showError: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||||
|
|
||||||
private val _formatTime: MutableStateFlow<Boolean> = MutableStateFlow(true)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current state of UI.
|
* Current state of UI.
|
||||||
*/
|
*/
|
||||||
@ -123,9 +121,8 @@ class ConverterViewModel @Inject constructor(
|
|||||||
_result,
|
_result,
|
||||||
_showLoading,
|
_showLoading,
|
||||||
_showError,
|
_showError,
|
||||||
_formatTime,
|
|
||||||
_userPrefs
|
_userPrefs
|
||||||
) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, formatTime, prefs ->
|
) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, prefs ->
|
||||||
return@combine ConverterUIState(
|
return@combine ConverterUIState(
|
||||||
inputValue = inputValue,
|
inputValue = inputValue,
|
||||||
calculatedValue = calculatedValue,
|
calculatedValue = calculatedValue,
|
||||||
@ -139,7 +136,7 @@ class ConverterViewModel @Inject constructor(
|
|||||||
* changing units.
|
* changing units.
|
||||||
*/
|
*/
|
||||||
mode = if (_unitFrom.value is NumberBaseUnit) ConverterMode.BASE else ConverterMode.DEFAULT,
|
mode = if (_unitFrom.value is NumberBaseUnit) ConverterMode.BASE else ConverterMode.DEFAULT,
|
||||||
formatTime = formatTime,
|
formatTime = prefs.unitConverterFormatTime,
|
||||||
allowVibration = prefs.enableVibrations
|
allowVibration = prefs.enableVibrations
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -373,10 +370,6 @@ class ConverterViewModel @Inject constructor(
|
|||||||
setInputSymbols(Token._0, false)
|
setInputSymbols(Token._0, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleFormatTime() {
|
|
||||||
_formatTime.update { !it }
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun convertInput() {
|
private suspend fun convertInput() {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(Dispatchers.Default) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
|
@ -77,7 +77,6 @@ import com.sadellie.unitto.feature.converter.ConverterMode
|
|||||||
* @param swapUnits Method to swap units.
|
* @param swapUnits Method to swap units.
|
||||||
* @param converterMode [ConverterMode.BASE] doesn't use formatting for input/output.
|
* @param converterMode [ConverterMode.BASE] doesn't use formatting for input/output.
|
||||||
* @param formatTime If True will use [Formatter.formatTime].
|
* @param formatTime If True will use [Formatter.formatTime].
|
||||||
* @param onOutputTextFieldClick Action to be called when user clicks on output text field.
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TopScreenPart(
|
internal fun TopScreenPart(
|
||||||
@ -94,7 +93,6 @@ internal fun TopScreenPart(
|
|||||||
swapUnits: () -> Unit,
|
swapUnits: () -> Unit,
|
||||||
converterMode: ConverterMode,
|
converterMode: ConverterMode,
|
||||||
formatTime: Boolean,
|
formatTime: Boolean,
|
||||||
onOutputTextFieldClick: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
var swapped by remember { mutableStateOf(false) }
|
var swapped by remember { mutableStateOf(false) }
|
||||||
val swapButtonRotation: Float by animateFloatAsState(
|
val swapButtonRotation: Float by animateFloatAsState(
|
||||||
|
@ -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.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
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -76,21 +77,6 @@ internal fun SettingsScreen(
|
|||||||
) { padding ->
|
) { padding ->
|
||||||
LazyColumn(contentPadding = padding) {
|
LazyColumn(contentPadding = padding) {
|
||||||
|
|
||||||
// UNIT GROUPS
|
|
||||||
item {
|
|
||||||
ListItem(
|
|
||||||
leadingContent = {
|
|
||||||
Icon(
|
|
||||||
Icons.Default.Rule,
|
|
||||||
stringResource(R.string.disable_unit_group_description),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
headlineText = { Text(stringResource(R.string.unit_groups_setting)) },
|
|
||||||
supportingText = { Text(stringResource(R.string.unit_groups_support)) },
|
|
||||||
modifier = Modifier.clickable { navControllerAction(unitsGroupRoute) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// THEME
|
// THEME
|
||||||
item {
|
item {
|
||||||
ListItem(
|
ListItem(
|
||||||
@ -161,6 +147,40 @@ internal fun SettingsScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UNIT CONVERTER GROUP
|
||||||
|
item { Header(stringResource(R.string.unit_converter)) }
|
||||||
|
|
||||||
|
// UNIT GROUPS
|
||||||
|
item {
|
||||||
|
ListItem(
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Rule,
|
||||||
|
stringResource(R.string.disable_unit_group_description),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
headlineText = { Text(stringResource(R.string.unit_groups_setting)) },
|
||||||
|
supportingText = { Text(stringResource(R.string.unit_groups_support)) },
|
||||||
|
modifier = Modifier.clickable { navControllerAction(unitsGroupRoute) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FORMAT TIME
|
||||||
|
item {
|
||||||
|
UnittoListItem(
|
||||||
|
label = stringResource(R.string.format_time),
|
||||||
|
leadingContent = {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.Timer,
|
||||||
|
stringResource(R.string.format_time)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
supportText = stringResource(R.string.format_time_support),
|
||||||
|
switchState = userPrefs.value.unitConverterFormatTime,
|
||||||
|
onSwitchChange = viewModel::updateUnitConverterFormatTime
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// ADDITIONAL GROUP
|
// ADDITIONAL GROUP
|
||||||
item { Header(stringResource(R.string.additional_settings_group)) }
|
item { Header(stringResource(R.string.additional_settings_group)) }
|
||||||
|
|
||||||
|
@ -168,6 +168,15 @@ class SettingsViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see UserPreferencesRepository.updateUnitConverterFormatTime
|
||||||
|
*/
|
||||||
|
fun updateUnitConverterFormatTime(enabled: Boolean) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateUnitConverterFormatTime(enabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevent from dragging over non-draggable items (headers and hidden)
|
* Prevent from dragging over non-draggable items (headers and hidden)
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user