Start screen option

This commit is contained in:
Sad Ellie 2023-02-22 10:19:06 +04:00
parent 30b97ef821
commit f92488f336
12 changed files with 123 additions and 25 deletions

View File

@ -45,7 +45,7 @@ fun UnittoApp() {
val themmoController = rememberThemmoController(
lightColorScheme = LightThemeColors,
darkColorScheme = DarkThemeColors,
// Anything below will not called if theming mode is still loading from DataStore
// Anything below will not be called if theming mode is still loading from DataStore
themingMode = userPrefs.value.themingMode ?: return,
dynamicThemeEnabled = userPrefs.value.enableDynamicTheme,
amoledThemeEnabled = userPrefs.value.enableAmoledTheme
@ -65,7 +65,8 @@ fun UnittoApp() {
converterViewModel = converterViewModel,
secondViewModel = secondViewModel,
settingsViewModel = settingsViewModel,
themmoController = it
themmoController = it,
startDestination = userPrefs.value.startingScreen
)
SideEffect { sysUiController.setSystemBarsColor(backgroundColor) }

View File

@ -26,7 +26,6 @@ import androidx.navigation.compose.NavHost
import com.sadellie.unitto.feature.calculator.navigation.calculatorScreen
import com.sadellie.unitto.feature.calculator.navigation.navigateToCalculator
import com.sadellie.unitto.feature.converter.ConverterViewModel
import com.sadellie.unitto.feature.converter.navigation.converterRoute
import com.sadellie.unitto.feature.converter.navigation.converterScreen
import com.sadellie.unitto.feature.converter.navigation.navigateToConverter
import com.sadellie.unitto.feature.epoch.navigation.epochScreen
@ -50,11 +49,12 @@ fun UnittoNavigation(
converterViewModel: ConverterViewModel,
secondViewModel: SecondViewModel,
settingsViewModel: SettingsViewModel,
themmoController: ThemmoController
themmoController: ThemmoController,
startDestination: String
) {
NavHost(
navController = navController,
startDestination = converterRoute
startDestination = startDestination
) {
converterScreen(
navigateToLeftScreen = navController::navigateToLeftSide,

View File

@ -0,0 +1,32 @@
/*
* 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.core.base
object TopLevelDestinations {
const val CONVERTER = "converter_route"
const val CALCULATOR = "calculator_route"
const val EPOCH = "epoch_route"
}
val TOP_LEVEL_DESTINATIONS: Map<String, Int> by lazy {
mapOf(
TopLevelDestinations.CONVERTER to R.string.unit_converter,
TopLevelDestinations.CALCULATOR to R.string.calculator,
)
}

View File

@ -999,6 +999,8 @@
<string name="precision_setting">Precision</string>
<string name="separator_setting">Separator</string>
<string name="output_format_setting">Output format</string>
<string name="starting_screen_setting">Starting screen</string>
<string name="starting_screen_setting_support">Choose which screen is shown when you launch the app</string>
<string name="unit_groups_setting">Unit groups</string>
<string name="enable_vibrations">Vibrations</string>
<string name="enable_vibrations_support">Haptic feedback when clicking keyboard buttons</string>

View File

@ -27,6 +27,7 @@ import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.sadellie.unitto.core.base.OutputFormat
import com.sadellie.unitto.core.base.Separator
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
@ -65,7 +66,8 @@ data class UserPreferences(
val latestRightSideUnit: String = MyUnitIDS.mile,
val shownUnitGroups: List<UnitGroup> = ALL_UNIT_GROUPS,
val enableVibrations: Boolean = true,
val enableToolsExperiment: Boolean = false
val enableToolsExperiment: Boolean = false,
val startingScreen: String = TopLevelDestinations.CONVERTER
)
/**
@ -87,6 +89,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
val SHOWN_UNIT_GROUPS = stringPreferencesKey("SHOWN_UNIT_GROUPS_PREF_KEY")
val ENABLE_VIBRATIONS = booleanPreferencesKey("ENABLE_VIBRATIONS_PREF_KEY")
val ENABLE_TOOLS_EXPERIMENT = booleanPreferencesKey("ENABLE_TOOLS_EXPERIMENT_PREF_KEY")
val STARTING_SCREEN = stringPreferencesKey("STARTING_SCREEN_PREF_KEY")
}
val userPreferencesFlow: Flow<UserPreferences> = dataStore.data
@ -130,6 +133,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
} ?: ALL_UNIT_GROUPS
val enableVibrations: Boolean = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true
val enableToolsExperiment: Boolean = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false
val startingScreen: String = preferences[PrefsKeys.STARTING_SCREEN] ?: TopLevelDestinations.CONVERTER
UserPreferences(
themingMode = themingMode,
@ -142,7 +146,8 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
latestRightSideUnit = latestRightSideUnit,
shownUnitGroups = shownUnitGroups,
enableVibrations = enableVibrations,
enableToolsExperiment = enableToolsExperiment
enableToolsExperiment = enableToolsExperiment,
startingScreen = startingScreen
)
}
@ -226,6 +231,17 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
}
}
/**
* Update preference on starting screen route.
*
* @param startingScreen Route from [TopLevelDestinations].
*/
suspend fun updateStartingScreen(startingScreen: String) {
dataStore.edit { preferences ->
preferences[PrefsKeys.STARTING_SCREEN] = startingScreen
}
}
suspend fun updateShownUnitGroups(shownUnitGroups: List<UnitGroup>) {
dataStore.edit { preferences ->
preferences[PrefsKeys.SHOWN_UNIT_GROUPS] = shownUnitGroups.joinToString(",")

View File

@ -23,9 +23,10 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import androidx.navigation.navDeepLink
import com.sadellie.unitto.core.base.TopLevelDestinations
import com.sadellie.unitto.feature.calculator.CalculatorRoute
private const val calculatorRoute = "calculator_route"
private const val calculatorRoute = TopLevelDestinations.CALCULATOR
fun NavController.navigateToCalculator(navOptions: NavOptions) {
navigate(calculatorRoute, navOptions)

View File

@ -22,10 +22,11 @@ import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.sadellie.unitto.core.base.TopLevelDestinations
import com.sadellie.unitto.feature.converter.ConverterRoute
import com.sadellie.unitto.feature.converter.ConverterViewModel
const val converterRoute = "converter_route"
const val converterRoute = TopLevelDestinations.CONVERTER
fun NavController.navigateToConverter(navOptions: NavOptions) {
navigate(converterRoute, navOptions)

View File

@ -23,9 +23,10 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import androidx.navigation.navDeepLink
import com.sadellie.unitto.core.base.TopLevelDestinations
import com.sadellie.unitto.feature.epoch.EpochRoute
private const val epochRoute = "epoch_route"
private const val epochRoute = TopLevelDestinations.EPOCH
fun NavController.navigateToEpoch(navOptions: NavOptions) {
navigate(epochRoute, navOptions)

View File

@ -30,9 +30,11 @@ import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Policy
import androidx.compose.material.icons.filled.PrivacyTip
import androidx.compose.material.icons.filled.Translate
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -46,7 +48,6 @@ import com.sadellie.unitto.core.base.BuildConfig
import com.sadellie.unitto.core.ui.R
import com.sadellie.unitto.core.ui.common.UnittoLargeTopAppBar
import com.sadellie.unitto.core.ui.openLink
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
@Composable
internal fun AboutScreen(
@ -198,11 +199,19 @@ internal fun AboutScreen(
}
if (showDialog) {
AlertDialogWithList(
title = stringResource(R.string.currency_rates_note_title),
dismissAction = { showDialog = false },
supportText = stringResource(R.string.currency_rates_note_text),
dismissButtonLabel = stringResource(R.string.ok_label)
AlertDialog(
title = {
Text(stringResource(R.string.currency_rates_note_title))
},
text = {
Text(stringResource(R.string.currency_rates_note_text))
},
confirmButton = {
TextButton(onClick = { showDialog = false }) {
Text(stringResource(R.string.ok_label))
}
},
onDismissRequest = { showDialog = false }
)
}
}

View File

@ -22,6 +22,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.RateReview
@ -45,6 +46,7 @@ import com.sadellie.unitto.core.base.BuildConfig
import com.sadellie.unitto.core.base.OUTPUT_FORMAT
import com.sadellie.unitto.core.base.PRECISIONS
import com.sadellie.unitto.core.base.SEPARATORS
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.UnittoLargeTopAppBar
@ -103,6 +105,21 @@ internal fun SettingsScreen(
)
}
// START SCREEN
item {
ListItem(
leadingContent = {
Icon(
Icons.Default.Home,
stringResource(R.string.starting_screen_setting),
)
},
headlineText = { Text(stringResource(R.string.starting_screen_setting)) },
supportingText = { Text(stringResource(R.string.starting_screen_setting_support)) },
modifier = Modifier.clickable { dialogState = DialogState.START_SCREEN }
)
}
// GENERAL GROUP
item { Header(stringResource(R.string.formatting_settings_group)) }
@ -209,7 +226,7 @@ internal fun SettingsScreen(
title = stringResource(R.string.precision_setting),
listItems = PRECISIONS,
selectedItemIndex = userPrefs.value.digitsPrecision,
selectAction = { viewModel.updatePrecision(it) },
selectAction = viewModel::updatePrecision,
dismissAction = { resetDialog() },
supportText = stringResource(R.string.precision_setting_info)
)
@ -219,7 +236,7 @@ internal fun SettingsScreen(
title = stringResource(R.string.separator_setting),
listItems = SEPARATORS,
selectedItemIndex = userPrefs.value.separator,
selectAction = { viewModel.updateSeparator(it) },
selectAction = viewModel::updateSeparator,
dismissAction = { resetDialog() }
)
}
@ -228,11 +245,20 @@ internal fun SettingsScreen(
title = stringResource(R.string.output_format_setting),
listItems = OUTPUT_FORMAT,
selectedItemIndex = userPrefs.value.outputFormat,
selectAction = { viewModel.updateOutputFormat(it) },
selectAction = viewModel::updateOutputFormat,
dismissAction = { resetDialog() },
supportText = stringResource(R.string.output_format_setting_info)
)
}
DialogState.START_SCREEN -> {
AlertDialogWithList(
title = stringResource(R.string.starting_screen_setting),
selectedItemIndex = userPrefs.value.startingScreen,
listItems = TOP_LEVEL_DESTINATIONS,
selectAction = viewModel::updateStartingScreen,
dismissAction = { resetDialog() }
)
}
// Dismissing alert dialog
else -> {}
}
@ -242,5 +268,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,
NONE, PRECISION, SEPARATOR, OUTPUT_FORMAT, START_SCREEN
}

View File

@ -110,6 +110,15 @@ class SettingsViewModel @Inject constructor(
}
}
/**
* @see UserPreferencesRepository.updateStartingScreen
*/
fun updateStartingScreen(startingScreen: String) {
viewModelScope.launch {
userPrefsRepository.updateStartingScreen(startingScreen)
}
}
/**
* @see UnitGroupsRepository.markUnitGroupAsHidden
* @see UserPreferencesRepository.updateShownUnitGroups

View File

@ -44,18 +44,18 @@ import com.sadellie.unitto.feature.settings.R
* Alert dialog that has a list of options in it
*
* @param title Dialog title
* @param listItems List of options
* @param listItems List of options. Map, where key is an option and value is a string (option name)
* @param selectedItemIndex Currently selected item index
* @param selectAction Action to perform when clicking an option
* @param dismissAction Action to perform when clicking "cancel"
* @param supportText Text above list of options
*/
@Composable
internal fun AlertDialogWithList(
internal fun <T> AlertDialogWithList(
title: String,
listItems: Map<Int, Int> = emptyMap(),
selectedItemIndex: Int = 0,
selectAction: (Int) -> Unit = {},
listItems: Map<T, Int>,
selectedItemIndex: T,
selectAction: (T) -> Unit,
dismissAction: () -> Unit,
supportText: String? = null,
dismissButtonLabel: String = stringResource(R.string.cancel_label)