mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 16:25:27 +02:00
Fix initial states, navigation, loading logic and transitions
closes #92
This commit is contained in:
parent
1279a8acad
commit
f3ba0bd06a
@ -44,7 +44,7 @@ internal class MainActivity : AppCompatActivity() {
|
|||||||
val prefs = userPrefsRepository.appPrefs
|
val prefs = userPrefsRepository.appPrefs
|
||||||
.collectAsStateWithLifecycle(null).value
|
.collectAsStateWithLifecycle(null).value
|
||||||
|
|
||||||
if (prefs != null) UnittoApp(prefs)
|
UnittoApp(prefs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,23 +53,14 @@ import com.sadellie.unitto.core.ui.theme.TypographySystem
|
|||||||
import com.sadellie.unitto.core.ui.theme.TypographyUnitto
|
import com.sadellie.unitto.core.ui.theme.TypographyUnitto
|
||||||
import com.sadellie.unitto.data.userprefs.AppPreferences
|
import com.sadellie.unitto.data.userprefs.AppPreferences
|
||||||
import io.github.sadellie.themmo.Themmo
|
import io.github.sadellie.themmo.Themmo
|
||||||
import io.github.sadellie.themmo.rememberThemmoController
|
import io.github.sadellie.themmo.ThemmoController
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
internal fun UnittoApp(prefs: AppPreferences) {
|
internal fun UnittoApp(prefs: AppPreferences?) {
|
||||||
|
|
||||||
val mContext = LocalContext.current
|
val mContext = LocalContext.current
|
||||||
val themmoController = rememberThemmoController(
|
|
||||||
lightColorScheme = LightThemeColors,
|
|
||||||
darkColorScheme = DarkThemeColors,
|
|
||||||
themingMode = prefs.themingMode,
|
|
||||||
dynamicThemeEnabled = prefs.enableDynamicTheme,
|
|
||||||
amoledThemeEnabled = prefs.enableAmoledTheme,
|
|
||||||
customColor = prefs.customColor,
|
|
||||||
monetMode = prefs.monetMode
|
|
||||||
)
|
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val sysUiController = rememberSystemUiController()
|
val sysUiController = rememberSystemUiController()
|
||||||
|
|
||||||
@ -97,66 +88,80 @@ internal fun UnittoApp(prefs: AppPreferences) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Themmo(
|
if (prefs != null) {
|
||||||
themmoController = themmoController,
|
val themmoController = remember(prefs) {
|
||||||
typography = if (prefs.systemFont) TypographySystem else TypographyUnitto,
|
ThemmoController(
|
||||||
animationSpec = tween(250)
|
lightColorScheme = LightThemeColors,
|
||||||
) {
|
darkColorScheme = DarkThemeColors,
|
||||||
val backgroundColor = MaterialTheme.colorScheme.background
|
themingMode = prefs.themingMode,
|
||||||
val useDarkIcons by remember(backgroundColor) {
|
dynamicThemeEnabled = prefs.enableDynamicTheme,
|
||||||
mutableStateOf(backgroundColor.luminance() > 0.5f)
|
amoledThemeEnabled = prefs.enableAmoledTheme,
|
||||||
|
customColor = prefs.customColor,
|
||||||
|
monetMode = prefs.monetMode
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
UnittoModalNavigationDrawer(
|
Themmo(
|
||||||
drawer = {
|
themmoController = themmoController,
|
||||||
UnittoDrawerSheet(
|
typography = if (prefs.systemFont) TypographySystem else TypographyUnitto,
|
||||||
modifier = Modifier,
|
animationSpec = tween(250)
|
||||||
tabs = tabs,
|
) {
|
||||||
currentDestination = navBackStackEntry?.destination?.route
|
val backgroundColor = MaterialTheme.colorScheme.background
|
||||||
) { destination ->
|
val useDarkIcons by remember(backgroundColor) {
|
||||||
drawerScope.launch { drawerState.close() }
|
mutableStateOf(backgroundColor.luminance() > 0.5f)
|
||||||
|
|
||||||
navController.navigate(destination.graph) {
|
|
||||||
popUpTo(navController.graph.findStartDestination().id) {
|
|
||||||
saveState = true
|
|
||||||
}
|
|
||||||
launchSingleTop = true
|
|
||||||
restoreState = true
|
|
||||||
}
|
|
||||||
|
|
||||||
shortcutsScope.launch {
|
|
||||||
destination.shortcut?.let { shortcut: Shortcut ->
|
|
||||||
mContext.pushDynamicShortcut(
|
|
||||||
destination.graph,
|
|
||||||
shortcut.shortcutShortLabel,
|
|
||||||
shortcut.shortcutLongLabel,
|
|
||||||
shortcut.shortcutDrawable
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
state = drawerState,
|
|
||||||
gesturesEnabled = gesturesEnabled,
|
|
||||||
scope = drawerScope,
|
|
||||||
content = {
|
|
||||||
UnittoNavigation(
|
|
||||||
navController = navController,
|
|
||||||
themmoController = it,
|
|
||||||
startDestination = prefs.startingScreen,
|
|
||||||
openDrawer = { drawerScope.launch { drawerState.open() } }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
BackHandler(drawerState.isOpen) {
|
UnittoModalNavigationDrawer(
|
||||||
drawerScope.launch { drawerState.close() }
|
drawer = {
|
||||||
}
|
UnittoDrawerSheet(
|
||||||
|
modifier = Modifier,
|
||||||
|
tabs = tabs,
|
||||||
|
currentDestination = navBackStackEntry?.destination?.route
|
||||||
|
) { destination ->
|
||||||
|
drawerScope.launch { drawerState.close() }
|
||||||
|
|
||||||
LaunchedEffect(useDarkIcons) {
|
navController.navigate(destination.graph) {
|
||||||
sysUiController.setNavigationBarColor(Color.Transparent, useDarkIcons)
|
popUpTo(navController.graph.findStartDestination().id) {
|
||||||
sysUiController.setStatusBarColor(Color.Transparent, useDarkIcons)
|
saveState = true
|
||||||
|
}
|
||||||
|
launchSingleTop = true
|
||||||
|
restoreState = true
|
||||||
|
}
|
||||||
|
|
||||||
|
shortcutsScope.launch {
|
||||||
|
destination.shortcut?.let { shortcut: Shortcut ->
|
||||||
|
mContext.pushDynamicShortcut(
|
||||||
|
destination.graph,
|
||||||
|
shortcut.shortcutShortLabel,
|
||||||
|
shortcut.shortcutLongLabel,
|
||||||
|
shortcut.shortcutDrawable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
state = drawerState,
|
||||||
|
gesturesEnabled = gesturesEnabled,
|
||||||
|
scope = drawerScope,
|
||||||
|
content = {
|
||||||
|
UnittoNavigation(
|
||||||
|
navController = navController,
|
||||||
|
themmoController = it,
|
||||||
|
startDestination = prefs.startingScreen,
|
||||||
|
openDrawer = { drawerScope.launch { drawerState.open() } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
LaunchedEffect(useDarkIcons) {
|
||||||
|
sysUiController.setNavigationBarColor(Color.Transparent, useDarkIcons)
|
||||||
|
sysUiController.setStatusBarColor(Color.Transparent, useDarkIcons)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BackHandler(drawerState.isOpen) {
|
||||||
|
drawerScope.launch { drawerState.close() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,14 @@ import androidx.compose.animation.AnimatedContentScope
|
|||||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||||
import androidx.compose.animation.EnterTransition
|
import androidx.compose.animation.EnterTransition
|
||||||
import androidx.compose.animation.ExitTransition
|
import androidx.compose.animation.ExitTransition
|
||||||
|
import androidx.compose.animation.core.FiniteAnimationSpec
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.slideInHorizontally
|
||||||
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.navigation.NamedNavArgument
|
import androidx.navigation.NamedNavArgument
|
||||||
import androidx.navigation.NavBackStackEntry
|
import androidx.navigation.NavBackStackEntry
|
||||||
import androidx.navigation.NavDeepLink
|
import androidx.navigation.NavDeepLink
|
||||||
@ -40,16 +45,16 @@ fun NavGraphBuilder.unittoComposable(
|
|||||||
arguments: List<NamedNavArgument> = emptyList(),
|
arguments: List<NamedNavArgument> = emptyList(),
|
||||||
deepLinks: List<NavDeepLink> = emptyList(),
|
deepLinks: List<NavDeepLink> = emptyList(),
|
||||||
enterTransition: (@JvmSuppressWildcards
|
enterTransition: (@JvmSuppressWildcards
|
||||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = { fadeIn() },
|
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? = { unittoFadeIn() },
|
||||||
exitTransition: (@JvmSuppressWildcards
|
exitTransition: (@JvmSuppressWildcards
|
||||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = { fadeOut() },
|
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? = { unittoFadeOut() },
|
||||||
popEnterTransition: (@JvmSuppressWildcards
|
popEnterTransition: (@JvmSuppressWildcards
|
||||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? =
|
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition?)? =
|
||||||
enterTransition,
|
enterTransition,
|
||||||
popExitTransition: (@JvmSuppressWildcards
|
popExitTransition: (@JvmSuppressWildcards
|
||||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? =
|
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?)? =
|
||||||
exitTransition,
|
exitTransition,
|
||||||
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit
|
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
|
||||||
): Unit = composable(
|
): Unit = composable(
|
||||||
route = route,
|
route = route,
|
||||||
arguments = arguments,
|
arguments = arguments,
|
||||||
@ -61,6 +66,40 @@ fun NavGraphBuilder.unittoComposable(
|
|||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun NavGraphBuilder.unittoStackedComposable(
|
||||||
|
route: String,
|
||||||
|
arguments: List<NamedNavArgument> = emptyList(),
|
||||||
|
deepLinks: List<NavDeepLink> = emptyList(),
|
||||||
|
content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit,
|
||||||
|
) {
|
||||||
|
composable(
|
||||||
|
route = route,
|
||||||
|
arguments = arguments,
|
||||||
|
deepLinks = deepLinks,
|
||||||
|
enterTransition = {
|
||||||
|
slideInHorizontally(
|
||||||
|
animationSpec = unittoEnterTween(),
|
||||||
|
initialOffsetX = { (it * 0.2f).toInt() }) + unittoFadeIn()
|
||||||
|
},
|
||||||
|
exitTransition = {
|
||||||
|
slideOutHorizontally(
|
||||||
|
animationSpec = unittoExitTween(),
|
||||||
|
targetOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeOut()
|
||||||
|
},
|
||||||
|
popEnterTransition = {
|
||||||
|
slideInHorizontally(
|
||||||
|
animationSpec = unittoEnterTween(),
|
||||||
|
initialOffsetX = { -(it * 0.2f).toInt() }) + unittoFadeIn()
|
||||||
|
},
|
||||||
|
popExitTransition = {
|
||||||
|
slideOutHorizontally(
|
||||||
|
animationSpec = unittoExitTween(),
|
||||||
|
targetOffsetX = { (it * 0.2f).toInt() }) + unittoFadeOut()
|
||||||
|
},
|
||||||
|
content = content,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see NavGraphBuilder.navigation
|
* @see NavGraphBuilder.navigation
|
||||||
*/
|
*/
|
||||||
@ -79,7 +118,7 @@ fun NavGraphBuilder.unittoNavigation(
|
|||||||
popExitTransition: (
|
popExitTransition: (
|
||||||
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition?
|
||||||
)? = exitTransition,
|
)? = exitTransition,
|
||||||
builder: NavGraphBuilder.() -> Unit
|
builder: NavGraphBuilder.() -> Unit,
|
||||||
): Unit = navigation(
|
): Unit = navigation(
|
||||||
startDestination = startDestination,
|
startDestination = startDestination,
|
||||||
route = route,
|
route = route,
|
||||||
@ -91,3 +130,11 @@ fun NavGraphBuilder.unittoNavigation(
|
|||||||
popExitTransition = popExitTransition,
|
popExitTransition = popExitTransition,
|
||||||
builder = builder
|
builder = builder
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private const val ENTER_DURATION = 350
|
||||||
|
private const val EXIT_DURATION = 200
|
||||||
|
|
||||||
|
private fun unittoFadeIn(): EnterTransition = fadeIn(tween(ENTER_DURATION))
|
||||||
|
private fun unittoFadeOut(): ExitTransition = fadeOut(tween(EXIT_DURATION))
|
||||||
|
private fun unittoEnterTween(): FiniteAnimationSpec<IntOffset> = tween(ENTER_DURATION)
|
||||||
|
private fun unittoExitTween(): FiniteAnimationSpec<IntOffset> = tween(EXIT_DURATION)
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.common
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UnittoEmptyScreen() {
|
||||||
|
Spacer(modifier = Modifier.fillMaxSize())
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.userprefs
|
||||||
|
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
||||||
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
|
import io.github.sadellie.themmo.MonetMode
|
||||||
|
import io.github.sadellie.themmo.ThemingMode
|
||||||
|
|
||||||
|
data class AppPreferences(
|
||||||
|
val themingMode: ThemingMode,
|
||||||
|
val enableDynamicTheme: Boolean,
|
||||||
|
val enableAmoledTheme: Boolean,
|
||||||
|
val customColor: Color,
|
||||||
|
val monetMode: MonetMode,
|
||||||
|
val startingScreen: String,
|
||||||
|
val enableToolsExperiment: Boolean,
|
||||||
|
val systemFont: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class GeneralPreferences(
|
||||||
|
val enableVibrations: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CalculatorPreferences(
|
||||||
|
val radianMode: Boolean,
|
||||||
|
val enableVibrations: Boolean,
|
||||||
|
val separator: Int,
|
||||||
|
val middleZero: Boolean,
|
||||||
|
val partialHistoryView: Boolean,
|
||||||
|
val precision: Int,
|
||||||
|
val outputFormat: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ConverterPreferences(
|
||||||
|
val enableVibrations: Boolean,
|
||||||
|
val separator: Int,
|
||||||
|
val middleZero: Boolean,
|
||||||
|
val precision: Int,
|
||||||
|
val outputFormat: Int,
|
||||||
|
val unitConverterFormatTime: Boolean,
|
||||||
|
val unitConverterSorting: UnitsListSorting,
|
||||||
|
val shownUnitGroups: List<UnitGroup>,
|
||||||
|
val unitConverterFavoritesOnly: Boolean,
|
||||||
|
val enableToolsExperiment: Boolean,
|
||||||
|
val latestLeftSideUnit: String,
|
||||||
|
val latestRightSideUnit: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class DisplayPreferences(
|
||||||
|
val systemFont: Boolean,
|
||||||
|
val middleZero: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FormattingPreferences(
|
||||||
|
val digitsPrecision: Int,
|
||||||
|
val separator: Int,
|
||||||
|
val outputFormat: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class UnitGroupsPreferences(
|
||||||
|
val shownUnitGroups: List<UnitGroup> = ALL_UNIT_GROUPS,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AddSubtractPreferences(
|
||||||
|
val separator: Int,
|
||||||
|
val enableVibrations: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AboutPreferences(
|
||||||
|
val enableToolsExperiment: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class StartingScreenPreferences(
|
||||||
|
val startingScreen: String,
|
||||||
|
)
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.userprefs
|
||||||
|
|
||||||
|
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.intPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.longPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
|
|
||||||
|
internal object PrefsKeys {
|
||||||
|
val THEMING_MODE = stringPreferencesKey("THEMING_MODE_PREF_KEY")
|
||||||
|
val ENABLE_DYNAMIC_THEME = booleanPreferencesKey("ENABLE_DYNAMIC_THEME_PREF_KEY")
|
||||||
|
val ENABLE_AMOLED_THEME = booleanPreferencesKey("ENABLE_AMOLED_THEME_PREF_KEY")
|
||||||
|
val CUSTOM_COLOR = longPreferencesKey("CUSTOM_COLOR_PREF_KEY")
|
||||||
|
val MONET_MODE = stringPreferencesKey("MONET_MODE_PREF_KEY")
|
||||||
|
val DIGITS_PRECISION = intPreferencesKey("DIGITS_PRECISION_PREF_KEY")
|
||||||
|
val SEPARATOR = intPreferencesKey("SEPARATOR_PREF_KEY")
|
||||||
|
val OUTPUT_FORMAT = intPreferencesKey("OUTPUT_FORMAT_PREF_KEY")
|
||||||
|
val LATEST_LEFT_SIDE = stringPreferencesKey("LATEST_LEFT_SIDE_PREF_KEY")
|
||||||
|
val LATEST_RIGHT_SIDE = stringPreferencesKey("LATEST_RIGHT_SIDE_PREF_KEY")
|
||||||
|
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 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 MIDDLE_ZERO = booleanPreferencesKey("MIDDLE_ZERO_PREF_KEY")
|
||||||
|
val SYSTEM_FONT = booleanPreferencesKey("SYSTEM_FONT_PREF_KEY")
|
||||||
|
val PARTIAL_HISTORY_VIEW = booleanPreferencesKey("PARTIAL_HISTORY_VIEW_PREF_KEY")
|
||||||
|
}
|
@ -21,12 +21,8 @@ package com.sadellie.unitto.data.userprefs
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.datastore.core.DataStore
|
import androidx.datastore.core.DataStore
|
||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.emptyPreferences
|
import androidx.datastore.preferences.core.emptyPreferences
|
||||||
import androidx.datastore.preferences.core.intPreferencesKey
|
|
||||||
import androidx.datastore.preferences.core.longPreferencesKey
|
|
||||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
|
||||||
import com.sadellie.unitto.core.base.OutputFormat
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.base.Separator
|
import com.sadellie.unitto.core.base.Separator
|
||||||
import com.sadellie.unitto.core.base.TopLevelDestinations
|
import com.sadellie.unitto.core.base.TopLevelDestinations
|
||||||
@ -43,214 +39,107 @@ import kotlinx.coroutines.flow.map
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private object PrefsKeys {
|
class UserPreferencesRepository @Inject constructor(
|
||||||
val THEMING_MODE = stringPreferencesKey("THEMING_MODE_PREF_KEY")
|
private val dataStore: DataStore<Preferences>,
|
||||||
val ENABLE_DYNAMIC_THEME = booleanPreferencesKey("ENABLE_DYNAMIC_THEME_PREF_KEY")
|
) {
|
||||||
val ENABLE_AMOLED_THEME = booleanPreferencesKey("ENABLE_AMOLED_THEME_PREF_KEY")
|
|
||||||
val CUSTOM_COLOR = longPreferencesKey("CUSTOM_COLOR_PREF_KEY")
|
|
||||||
val MONET_MODE = stringPreferencesKey("MONET_MODE_PREF_KEY")
|
|
||||||
val DIGITS_PRECISION = intPreferencesKey("DIGITS_PRECISION_PREF_KEY")
|
|
||||||
val SEPARATOR = intPreferencesKey("SEPARATOR_PREF_KEY")
|
|
||||||
val OUTPUT_FORMAT = intPreferencesKey("OUTPUT_FORMAT_PREF_KEY")
|
|
||||||
val LATEST_LEFT_SIDE = stringPreferencesKey("LATEST_LEFT_SIDE_PREF_KEY")
|
|
||||||
val LATEST_RIGHT_SIDE = stringPreferencesKey("LATEST_RIGHT_SIDE_PREF_KEY")
|
|
||||||
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 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 MIDDLE_ZERO = booleanPreferencesKey("MIDDLE_ZERO_PREF_KEY")
|
|
||||||
val SYSTEM_FONT = booleanPreferencesKey("SYSTEM_FONT_PREF_KEY")
|
|
||||||
val PARTIAL_HISTORY_VIEW = booleanPreferencesKey("PARTIAL_HISTORY_VIEW_PREF_KEY")
|
|
||||||
}
|
|
||||||
|
|
||||||
data class AppPreferences(
|
|
||||||
val themingMode: ThemingMode = ThemingMode.AUTO,
|
|
||||||
val enableDynamicTheme: Boolean = true,
|
|
||||||
val enableAmoledTheme: Boolean = false,
|
|
||||||
val customColor: Color = Color.Unspecified,
|
|
||||||
val monetMode: MonetMode = MonetMode.TonalSpot,
|
|
||||||
val startingScreen: String = TopLevelDestinations.Calculator.graph,
|
|
||||||
val enableToolsExperiment: Boolean = false,
|
|
||||||
val systemFont: Boolean = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class GeneralPreferences(
|
|
||||||
val enableVibrations: Boolean = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class CalculatorPreferences(
|
|
||||||
val radianMode: Boolean = true,
|
|
||||||
val enableVibrations: Boolean = true,
|
|
||||||
val separator: Int = Separator.SPACE,
|
|
||||||
val middleZero: Boolean = false,
|
|
||||||
val partialHistoryView: Boolean = true,
|
|
||||||
val precision: Int = 3,
|
|
||||||
val outputFormat: Int = OutputFormat.PLAIN,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ConverterPreferences(
|
|
||||||
val enableVibrations: Boolean = true,
|
|
||||||
val separator: Int = Separator.SPACE,
|
|
||||||
val middleZero: Boolean = false,
|
|
||||||
val precision: Int = 3,
|
|
||||||
val outputFormat: Int = OutputFormat.PLAIN,
|
|
||||||
val unitConverterFormatTime: Boolean = false,
|
|
||||||
val unitConverterSorting: UnitsListSorting = UnitsListSorting.USAGE,
|
|
||||||
val shownUnitGroups: List<UnitGroup> = ALL_UNIT_GROUPS,
|
|
||||||
val unitConverterFavoritesOnly: Boolean = false,
|
|
||||||
val enableToolsExperiment: Boolean = false,
|
|
||||||
val latestLeftSideUnit: String = MyUnitIDS.kilometer,
|
|
||||||
val latestRightSideUnit: String = MyUnitIDS.mile,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class DisplayPreferences(
|
|
||||||
val systemFont: Boolean = false,
|
|
||||||
val middleZero: Boolean = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class FormattingPreferences(
|
|
||||||
val digitsPrecision: Int = 3,
|
|
||||||
val separator: Int = Separator.SPACE,
|
|
||||||
val outputFormat: Int = OutputFormat.PLAIN,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class UnitGroupsPreferences(
|
|
||||||
val shownUnitGroups: List<UnitGroup> = ALL_UNIT_GROUPS,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class AddSubtractPreferences(
|
|
||||||
val separator: Int = Separator.SPACE,
|
|
||||||
val enableVibrations: Boolean = true,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class AboutPreferences(
|
|
||||||
val enableToolsExperiment: Boolean = false,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class StartingScreenPreferences(
|
|
||||||
val startingScreen: String = TopLevelDestinations.Calculator.graph,
|
|
||||||
)
|
|
||||||
|
|
||||||
class UserPreferencesRepository @Inject constructor(private val dataStore: DataStore<Preferences>) {
|
|
||||||
private val data = dataStore.data
|
private val data = dataStore.data
|
||||||
.catch { if (it is IOException) emit(emptyPreferences()) else throw it }
|
.catch { if (it is IOException) emit(emptyPreferences()) else throw it }
|
||||||
|
|
||||||
val appPrefs: Flow<AppPreferences> = data
|
val appPrefs: Flow<AppPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
AppPreferences(
|
AppPreferences(
|
||||||
themingMode = preferences[PrefsKeys.THEMING_MODE]?.letTryOrNull {
|
themingMode = preferences.getThemingMode(),
|
||||||
ThemingMode.valueOf(it)
|
enableDynamicTheme = preferences.getEnableDynamicTheme(),
|
||||||
}
|
enableAmoledTheme = preferences.getEnableAmoledTheme(),
|
||||||
?: ThemingMode.AUTO,
|
customColor = preferences.getCustomColor(),
|
||||||
enableDynamicTheme = preferences[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: true,
|
monetMode = preferences.getMonetMode(),
|
||||||
enableAmoledTheme = preferences[PrefsKeys.ENABLE_AMOLED_THEME] ?: false,
|
startingScreen = preferences.getStartingScreen(),
|
||||||
customColor = preferences[PrefsKeys.CUSTOM_COLOR]?.letTryOrNull { Color(it.toULong()) }
|
enableToolsExperiment = preferences.getEnableToolsExperiment(),
|
||||||
?: Color.Unspecified,
|
systemFont = preferences.getSystemFont()
|
||||||
monetMode = preferences[PrefsKeys.MONET_MODE]?.letTryOrNull { MonetMode.valueOf(it) }
|
|
||||||
?: MonetMode.TonalSpot,
|
|
||||||
startingScreen = preferences[PrefsKeys.STARTING_SCREEN]
|
|
||||||
?: TopLevelDestinations.Calculator.graph,
|
|
||||||
enableToolsExperiment = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false,
|
|
||||||
systemFont = preferences[PrefsKeys.SYSTEM_FONT] ?: false
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val generalPrefs: Flow<GeneralPreferences> = data
|
val generalPrefs: Flow<GeneralPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
GeneralPreferences(
|
GeneralPreferences(
|
||||||
enableVibrations = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true,
|
enableVibrations = preferences.getEnableVibrations(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val calculatorPrefs: Flow<CalculatorPreferences> = data
|
val calculatorPrefs: Flow<CalculatorPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
CalculatorPreferences(
|
CalculatorPreferences(
|
||||||
radianMode = preferences[PrefsKeys.RADIAN_MODE] ?: true,
|
radianMode = preferences.getRadianMode(),
|
||||||
enableVibrations = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true,
|
enableVibrations = preferences.getEnableVibrations(),
|
||||||
separator = preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACE,
|
separator = preferences.getSeparator(),
|
||||||
middleZero = preferences[PrefsKeys.MIDDLE_ZERO] ?: false,
|
middleZero = preferences.getMiddleZero(),
|
||||||
partialHistoryView = preferences[PrefsKeys.PARTIAL_HISTORY_VIEW] ?: true,
|
partialHistoryView = preferences.getPartialHistoryView(),
|
||||||
precision = preferences[PrefsKeys.DIGITS_PRECISION] ?: 3,
|
precision = preferences.getDigitsPrecision(),
|
||||||
outputFormat = preferences[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN
|
outputFormat = preferences.getOutputFormat()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val converterPrefs: Flow<ConverterPreferences> = data
|
val converterPrefs: Flow<ConverterPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
ConverterPreferences(
|
ConverterPreferences(
|
||||||
enableVibrations = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true,
|
enableVibrations = preferences.getEnableVibrations(),
|
||||||
separator = preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACE,
|
separator = preferences.getSeparator(),
|
||||||
middleZero = preferences[PrefsKeys.MIDDLE_ZERO] ?: false,
|
middleZero = preferences.getMiddleZero(),
|
||||||
precision = preferences[PrefsKeys.DIGITS_PRECISION] ?: 3,
|
precision = preferences.getDigitsPrecision(),
|
||||||
outputFormat = preferences[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN,
|
outputFormat = preferences.getOutputFormat(),
|
||||||
unitConverterFormatTime = preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME]
|
unitConverterFormatTime = preferences.getUnitConverterFormatTime(),
|
||||||
?: false,
|
unitConverterSorting = preferences.getUnitConverterSorting(),
|
||||||
unitConverterSorting = preferences[PrefsKeys.UNIT_CONVERTER_SORTING]
|
shownUnitGroups = preferences.getShownUnitGroups(),
|
||||||
?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE,
|
unitConverterFavoritesOnly = preferences.getUnitConverterFavoritesOnly(),
|
||||||
shownUnitGroups = preferences[PrefsKeys.SHOWN_UNIT_GROUPS]?.letTryOrNull { list ->
|
enableToolsExperiment = preferences.getEnableToolsExperiment(),
|
||||||
list.ifEmpty { return@letTryOrNull listOf() }.split(",")
|
latestLeftSideUnit = preferences.getLatestLeftSide(),
|
||||||
.map { UnitGroup.valueOf(it) }
|
latestRightSideUnit = preferences.getLatestRightSide(),
|
||||||
} ?: ALL_UNIT_GROUPS,
|
|
||||||
unitConverterFavoritesOnly = preferences[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY]
|
|
||||||
?: false,
|
|
||||||
enableToolsExperiment = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false,
|
|
||||||
latestLeftSideUnit = preferences[PrefsKeys.LATEST_LEFT_SIDE] ?: MyUnitIDS.kilometer,
|
|
||||||
latestRightSideUnit = preferences[PrefsKeys.LATEST_RIGHT_SIDE] ?: MyUnitIDS.mile,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val displayPrefs: Flow<DisplayPreferences> = data
|
val displayPrefs: Flow<DisplayPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
DisplayPreferences(
|
DisplayPreferences(
|
||||||
systemFont = preferences[PrefsKeys.SYSTEM_FONT] ?: false,
|
systemFont = preferences.getSystemFont(),
|
||||||
middleZero = preferences[PrefsKeys.MIDDLE_ZERO] ?: false,
|
middleZero = preferences.getMiddleZero(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val formattingPrefs: Flow<FormattingPreferences> = data
|
val formattingPrefs: Flow<FormattingPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
FormattingPreferences(
|
FormattingPreferences(
|
||||||
digitsPrecision = preferences[PrefsKeys.DIGITS_PRECISION] ?: 3,
|
digitsPrecision = preferences.getDigitsPrecision(),
|
||||||
separator = preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACE,
|
separator = preferences.getSeparator(),
|
||||||
outputFormat = preferences[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN,
|
outputFormat = preferences.getOutputFormat(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val unitGroupsPrefs: Flow<UnitGroupsPreferences> = data
|
val unitGroupsPrefs: Flow<UnitGroupsPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
UnitGroupsPreferences(
|
UnitGroupsPreferences(
|
||||||
shownUnitGroups = preferences[PrefsKeys.SHOWN_UNIT_GROUPS]?.letTryOrNull { list ->
|
shownUnitGroups = preferences.getShownUnitGroups(),
|
||||||
list.ifEmpty { return@letTryOrNull listOf() }.split(",")
|
|
||||||
.map { UnitGroup.valueOf(it) }
|
|
||||||
} ?: ALL_UNIT_GROUPS,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val addSubtractPrefs: Flow<AddSubtractPreferences> = data
|
val addSubtractPrefs: Flow<AddSubtractPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
AddSubtractPreferences(
|
AddSubtractPreferences(
|
||||||
separator = preferences[PrefsKeys.SEPARATOR] ?: Separator.SPACE,
|
separator = preferences.getSeparator(),
|
||||||
enableVibrations = preferences[PrefsKeys.ENABLE_VIBRATIONS] ?: true,
|
enableVibrations = preferences.getEnableVibrations(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val aboutPrefs: Flow<AboutPreferences> = data
|
val aboutPrefs: Flow<AboutPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
AboutPreferences(
|
AboutPreferences(
|
||||||
enableToolsExperiment = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false
|
enableToolsExperiment = preferences.getEnableToolsExperiment()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val startingScreenPrefs: Flow<StartingScreenPreferences> = data
|
val startingScreenPrefs: Flow<StartingScreenPreferences> = data
|
||||||
.map { preferences ->
|
.map { preferences ->
|
||||||
StartingScreenPreferences(
|
StartingScreenPreferences(
|
||||||
startingScreen = preferences[PrefsKeys.STARTING_SCREEN]
|
startingScreen = preferences.getStartingScreen(),
|
||||||
?: TopLevelDestinations.Calculator.graph,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,10 +263,104 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
preferences[PrefsKeys.PARTIAL_HISTORY_VIEW] = enabled
|
preferences[PrefsKeys.PARTIAL_HISTORY_VIEW] = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private inline fun <T, R> T.letTryOrNull(block: (T) -> R): R? = try {
|
|
||||||
this?.let(block)
|
private fun Preferences.getEnableDynamicTheme(): Boolean {
|
||||||
} catch (e: Exception) {
|
return this[PrefsKeys.ENABLE_DYNAMIC_THEME] ?: true
|
||||||
null
|
}
|
||||||
}
|
|
||||||
|
private fun Preferences.getThemingMode(): ThemingMode {
|
||||||
|
return this[PrefsKeys.THEMING_MODE]
|
||||||
|
?.letTryOrNull { ThemingMode.valueOf(it) }
|
||||||
|
?: ThemingMode.AUTO
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getEnableAmoledTheme(): Boolean {
|
||||||
|
return this[PrefsKeys.ENABLE_AMOLED_THEME] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getCustomColor(): Color {
|
||||||
|
return this[PrefsKeys.CUSTOM_COLOR]?.letTryOrNull { Color(it.toULong()) }
|
||||||
|
?: Color.Unspecified
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getMonetMode(): MonetMode {
|
||||||
|
return this[PrefsKeys.MONET_MODE]?.letTryOrNull { MonetMode.valueOf(it) }
|
||||||
|
?: MonetMode.TonalSpot
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getStartingScreen(): String {
|
||||||
|
return this[PrefsKeys.STARTING_SCREEN]
|
||||||
|
?: TopLevelDestinations.Calculator.graph
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getEnableToolsExperiment(): Boolean {
|
||||||
|
return this[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getSystemFont(): Boolean {
|
||||||
|
return this[PrefsKeys.SYSTEM_FONT] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getEnableVibrations(): Boolean {
|
||||||
|
return this[PrefsKeys.ENABLE_VIBRATIONS] ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getRadianMode(): Boolean {
|
||||||
|
return this[PrefsKeys.RADIAN_MODE] ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getSeparator(): Int {
|
||||||
|
return this[PrefsKeys.SEPARATOR] ?: Separator.SPACE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getMiddleZero(): Boolean {
|
||||||
|
return this[PrefsKeys.MIDDLE_ZERO] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getPartialHistoryView(): Boolean {
|
||||||
|
return this[PrefsKeys.PARTIAL_HISTORY_VIEW] ?: true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getDigitsPrecision(): Int {
|
||||||
|
return this[PrefsKeys.DIGITS_PRECISION] ?: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getOutputFormat(): Int {
|
||||||
|
return this[PrefsKeys.OUTPUT_FORMAT] ?: OutputFormat.PLAIN
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getUnitConverterFormatTime(): Boolean {
|
||||||
|
return this[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getUnitConverterSorting(): UnitsListSorting {
|
||||||
|
return this[PrefsKeys.UNIT_CONVERTER_SORTING]
|
||||||
|
?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getShownUnitGroups(): List<UnitGroup> {
|
||||||
|
return this[PrefsKeys.SHOWN_UNIT_GROUPS]?.letTryOrNull { list ->
|
||||||
|
list.ifEmpty { return@letTryOrNull listOf() }.split(",")
|
||||||
|
.map { UnitGroup.valueOf(it) }
|
||||||
|
} ?: ALL_UNIT_GROUPS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getUnitConverterFavoritesOnly(): Boolean {
|
||||||
|
return this[PrefsKeys.UNIT_CONVERTER_FAVORITES_ONLY]
|
||||||
|
?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getLatestLeftSide(): String {
|
||||||
|
return this[PrefsKeys.LATEST_LEFT_SIDE] ?: MyUnitIDS.kilometer
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Preferences.getLatestRightSide(): String {
|
||||||
|
return this[PrefsKeys.LATEST_RIGHT_SIDE] ?: MyUnitIDS.mile
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <T, R> T.letTryOrNull(block: (T) -> R): R? = try {
|
||||||
|
this?.let(block)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
}
|
}
|
||||||
|
@ -18,24 +18,17 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.feature.calculator
|
package com.sadellie.unitto.feature.calculator
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.gestures.AnchoredDraggableState
|
import androidx.compose.foundation.gestures.AnchoredDraggableState
|
||||||
import androidx.compose.foundation.gestures.DraggableAnchors
|
import androidx.compose.foundation.gestures.DraggableAnchors
|
||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.gestures.anchoredDraggable
|
import androidx.compose.foundation.gestures.anchoredDraggable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.offset
|
import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.sizeIn
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
@ -53,9 +46,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@ -70,11 +61,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.MenuButton
|
import com.sadellie.unitto.core.ui.common.MenuButton
|
||||||
import com.sadellie.unitto.core.ui.common.SettingsButton
|
import com.sadellie.unitto.core.ui.common.SettingsButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithTopBar
|
import com.sadellie.unitto.core.ui.common.UnittoScreenWithTopBar
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField
|
|
||||||
import com.sadellie.unitto.data.model.HistoryItem
|
import com.sadellie.unitto.data.model.HistoryItem
|
||||||
import com.sadellie.unitto.feature.calculator.components.CalculatorKeyboard
|
import com.sadellie.unitto.feature.calculator.components.CalculatorKeyboard
|
||||||
import com.sadellie.unitto.feature.calculator.components.CalculatorKeyboardLoading
|
|
||||||
import com.sadellie.unitto.feature.calculator.components.HistoryItemHeight
|
import com.sadellie.unitto.feature.calculator.components.HistoryItemHeight
|
||||||
import com.sadellie.unitto.feature.calculator.components.HistoryList
|
import com.sadellie.unitto.feature.calculator.components.HistoryList
|
||||||
import com.sadellie.unitto.feature.calculator.components.TextBox
|
import com.sadellie.unitto.feature.calculator.components.TextBox
|
||||||
@ -117,10 +107,7 @@ internal fun CalculatorScreen(
|
|||||||
clearHistory: () -> Unit
|
clearHistory: () -> Unit
|
||||||
) {
|
) {
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is CalculatorUIState.Loading -> Loading(
|
is CalculatorUIState.Loading -> UnittoEmptyScreen()
|
||||||
navigateToMenu = navigateToMenu,
|
|
||||||
navigateToSettings = navigateToSettings,
|
|
||||||
)
|
|
||||||
is CalculatorUIState.Ready -> Ready(
|
is CalculatorUIState.Ready -> Ready(
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
navigateToMenu = navigateToMenu,
|
navigateToMenu = navigateToMenu,
|
||||||
@ -314,81 +301,6 @@ private fun Ready(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun Loading(
|
|
||||||
navigateToMenu: () -> Unit,
|
|
||||||
navigateToSettings: () -> Unit,
|
|
||||||
) {
|
|
||||||
UnittoScreenWithTopBar(
|
|
||||||
title = { Text(stringResource(R.string.calculator_title)) },
|
|
||||||
navigationIcon = { MenuButton { navigateToMenu() } },
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors(MaterialTheme.colorScheme.surfaceVariant),
|
|
||||||
actions = { SettingsButton(navigateToSettings) }
|
|
||||||
) { paddingValues ->
|
|
||||||
BoxWithConstraints(
|
|
||||||
modifier = Modifier.padding(paddingValues),
|
|
||||||
) {
|
|
||||||
// Input
|
|
||||||
Column(
|
|
||||||
Modifier
|
|
||||||
.height(maxHeight * 0.25f)
|
|
||||||
.background(
|
|
||||||
MaterialTheme.colorScheme.surfaceVariant,
|
|
||||||
RoundedCornerShape(
|
|
||||||
topStartPercent = 0, topEndPercent = 0,
|
|
||||||
bottomStartPercent = 20, bottomEndPercent = 20
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.padding(top = 12.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
UnformattedTextField(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(2f)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 8.dp),
|
|
||||||
value = TextFieldValue(),
|
|
||||||
minRatio = 0.5f,
|
|
||||||
onCursorChange = {},
|
|
||||||
)
|
|
||||||
if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
|
||||||
UnformattedTextField(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 8.dp),
|
|
||||||
value = TextFieldValue(),
|
|
||||||
minRatio = 1f,
|
|
||||||
onCursorChange = {},
|
|
||||||
readOnly = true,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Handle
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
.background(
|
|
||||||
MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
RoundedCornerShape(100)
|
|
||||||
)
|
|
||||||
.sizeIn(24.dp, 4.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keyboard
|
|
||||||
CalculatorKeyboardLoading(
|
|
||||||
modifier = Modifier
|
|
||||||
.semantics { testTag = "loading" }
|
|
||||||
.offset(y = maxHeight * 0.25f)
|
|
||||||
.height(maxHeight * 0.75f)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 8.dp, vertical = 4.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(widthDp = 432, heightDp = 1008, device = "spec:parent=pixel_5,orientation=portrait")
|
@Preview(widthDp = 432, heightDp = 1008, device = "spec:parent=pixel_5,orientation=portrait")
|
||||||
@Preview(widthDp = 432, heightDp = 864, device = "spec:parent=pixel_5,orientation=portrait")
|
@Preview(widthDp = 432, heightDp = 864, device = "spec:parent=pixel_5,orientation=portrait")
|
||||||
@Preview(widthDp = 597, heightDp = 1393, device = "spec:parent=pixel_5,orientation=portrait")
|
@Preview(widthDp = 597, heightDp = 1393, device = "spec:parent=pixel_5,orientation=portrait")
|
||||||
|
@ -22,6 +22,8 @@ import androidx.compose.ui.text.TextRange
|
|||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
|
import com.sadellie.unitto.core.base.Separator
|
||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.Token
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
||||||
@ -58,7 +60,15 @@ internal class CalculatorViewModel @Inject constructor(
|
|||||||
userPrefsRepository.calculatorPrefs.stateIn(
|
userPrefsRepository.calculatorPrefs.stateIn(
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
SharingStarted.WhileSubscribed(5000L),
|
SharingStarted.WhileSubscribed(5000L),
|
||||||
CalculatorPreferences()
|
CalculatorPreferences(
|
||||||
|
radianMode = false,
|
||||||
|
enableVibrations = false,
|
||||||
|
separator = Separator.SPACE,
|
||||||
|
middleZero = false,
|
||||||
|
partialHistoryView = true,
|
||||||
|
precision = 3,
|
||||||
|
outputFormat = OutputFormat.PLAIN
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val _input: MutableStateFlow<TextFieldValue> = MutableStateFlow(TextFieldValue())
|
private val _input: MutableStateFlow<TextFieldValue> = MutableStateFlow(TextFieldValue())
|
||||||
@ -79,7 +89,8 @@ internal class CalculatorViewModel @Inject constructor(
|
|||||||
middleZero = userPrefs.middleZero,
|
middleZero = userPrefs.middleZero,
|
||||||
partialHistoryView = userPrefs.partialHistoryView,
|
partialHistoryView = userPrefs.partialHistoryView,
|
||||||
)
|
)
|
||||||
}.stateIn(
|
}
|
||||||
|
.stateIn(
|
||||||
viewModelScope, SharingStarted.WhileSubscribed(5000L), CalculatorUIState.Loading
|
viewModelScope, SharingStarted.WhileSubscribed(5000L), CalculatorUIState.Loading
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import androidx.compose.animation.Crossfade
|
|||||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@ -35,7 +34,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ExpandMore
|
import androidx.compose.material.icons.filled.ExpandMore
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -50,11 +48,9 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.Token
|
||||||
import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
|
import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
|
||||||
import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional
|
import com.sadellie.unitto.core.ui.common.KeyboardButtonAdditional
|
||||||
@ -145,118 +141,6 @@ internal fun CalculatorKeyboard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun CalculatorKeyboardLoading(
|
|
||||||
modifier: Modifier
|
|
||||||
) {
|
|
||||||
if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
|
||||||
PortraitKeyboardLoading(modifier)
|
|
||||||
} else {
|
|
||||||
LandscapeKeyboardLoading(modifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun PortraitKeyboardLoading(
|
|
||||||
modifier: Modifier
|
|
||||||
) {
|
|
||||||
ColumnWithConstraints(
|
|
||||||
modifier = modifier
|
|
||||||
) { constraints ->
|
|
||||||
|
|
||||||
val additionalButtonHeight by remember {
|
|
||||||
mutableStateOf(constraints.maxHeight * 0.09f)
|
|
||||||
}
|
|
||||||
|
|
||||||
val spacerHeight by remember {
|
|
||||||
mutableStateOf(constraints.maxHeight * 0.025f)
|
|
||||||
}
|
|
||||||
|
|
||||||
val additionalRowSpacedBy by remember {
|
|
||||||
mutableStateOf(constraints.maxWidth * 0.03f)
|
|
||||||
}
|
|
||||||
|
|
||||||
val weightModifier = Modifier.weight(1f)
|
|
||||||
val additionalButtonModifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.height(additionalButtonHeight)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(additionalRowSpacedBy)
|
|
||||||
) {
|
|
||||||
// Additional buttons
|
|
||||||
Box(weightModifier) {
|
|
||||||
AdditionalButtonsPortrait(
|
|
||||||
modifier = additionalButtonModifier,
|
|
||||||
allowVibration = false,
|
|
||||||
addSymbol = {},
|
|
||||||
showAdditional = false,
|
|
||||||
radianMode = false,
|
|
||||||
toggleAngleMode = {},
|
|
||||||
toggleInvMode = {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.size(additionalButtonHeight),
|
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
// Expand/Collapse
|
|
||||||
IconButton(
|
|
||||||
onClick = { },
|
|
||||||
colors = IconButtonDefaults.iconButtonColors(containerColor = MaterialTheme.colorScheme.inverseOnSurface)
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.ExpandMore, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = weightModifier
|
|
||||||
.clip(RoundedCornerShape(32.dp))
|
|
||||||
.background(MaterialTheme.colorScheme.inverseOnSurface)
|
|
||||||
.fillMaxSize()
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(spacerHeight))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun LandscapeKeyboardLoading(
|
|
||||||
modifier: Modifier
|
|
||||||
) {
|
|
||||||
RowWithConstraints(modifier) { constraints ->
|
|
||||||
val buttonModifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.weight(1f)
|
|
||||||
.padding(constraints.maxWidth * 0.005f, constraints.maxHeight * 0.02f)
|
|
||||||
|
|
||||||
AdditionalButtonsLandscape(
|
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
buttonModifier = buttonModifier,
|
|
||||||
allowVibration = false,
|
|
||||||
radianMode = false,
|
|
||||||
addSymbol = {},
|
|
||||||
toggleAngleMode = {},
|
|
||||||
toggleInvMode = {}
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.clip(RoundedCornerShape(32.dp))
|
|
||||||
.background(MaterialTheme.colorScheme.inverseOnSurface)
|
|
||||||
.weight(5f)
|
|
||||||
.fillMaxSize()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PortraitKeyboard(
|
private fun PortraitKeyboard(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
|
@ -31,7 +31,7 @@ import androidx.compose.animation.fadeOut
|
|||||||
import androidx.compose.animation.shrinkVertically
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.animation.togetherWith
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
@ -64,7 +64,6 @@ import androidx.compose.ui.text.TextRange
|
|||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.sadellie.unitto.core.base.OutputFormat
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
@ -74,6 +73,7 @@ import com.sadellie.unitto.core.ui.common.ColumnWithConstraints
|
|||||||
import com.sadellie.unitto.core.ui.common.MenuButton
|
import com.sadellie.unitto.core.ui.common.MenuButton
|
||||||
import com.sadellie.unitto.core.ui.common.PortraitLandscape
|
import com.sadellie.unitto.core.ui.common.PortraitLandscape
|
||||||
import com.sadellie.unitto.core.ui.common.SettingsButton
|
import com.sadellie.unitto.core.ui.common.SettingsButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoScreenWithTopBar
|
import com.sadellie.unitto.core.ui.common.UnittoScreenWithTopBar
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
@ -124,6 +124,56 @@ private fun ConverterScreen(
|
|||||||
clearInput: () -> Unit,
|
clearInput: () -> Unit,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onCursorChange: (TextRange) -> Unit,
|
||||||
onErrorClick: (AbstractUnit) -> Unit,
|
onErrorClick: (AbstractUnit) -> Unit,
|
||||||
|
) {
|
||||||
|
when (uiState) {
|
||||||
|
UnitConverterUIState.Loading -> UnittoEmptyScreen()
|
||||||
|
|
||||||
|
is UnitConverterUIState.NumberBase -> {
|
||||||
|
UnitConverterTopBar(
|
||||||
|
navigateToMenu = navigateToMenu,
|
||||||
|
navigateToSettings = navigateToSettings
|
||||||
|
) {
|
||||||
|
NumberBase(
|
||||||
|
modifier = Modifier.padding(it),
|
||||||
|
uiState = uiState,
|
||||||
|
onCursorChange = onCursorChange,
|
||||||
|
processInput = processInput,
|
||||||
|
deleteDigit = deleteDigit,
|
||||||
|
navigateToLeftScreen = navigateToLeftScreen,
|
||||||
|
swapUnits = swapUnits,
|
||||||
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
|
clearInput = clearInput
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is UnitConverterUIState.Default -> {
|
||||||
|
UnitConverterTopBar(
|
||||||
|
navigateToMenu = navigateToMenu,
|
||||||
|
navigateToSettings = navigateToSettings
|
||||||
|
) {
|
||||||
|
Default(
|
||||||
|
modifier = Modifier.padding(it),
|
||||||
|
uiState = uiState,
|
||||||
|
onCursorChange = onCursorChange,
|
||||||
|
processInput = processInput,
|
||||||
|
deleteDigit = deleteDigit,
|
||||||
|
navigateToLeftScreen = navigateToLeftScreen,
|
||||||
|
swapUnits = swapUnits,
|
||||||
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
|
clearInput = clearInput,
|
||||||
|
refreshCurrencyRates = onErrorClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun UnitConverterTopBar(
|
||||||
|
navigateToMenu: () -> Unit,
|
||||||
|
navigateToSettings: () -> Unit,
|
||||||
|
content: @Composable (PaddingValues) -> Unit
|
||||||
) {
|
) {
|
||||||
UnittoScreenWithTopBar(
|
UnittoScreenWithTopBar(
|
||||||
title = { Text(stringResource(R.string.unit_converter_title)) },
|
title = { Text(stringResource(R.string.unit_converter_title)) },
|
||||||
@ -131,83 +181,8 @@ private fun ConverterScreen(
|
|||||||
actions = {
|
actions = {
|
||||||
SettingsButton(navigateToSettings)
|
SettingsButton(navigateToSettings)
|
||||||
},
|
},
|
||||||
colors = TopAppBarDefaults
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(containerColor = Color.Transparent),
|
||||||
.centerAlignedTopAppBarColors(containerColor = Color.Transparent),
|
content = { content(it) }
|
||||||
content = { padding ->
|
|
||||||
when (uiState) {
|
|
||||||
is UnitConverterUIState.Loading -> {
|
|
||||||
ConverterLoading(modifier = Modifier.padding(padding))
|
|
||||||
}
|
|
||||||
|
|
||||||
is UnitConverterUIState.NumberBase -> {
|
|
||||||
NumberBase(
|
|
||||||
modifier = Modifier.padding(padding),
|
|
||||||
uiState = uiState,
|
|
||||||
onCursorChange = onCursorChange,
|
|
||||||
processInput = processInput,
|
|
||||||
deleteDigit = deleteDigit,
|
|
||||||
navigateToLeftScreen = navigateToLeftScreen,
|
|
||||||
swapUnits = swapUnits,
|
|
||||||
navigateToRightScreen = navigateToRightScreen,
|
|
||||||
clearInput = clearInput
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is UnitConverterUIState.Default -> {
|
|
||||||
Default(
|
|
||||||
modifier = Modifier.padding(padding),
|
|
||||||
uiState = uiState,
|
|
||||||
onCursorChange = onCursorChange,
|
|
||||||
processInput = processInput,
|
|
||||||
deleteDigit = deleteDigit,
|
|
||||||
navigateToLeftScreen = navigateToLeftScreen,
|
|
||||||
swapUnits = swapUnits,
|
|
||||||
navigateToRightScreen = navigateToRightScreen,
|
|
||||||
clearInput = clearInput,
|
|
||||||
refreshCurrencyRates = onErrorClick
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun ConverterLoading(modifier: Modifier) {
|
|
||||||
PortraitLandscape(
|
|
||||||
modifier = modifier.fillMaxSize(),
|
|
||||||
content1 = { contentModifier ->
|
|
||||||
ColumnWithConstraints(modifier = contentModifier) {
|
|
||||||
val textFieldModifier = Modifier.weight(2f)
|
|
||||||
|
|
||||||
UnformattedTextField(
|
|
||||||
modifier = textFieldModifier,
|
|
||||||
value = TextFieldValue(stringResource(R.string.loading_label)),
|
|
||||||
onCursorChange = {},
|
|
||||||
minRatio = 0.7f,
|
|
||||||
readOnly = true
|
|
||||||
)
|
|
||||||
AnimatedUnitShortName()
|
|
||||||
|
|
||||||
ConverterResultTextField(
|
|
||||||
modifier = textFieldModifier,
|
|
||||||
result = ConverterResult.Loading
|
|
||||||
)
|
|
||||||
AnimatedUnitShortName()
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(it.maxHeight * 0.03f))
|
|
||||||
|
|
||||||
UnitSelectionButtons()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content2 = {
|
|
||||||
Box(
|
|
||||||
modifier = it
|
|
||||||
.clip(RoundedCornerShape(32.dp))
|
|
||||||
.background(MaterialTheme.colorScheme.inverseOnSurface)
|
|
||||||
.fillMaxSize()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ import androidx.compose.animation.animateColorAsState
|
|||||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -48,6 +47,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
||||||
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.UnitsListSorting
|
||||||
@ -71,9 +71,7 @@ internal fun LeftSideRoute(
|
|||||||
when (
|
when (
|
||||||
val uiState = viewModel.leftSideUIState.collectAsStateWithLifecycle().value
|
val uiState = viewModel.leftSideUIState.collectAsStateWithLifecycle().value
|
||||||
) {
|
) {
|
||||||
is LeftSideUIState.Loading -> {
|
is LeftSideUIState.Loading -> UnittoEmptyScreen()
|
||||||
Box(modifier = Modifier.fillMaxSize())
|
|
||||||
}
|
|
||||||
is LeftSideUIState.Ready -> LeftSideScreen(
|
is LeftSideUIState.Ready -> LeftSideScreen(
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onQueryChange = viewModel::queryChangeLeft,
|
onQueryChange = viewModel::queryChangeLeft,
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
package com.sadellie.unitto.feature.converter
|
package com.sadellie.unitto.feature.converter
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@ -36,6 +35,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.sadellie.unitto.core.base.OutputFormat
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
|
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
|
||||||
@ -62,7 +62,7 @@ internal fun RightSideRoute(
|
|||||||
when (
|
when (
|
||||||
val uiState = viewModel.rightSideUIState.collectAsStateWithLifecycle().value
|
val uiState = viewModel.rightSideUIState.collectAsStateWithLifecycle().value
|
||||||
) {
|
) {
|
||||||
is RightSideUIState.Loading -> Box(Modifier.fillMaxSize())
|
is RightSideUIState.Loading -> UnittoEmptyScreen()
|
||||||
is RightSideUIState.Ready ->
|
is RightSideUIState.Ready ->
|
||||||
RightSideScreen(
|
RightSideScreen(
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
|
@ -54,6 +54,7 @@ import com.sadellie.unitto.core.base.BuildConfig
|
|||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.Header
|
import com.sadellie.unitto.core.ui.common.Header
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.core.ui.openLink
|
import com.sadellie.unitto.core.ui.openLink
|
||||||
@ -72,17 +73,22 @@ internal fun SettingsRoute(
|
|||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navControllerAction: (String) -> Unit,
|
navControllerAction: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle()
|
val userPrefs = viewModel.userPrefs.collectAsStateWithLifecycle().value
|
||||||
val cachePercentage = viewModel.cachePercentage.collectAsStateWithLifecycle()
|
val cachePercentage = viewModel.cachePercentage.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
SettingsScreen(
|
when (userPrefs) {
|
||||||
userPrefs = userPrefs.value,
|
null -> UnittoEmptyScreen()
|
||||||
navigateUp = navigateUp,
|
else -> {
|
||||||
navControllerAction = navControllerAction,
|
SettingsScreen(
|
||||||
updateVibrations = viewModel::updateVibrations,
|
userPrefs = userPrefs,
|
||||||
cachePercentage = cachePercentage.value,
|
navigateUp = navigateUp,
|
||||||
clearCache = viewModel::clearCache,
|
navControllerAction = navControllerAction,
|
||||||
)
|
updateVibrations = viewModel::updateVibrations,
|
||||||
|
cachePercentage = cachePercentage.value,
|
||||||
|
clearCache = viewModel::clearCache,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -197,7 +203,9 @@ private fun PreviewSettingsScreen() {
|
|||||||
var cacheSize by remember { mutableFloatStateOf(0.9f) }
|
var cacheSize by remember { mutableFloatStateOf(0.9f) }
|
||||||
|
|
||||||
SettingsScreen(
|
SettingsScreen(
|
||||||
userPrefs = GeneralPreferences(),
|
userPrefs = GeneralPreferences(
|
||||||
|
enableVibrations = true
|
||||||
|
),
|
||||||
navigateUp = {},
|
navigateUp = {},
|
||||||
navControllerAction = {},
|
navControllerAction = {},
|
||||||
updateVibrations = {},
|
updateVibrations = {},
|
||||||
|
@ -22,7 +22,6 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.database.CurrencyRatesDao
|
import com.sadellie.unitto.data.database.CurrencyRatesDao
|
||||||
import com.sadellie.unitto.data.userprefs.GeneralPreferences
|
|
||||||
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
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -36,7 +35,7 @@ internal class SettingsViewModel @Inject constructor(
|
|||||||
private val currencyRatesDao: CurrencyRatesDao,
|
private val currencyRatesDao: CurrencyRatesDao,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val userPrefs = userPrefsRepository.generalPrefs
|
val userPrefs = userPrefsRepository.generalPrefs
|
||||||
.stateIn(viewModelScope, GeneralPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
val cachePercentage = currencyRatesDao.size()
|
val cachePercentage = currencyRatesDao.size()
|
||||||
.map {
|
.map {
|
||||||
|
@ -47,6 +47,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.sadellie.unitto.core.base.BuildConfig
|
import com.sadellie.unitto.core.base.BuildConfig
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.core.ui.openLink
|
import com.sadellie.unitto.core.ui.openLink
|
||||||
@ -59,14 +60,17 @@ internal fun AboutRoute(
|
|||||||
navigateUpAction: () -> Unit,
|
navigateUpAction: () -> Unit,
|
||||||
navigateToThirdParty: () -> Unit,
|
navigateToThirdParty: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
AboutScreen(
|
else -> {
|
||||||
prefs = prefs.value,
|
AboutScreen(
|
||||||
navigateUpAction = navigateUpAction,
|
prefs = prefs,
|
||||||
navigateToThirdParty = navigateToThirdParty,
|
navigateUpAction = navigateUpAction,
|
||||||
enableToolsExperiment = viewModel::enableToolsExperiment
|
navigateToThirdParty = navigateToThirdParty,
|
||||||
)
|
enableToolsExperiment = viewModel::enableToolsExperiment
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -196,7 +200,9 @@ private fun AboutScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
fun PreviewAboutScreen() {
|
fun PreviewAboutScreen() {
|
||||||
AboutScreen(
|
AboutScreen(
|
||||||
prefs = AboutPreferences(),
|
prefs = AboutPreferences(
|
||||||
|
enableToolsExperiment = false
|
||||||
|
),
|
||||||
navigateUpAction = {},
|
navigateUpAction = {},
|
||||||
navigateToThirdParty = {},
|
navigateToThirdParty = {},
|
||||||
enableToolsExperiment = {}
|
enableToolsExperiment = {}
|
||||||
|
@ -21,7 +21,6 @@ package com.sadellie.unitto.feature.settings.about
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.userprefs.AboutPreferences
|
|
||||||
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
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -32,7 +31,7 @@ internal class AboutViewModel @Inject constructor(
|
|||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val prefs = userPrefsRepository.aboutPrefs
|
val prefs = userPrefsRepository.aboutPrefs
|
||||||
.stateIn(viewModelScope, AboutPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
fun enableToolsExperiment() = viewModelScope.launch {
|
fun enableToolsExperiment() = viewModelScope.launch {
|
||||||
userPrefsRepository.updateToolsExperiment(true)
|
userPrefsRepository.updateToolsExperiment(true)
|
||||||
|
@ -26,8 +26,11 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
|
import com.sadellie.unitto.core.base.Separator
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.data.userprefs.CalculatorPreferences
|
import com.sadellie.unitto.data.userprefs.CalculatorPreferences
|
||||||
@ -37,13 +40,16 @@ internal fun CalculatorSettingsRoute(
|
|||||||
viewModel: CalculatorViewModel = hiltViewModel(),
|
viewModel: CalculatorViewModel = hiltViewModel(),
|
||||||
navigateUpAction: () -> Unit,
|
navigateUpAction: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
CalculatorSettingsScreen(
|
else -> {
|
||||||
prefs = prefs.value,
|
CalculatorSettingsScreen(
|
||||||
navigateUpAction = navigateUpAction,
|
prefs = prefs,
|
||||||
updatePartialHistoryView = viewModel::updatePartialHistoryView
|
navigateUpAction = navigateUpAction,
|
||||||
)
|
updatePartialHistoryView = viewModel::updatePartialHistoryView
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -75,7 +81,15 @@ private fun CalculatorSettingsScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun PreviewCalculatorSettingsScreen() {
|
private fun PreviewCalculatorSettingsScreen() {
|
||||||
CalculatorSettingsScreen(
|
CalculatorSettingsScreen(
|
||||||
prefs = CalculatorPreferences(),
|
prefs = CalculatorPreferences(
|
||||||
|
radianMode = false,
|
||||||
|
enableVibrations = false,
|
||||||
|
separator = Separator.SPACE,
|
||||||
|
middleZero = false,
|
||||||
|
partialHistoryView = true,
|
||||||
|
precision = 3,
|
||||||
|
outputFormat = OutputFormat.PLAIN
|
||||||
|
),
|
||||||
navigateUpAction = {},
|
navigateUpAction = {},
|
||||||
updatePartialHistoryView = {}
|
updatePartialHistoryView = {}
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,6 @@ package com.sadellie.unitto.feature.settings.calculator
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.userprefs.CalculatorPreferences
|
|
||||||
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
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -32,7 +31,7 @@ class CalculatorViewModel @Inject constructor(
|
|||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val prefs = userPrefsRepository.calculatorPrefs
|
val prefs = userPrefsRepository.calculatorPrefs
|
||||||
.stateIn(viewModelScope, CalculatorPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
fun updatePartialHistoryView(enabled: Boolean) = viewModelScope.launch {
|
fun updatePartialHistoryView(enabled: Boolean) = viewModelScope.launch {
|
||||||
userPrefsRepository.updatePartialHistoryView(enabled)
|
userPrefsRepository.updatePartialHistoryView(enabled)
|
||||||
|
@ -34,10 +34,14 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
|
import com.sadellie.unitto.core.base.Separator
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
|
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.userprefs.ConverterPreferences
|
import com.sadellie.unitto.data.userprefs.ConverterPreferences
|
||||||
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
||||||
@ -48,15 +52,18 @@ internal fun ConverterSettingsRoute(
|
|||||||
navigateUpAction: () -> Unit,
|
navigateUpAction: () -> Unit,
|
||||||
navigateToUnitsGroup: () -> Unit,
|
navigateToUnitsGroup: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
ConverterSettingsScreen(
|
else -> {
|
||||||
prefs = prefs.value,
|
ConverterSettingsScreen(
|
||||||
navigateUpAction = navigateUpAction,
|
prefs = prefs,
|
||||||
navigateToUnitsGroup = navigateToUnitsGroup,
|
navigateUpAction = navigateUpAction,
|
||||||
updateUnitConverterFormatTime = viewModel::updateUnitConverterFormatTime,
|
navigateToUnitsGroup = navigateToUnitsGroup,
|
||||||
updateUnitConverterSorting = viewModel::updateUnitConverterSorting
|
updateUnitConverterFormatTime = viewModel::updateUnitConverterFormatTime,
|
||||||
)
|
updateUnitConverterSorting = viewModel::updateUnitConverterSorting
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -127,7 +134,20 @@ private fun ConverterSettingsScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun PreviewConverterSettingsScreen() {
|
private fun PreviewConverterSettingsScreen() {
|
||||||
ConverterSettingsScreen(
|
ConverterSettingsScreen(
|
||||||
prefs = ConverterPreferences(),
|
prefs = ConverterPreferences(
|
||||||
|
enableVibrations = true,
|
||||||
|
separator = Separator.SPACE,
|
||||||
|
middleZero = false,
|
||||||
|
precision = 3,
|
||||||
|
outputFormat = OutputFormat.PLAIN,
|
||||||
|
unitConverterFormatTime = false,
|
||||||
|
unitConverterSorting = UnitsListSorting.USAGE,
|
||||||
|
shownUnitGroups = ALL_UNIT_GROUPS,
|
||||||
|
unitConverterFavoritesOnly = false,
|
||||||
|
enableToolsExperiment = false,
|
||||||
|
latestLeftSideUnit = "kilometer",
|
||||||
|
latestRightSideUnit = "mile",
|
||||||
|
),
|
||||||
navigateUpAction = {},
|
navigateUpAction = {},
|
||||||
navigateToUnitsGroup = {},
|
navigateToUnitsGroup = {},
|
||||||
updateUnitConverterFormatTime = {},
|
updateUnitConverterFormatTime = {},
|
||||||
|
@ -22,7 +22,6 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.userprefs.ConverterPreferences
|
|
||||||
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
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -33,7 +32,7 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val prefs = userPrefsRepository.converterPrefs
|
val prefs = userPrefsRepository.converterPrefs
|
||||||
.stateIn(viewModelScope, ConverterPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
fun updateUnitConverterFormatTime(enabled: Boolean) = viewModelScope.launch {
|
fun updateUnitConverterFormatTime(enabled: Boolean) = viewModelScope.launch {
|
||||||
userPrefsRepository.updateUnitConverterFormatTime(enabled)
|
userPrefsRepository.updateUnitConverterFormatTime(enabled)
|
||||||
|
@ -59,6 +59,7 @@ import com.sadellie.unitto.core.ui.common.Header
|
|||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
import com.sadellie.unitto.core.ui.common.SegmentedButton
|
import com.sadellie.unitto.core.ui.common.SegmentedButton
|
||||||
import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
|
import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.feature.settings.components.ColorSelector
|
import com.sadellie.unitto.feature.settings.components.ColorSelector
|
||||||
@ -75,46 +76,49 @@ internal fun DisplayRoute(
|
|||||||
themmoController: ThemmoController,
|
themmoController: ThemmoController,
|
||||||
navigateToLanguages: () -> Unit,
|
navigateToLanguages: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
DisplayScreen(
|
else -> {
|
||||||
navigateUp = navigateUp,
|
DisplayScreen(
|
||||||
currentThemingMode = themmoController.currentThemingMode,
|
navigateUp = navigateUp,
|
||||||
onThemeChange = {
|
currentThemingMode = themmoController.currentThemingMode,
|
||||||
themmoController.setThemingMode(it)
|
onThemeChange = { newValue ->
|
||||||
viewModel.updateThemingMode(it)
|
themmoController.setThemingMode(newValue)
|
||||||
},
|
viewModel.updateThemingMode(newValue)
|
||||||
isDynamicThemeEnabled = themmoController.isDynamicThemeEnabled,
|
},
|
||||||
onDynamicThemeChange = {
|
isDynamicThemeEnabled = themmoController.isDynamicThemeEnabled,
|
||||||
// Prevent old devices from using other monet modes when dynamic theming is on
|
onDynamicThemeChange = { newValue ->
|
||||||
if (it) {
|
// Prevent old devices from using other monet modes when dynamic theming is on
|
||||||
themmoController.setMonetMode(MonetMode.TonalSpot)
|
if (newValue) {
|
||||||
viewModel.updateMonetMode(MonetMode.TonalSpot)
|
themmoController.setMonetMode(MonetMode.TonalSpot)
|
||||||
}
|
viewModel.updateMonetMode(MonetMode.TonalSpot)
|
||||||
themmoController.enableDynamicTheme(it)
|
}
|
||||||
viewModel.updateDynamicTheme(it)
|
themmoController.enableDynamicTheme(newValue)
|
||||||
},
|
viewModel.updateDynamicTheme(newValue)
|
||||||
isAmoledThemeEnabled = themmoController.isAmoledThemeEnabled,
|
},
|
||||||
onAmoledThemeChange = {
|
isAmoledThemeEnabled = themmoController.isAmoledThemeEnabled,
|
||||||
themmoController.enableAmoledTheme(it)
|
onAmoledThemeChange = { newValue ->
|
||||||
viewModel.updateAmoledTheme(it)
|
themmoController.enableAmoledTheme(newValue)
|
||||||
},
|
viewModel.updateAmoledTheme(newValue)
|
||||||
selectedColor = themmoController.currentCustomColor,
|
},
|
||||||
onColorChange = {
|
selectedColor = themmoController.currentCustomColor,
|
||||||
themmoController.setCustomColor(it)
|
onColorChange = { newValue ->
|
||||||
viewModel.updateCustomColor(it)
|
themmoController.setCustomColor(newValue)
|
||||||
},
|
viewModel.updateCustomColor(newValue)
|
||||||
monetMode = themmoController.currentMonetMode,
|
},
|
||||||
onMonetModeChange = {
|
monetMode = themmoController.currentMonetMode,
|
||||||
themmoController.setMonetMode(it)
|
onMonetModeChange = { newValue ->
|
||||||
viewModel.updateMonetMode(it)
|
themmoController.setMonetMode(newValue)
|
||||||
},
|
viewModel.updateMonetMode(newValue)
|
||||||
systemFont = prefs.value.systemFont,
|
},
|
||||||
updateSystemFont = viewModel::updateSystemFont,
|
systemFont = prefs.systemFont,
|
||||||
middleZero = prefs.value.middleZero,
|
updateSystemFont = viewModel::updateSystemFont,
|
||||||
updateMiddleZero = viewModel::updateMiddleZero,
|
middleZero = prefs.middleZero,
|
||||||
navigateToLanguages = navigateToLanguages
|
updateMiddleZero = viewModel::updateMiddleZero,
|
||||||
)
|
navigateToLanguages = navigateToLanguages
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -22,7 +22,6 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.userprefs.DisplayPreferences
|
|
||||||
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
|
||||||
import io.github.sadellie.themmo.MonetMode
|
import io.github.sadellie.themmo.MonetMode
|
||||||
@ -36,7 +35,7 @@ class DisplayViewModel @Inject constructor(
|
|||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
val prefs = userPrefsRepository.displayPrefs
|
val prefs = userPrefsRepository.displayPrefs
|
||||||
.stateIn(viewModelScope, DisplayPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see UserPreferencesRepository.updateThemingMode
|
* @see UserPreferencesRepository.updateThemingMode
|
||||||
|
@ -57,6 +57,7 @@ import com.sadellie.unitto.core.base.Separator
|
|||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
import com.sadellie.unitto.core.ui.common.SegmentedButton
|
import com.sadellie.unitto.core.ui.common.SegmentedButton
|
||||||
import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
|
import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoSlider
|
import com.sadellie.unitto.core.ui.common.UnittoSlider
|
||||||
@ -70,16 +71,19 @@ fun FormattingRoute(
|
|||||||
viewModel: FormattingViewModel = hiltViewModel(),
|
viewModel: FormattingViewModel = hiltViewModel(),
|
||||||
navigateUpAction: () -> Unit,
|
navigateUpAction: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
|
when (val uiState = viewModel.uiState.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
FormattingScreen(
|
else -> {
|
||||||
navigateUpAction = navigateUpAction,
|
FormattingScreen(
|
||||||
uiState = uiState.value,
|
navigateUpAction = navigateUpAction,
|
||||||
onPrecisionChange = viewModel::updatePrecision,
|
uiState = uiState,
|
||||||
onSeparatorChange = viewModel::updateSeparator,
|
onPrecisionChange = viewModel::updatePrecision,
|
||||||
onOutputFormatChange = viewModel::updateOutputFormat,
|
onSeparatorChange = viewModel::updateSeparator,
|
||||||
togglePreview = viewModel::togglePreview
|
onOutputFormatChange = viewModel::updateOutputFormat,
|
||||||
)
|
togglePreview = viewModel::togglePreview
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -61,7 +61,7 @@ class FormattingViewModel @Inject constructor(
|
|||||||
formatterSymbols = formatterSymbols
|
formatterSymbols = formatterSymbols
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, FormattingUIState())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
fun togglePreview() = _fractional.update { !it }
|
fun togglePreview() = _fractional.update { !it }
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ import androidx.navigation.NavGraphBuilder
|
|||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.navDeepLink
|
import androidx.navigation.navDeepLink
|
||||||
import com.sadellie.unitto.core.base.TopLevelDestinations
|
import com.sadellie.unitto.core.base.TopLevelDestinations
|
||||||
import com.sadellie.unitto.core.ui.unittoComposable
|
|
||||||
import com.sadellie.unitto.core.ui.unittoNavigation
|
import com.sadellie.unitto.core.ui.unittoNavigation
|
||||||
|
import com.sadellie.unitto.core.ui.unittoStackedComposable
|
||||||
import com.sadellie.unitto.feature.settings.SettingsRoute
|
import com.sadellie.unitto.feature.settings.SettingsRoute
|
||||||
import com.sadellie.unitto.feature.settings.about.AboutRoute
|
import com.sadellie.unitto.feature.settings.about.AboutRoute
|
||||||
import com.sadellie.unitto.feature.settings.calculator.CalculatorSettingsRoute
|
import com.sadellie.unitto.feature.settings.calculator.CalculatorSettingsRoute
|
||||||
@ -68,14 +68,14 @@ fun NavGraphBuilder.settingGraph(
|
|||||||
navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" }
|
navDeepLink { uriPattern = "app://com.sadellie.unitto/$graph" }
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
unittoComposable(start) {
|
unittoStackedComposable(start) {
|
||||||
SettingsRoute(
|
SettingsRoute(
|
||||||
navigateUp = navController::navigateUp,
|
navigateUp = navController::navigateUp,
|
||||||
navControllerAction = navController::navigate
|
navControllerAction = navController::navigate
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(displayRoute) {
|
unittoStackedComposable(displayRoute) {
|
||||||
DisplayRoute(
|
DisplayRoute(
|
||||||
navigateUp = navController::navigateUp,
|
navigateUp = navController::navigateUp,
|
||||||
themmoController = themmoController,
|
themmoController = themmoController,
|
||||||
@ -83,51 +83,51 @@ fun NavGraphBuilder.settingGraph(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(languageRoute) {
|
unittoStackedComposable(languageRoute) {
|
||||||
LanguageRoute(
|
LanguageRoute(
|
||||||
navigateUp = navController::navigateUp,
|
navigateUp = navController::navigateUp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(startingScreenRoute) {
|
unittoStackedComposable(startingScreenRoute) {
|
||||||
StartingScreenRoute(
|
StartingScreenRoute(
|
||||||
navigateUp = navController::navigateUp,
|
navigateUp = navController::navigateUp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(formattingRoute) {
|
unittoStackedComposable(formattingRoute) {
|
||||||
FormattingRoute(
|
FormattingRoute(
|
||||||
navigateUpAction = navController::navigateUp
|
navigateUpAction = navController::navigateUp
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(calculatorSettingsRoute) {
|
unittoStackedComposable(calculatorSettingsRoute) {
|
||||||
CalculatorSettingsRoute(
|
CalculatorSettingsRoute(
|
||||||
navigateUpAction = navController::navigateUp,
|
navigateUpAction = navController::navigateUp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(converterSettingsRoute) {
|
unittoStackedComposable(converterSettingsRoute) {
|
||||||
ConverterSettingsRoute(
|
ConverterSettingsRoute(
|
||||||
navigateUpAction = navController::navigateUp,
|
navigateUpAction = navController::navigateUp,
|
||||||
navigateToUnitsGroup = { navController.navigate(unitsGroupRoute) }
|
navigateToUnitsGroup = { navController.navigate(unitsGroupRoute) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(unitsGroupRoute) {
|
unittoStackedComposable(unitsGroupRoute) {
|
||||||
UnitGroupsScreen(
|
UnitGroupsScreen(
|
||||||
navigateUpAction = navController::navigateUp,
|
navigateUpAction = navController::navigateUp,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(aboutRoute) {
|
unittoStackedComposable(aboutRoute) {
|
||||||
AboutRoute(
|
AboutRoute(
|
||||||
navigateUpAction = navController::navigateUp,
|
navigateUpAction = navController::navigateUp,
|
||||||
navigateToThirdParty = { navController.navigate(thirdPartyRoute) }
|
navigateToThirdParty = { navController.navigate(thirdPartyRoute) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unittoComposable(thirdPartyRoute) {
|
unittoStackedComposable(thirdPartyRoute) {
|
||||||
ThirdPartyLicensesScreen(
|
ThirdPartyLicensesScreen(
|
||||||
navigateUpAction = navController::navigateUp,
|
navigateUpAction = navController::navigateUp,
|
||||||
)
|
)
|
||||||
|
@ -40,6 +40,7 @@ import com.sadellie.unitto.core.base.TOP_LEVEL_DESTINATIONS
|
|||||||
import com.sadellie.unitto.core.base.TopLevelDestinations
|
import com.sadellie.unitto.core.base.TopLevelDestinations
|
||||||
import com.sadellie.unitto.core.ui.addShortcut
|
import com.sadellie.unitto.core.ui.addShortcut
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
|
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
|
||||||
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.common.UnittoScreenWithLargeTopBar
|
||||||
|
|
||||||
@ -48,13 +49,16 @@ internal fun StartingScreenRoute(
|
|||||||
viewModel: StartingScreenViewModel = hiltViewModel(),
|
viewModel: StartingScreenViewModel = hiltViewModel(),
|
||||||
navigateUp: () -> Unit
|
navigateUp: () -> Unit
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs.collectAsStateWithLifecycle()
|
when (val prefs = viewModel.prefs.collectAsStateWithLifecycle().value) {
|
||||||
|
null -> UnittoEmptyScreen()
|
||||||
StartingScreenScreen(
|
else -> {
|
||||||
startingScreen = prefs.value.startingScreen,
|
StartingScreenScreen(
|
||||||
updateStartingScreen = viewModel::updateStartingScreen,
|
startingScreen = prefs.startingScreen,
|
||||||
navigateUp = navigateUp
|
updateStartingScreen = viewModel::updateStartingScreen,
|
||||||
)
|
navigateUp = navigateUp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -21,7 +21,6 @@ package com.sadellie.unitto.feature.settings.startingscreen
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.userprefs.StartingScreenPreferences
|
|
||||||
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
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -32,7 +31,7 @@ internal class StartingScreenViewModel @Inject constructor(
|
|||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val prefs = userPrefsRepository.startingScreenPrefs
|
val prefs = userPrefsRepository.startingScreenPrefs
|
||||||
.stateIn(viewModelScope, StartingScreenPreferences())
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
fun updateStartingScreen(startingScreen: String) = viewModelScope.launch {
|
fun updateStartingScreen(startingScreen: String) = viewModelScope.launch {
|
||||||
userPrefsRepository.updateStartingScreen(startingScreen)
|
userPrefsRepository.updateStartingScreen(startingScreen)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user