diff --git a/core/base/src/main/res/values/strings.xml b/core/base/src/main/res/values/strings.xml
index 1ddab2a9..78978fe1 100644
--- a/core/base/src/main/res/values/strings.xml
+++ b/core/base/src/main/res/values/strings.xml
@@ -1243,6 +1243,8 @@
Unit groups
Vibrations
Haptic feedback when clicking keyboard buttons
+ Format time
+ Example: Show 130 minutes as 2h 10m
Wrong currency rates?
Note
Currency rates are updated daily. There\'s no real-time market monitoring in the app
diff --git a/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt b/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt
index fd1ffa2d..83f5f89f 100644
--- a/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt
+++ b/data/units/src/main/java/com/sadellie/unitto/data/units/FlowUtils.kt
@@ -21,7 +21,7 @@ package com.sadellie.unitto.data.units
import kotlinx.coroutines.flow.Flow
@Suppress("UNCHECKED_CAST")
-fun combine(
+fun combine(
flow: Flow,
flow2: Flow,
flow3: Flow,
@@ -30,10 +30,9 @@ fun combine(
flow6: Flow,
flow7: Flow,
flow8: Flow,
- flow9: Flow,
- transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R
+ transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R
): Flow =
- 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(
args[0] as T1,
args[1] as T2,
@@ -43,6 +42,5 @@ fun combine(
args[5] as T6,
args[6] as T7,
args[7] as T8,
- args[8] as T9,
)
}
diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
index cd1ae09e..741b2166 100644
--- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
+++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferences.kt
@@ -56,6 +56,7 @@ 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
*/
data class UserPreferences(
val themingMode: ThemingMode? = null,
@@ -71,7 +72,8 @@ data class UserPreferences(
val enableToolsExperiment: Boolean = false,
val startingScreen: String = TopLevelDestinations.Converter.route,
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 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 userPreferencesFlow: Flow = 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 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
UserPreferences(
themingMode = themingMode,
@@ -157,7 +161,8 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
enableToolsExperiment = enableToolsExperiment,
startingScreen = startingScreen,
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
}
}
+
+ /**
+ * Update [UserPreferences.unitConverterFormatTime].
+ *
+ * @see UserPreferences.unitConverterFormatTime
+ */
+ suspend fun updateUnitConverterFormatTime(enabled: Boolean) {
+ dataStore.edit { preferences ->
+ preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] = enabled
+ }
+ }
}
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
index 697ba53e..23465338 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt
@@ -62,7 +62,6 @@ internal fun ConverterRoute(
processInput = viewModel::processInput,
deleteDigit = viewModel::deleteDigit,
clearInput = viewModel::clearInput,
- onOutputTextFieldClick = viewModel::toggleFormatTime
)
}
@@ -77,7 +76,6 @@ private fun ConverterScreen(
processInput: (String) -> Unit,
deleteDigit: () -> Unit,
clearInput: () -> Unit,
- onOutputTextFieldClick: () -> Unit
) {
UnittoScreenWithTopBar(
title = { Text(stringResource(R.string.unit_converter)) },
@@ -109,8 +107,7 @@ private fun ConverterScreen(
navigateToRightScreen = navigateToRightScreen,
swapUnits = swapMeasurements,
converterMode = uiState.mode,
- formatTime = uiState.formatTime,
- onOutputTextFieldClick = onOutputTextFieldClick
+ formatTime = uiState.formatTime
)
},
content2 = {
@@ -156,6 +153,5 @@ private fun PreviewConverterScreen(
processInput = {},
deleteDigit = {},
clearInput = {},
- onOutputTextFieldClick = {}
)
}
\ No newline at end of file
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
index adfa06f8..cd5b64b5 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt
@@ -110,8 +110,6 @@ class ConverterViewModel @Inject constructor(
*/
private val _showError: MutableStateFlow = MutableStateFlow(false)
- private val _formatTime: MutableStateFlow = MutableStateFlow(true)
-
/**
* Current state of UI.
*/
@@ -123,9 +121,8 @@ class ConverterViewModel @Inject constructor(
_result,
_showLoading,
_showError,
- _formatTime,
_userPrefs
- ) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, formatTime, prefs ->
+ ) { inputValue, unitFromValue, unitToValue, calculatedValue, resultValue, showLoadingValue, showErrorValue, prefs ->
return@combine ConverterUIState(
inputValue = inputValue,
calculatedValue = calculatedValue,
@@ -139,7 +136,7 @@ class ConverterViewModel @Inject constructor(
* changing units.
*/
mode = if (_unitFrom.value is NumberBaseUnit) ConverterMode.BASE else ConverterMode.DEFAULT,
- formatTime = formatTime,
+ formatTime = prefs.unitConverterFormatTime,
allowVibration = prefs.enableVibrations
)
}
@@ -373,10 +370,6 @@ class ConverterViewModel @Inject constructor(
setInputSymbols(Token._0, false)
}
- fun toggleFormatTime() {
- _formatTime.update { !it }
- }
-
private suspend fun convertInput() {
withContext(Dispatchers.Default) {
while (isActive) {
diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt
index aa40fe21..39f1af65 100644
--- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt
+++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt
@@ -77,7 +77,6 @@ import com.sadellie.unitto.feature.converter.ConverterMode
* @param swapUnits Method to swap units.
* @param converterMode [ConverterMode.BASE] doesn't use formatting for input/output.
* @param formatTime If True will use [Formatter.formatTime].
- * @param onOutputTextFieldClick Action to be called when user clicks on output text field.
*/
@Composable
internal fun TopScreenPart(
@@ -94,7 +93,6 @@ internal fun TopScreenPart(
swapUnits: () -> Unit,
converterMode: ConverterMode,
formatTime: Boolean,
- onOutputTextFieldClick: () -> Unit
) {
var swapped by remember { mutableStateOf(false) }
val swapButtonRotation: Float by animateFloatAsState(
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt
index c843c389..7073da12 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsScreen.kt
@@ -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.Timer
import androidx.compose.material.icons.filled.Vibration
import androidx.compose.material.icons.filled._123
import androidx.compose.material3.Icon
@@ -76,21 +77,6 @@ internal fun SettingsScreen(
) { 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
item {
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
item { Header(stringResource(R.string.additional_settings_group)) }
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt
index 3b3e77cf..07740129 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/SettingsViewModel.kt
@@ -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)
*