mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-26 04:00:37 +02:00
Little refactor for settings screen
This commit is contained in:
parent
685a3dfc56
commit
956a04bec6
@ -21,32 +21,34 @@ package com.sadellie.unitto
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.navigation.NavGraphBuilder
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
|
import androidx.navigation.compose.navigation
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import com.sadellie.unitto.data.NavRoutes.ABOUT_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.ABOUT_SCREEN
|
||||||
import com.sadellie.unitto.data.NavRoutes.LEFT_LIST_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.LEFT_LIST_SCREEN
|
||||||
import com.sadellie.unitto.data.NavRoutes.MAIN_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.MAIN_SCREEN
|
||||||
import com.sadellie.unitto.data.NavRoutes.RIGHT_LIST_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.RIGHT_LIST_SCREEN
|
||||||
|
import com.sadellie.unitto.data.NavRoutes.SETTINGS_GRAPH
|
||||||
import com.sadellie.unitto.data.NavRoutes.SETTINGS_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.SETTINGS_SCREEN
|
||||||
import com.sadellie.unitto.data.NavRoutes.THEMES_SCREEN
|
import com.sadellie.unitto.data.NavRoutes.THEMES_SCREEN
|
||||||
import com.sadellie.unitto.screens.MainViewModel
|
import com.sadellie.unitto.screens.MainViewModel
|
||||||
import com.sadellie.unitto.screens.about.AboutScreen
|
import com.sadellie.unitto.screens.setttings.SettingsViewModel
|
||||||
|
import com.sadellie.unitto.screens.setttings.AboutScreen
|
||||||
import com.sadellie.unitto.screens.main.MainScreen
|
import com.sadellie.unitto.screens.main.MainScreen
|
||||||
import com.sadellie.unitto.screens.second.LeftSideScreen
|
import com.sadellie.unitto.screens.second.LeftSideScreen
|
||||||
import com.sadellie.unitto.screens.second.RightSideScreen
|
import com.sadellie.unitto.screens.second.RightSideScreen
|
||||||
import com.sadellie.unitto.screens.second.SecondViewModel
|
import com.sadellie.unitto.screens.second.SecondViewModel
|
||||||
import com.sadellie.unitto.screens.setttings.SettingsScreen
|
import com.sadellie.unitto.screens.setttings.SettingsScreen
|
||||||
import com.sadellie.unitto.screens.theming.ThemesScreen
|
import com.sadellie.unitto.screens.setttings.ThemesScreen
|
||||||
import com.sadellie.unitto.screens.theming.ThemesViewModel
|
|
||||||
import com.sadellie.unitto.ui.theme.AppTypography
|
import com.sadellie.unitto.ui.theme.AppTypography
|
||||||
import com.sadellie.unitto.ui.theme.DarkThemeColors
|
import com.sadellie.unitto.ui.theme.DarkThemeColors
|
||||||
import com.sadellie.unitto.ui.theme.LightThemeColors
|
import com.sadellie.unitto.ui.theme.LightThemeColors
|
||||||
@ -57,20 +59,21 @@ import io.github.sadellie.themmo.rememberThemmoController
|
|||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
private val mainViewModel: MainViewModel by viewModels()
|
|
||||||
private val themesViewModel: ThemesViewModel by viewModels()
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
||||||
|
val userPrefs = settingsViewModel.userPrefs
|
||||||
|
|
||||||
val themmoController = rememberThemmoController(
|
val themmoController = rememberThemmoController(
|
||||||
lightColorScheme = LightThemeColors,
|
lightColorScheme = LightThemeColors,
|
||||||
darkColorScheme = DarkThemeColors,
|
darkColorScheme = DarkThemeColors,
|
||||||
// Anything below will not called if theming mode is still loading from DataStore
|
// Anything below will not called if theming mode is still loading from DataStore
|
||||||
themingMode = themesViewModel.themingMode ?: return@setContent,
|
themingMode = userPrefs.themingMode ?: return@setContent,
|
||||||
dynamicThemeEnabled = themesViewModel.enableDynamic,
|
dynamicThemeEnabled = userPrefs.enableDynamicTheme,
|
||||||
amoledThemeEnabled = themesViewModel.enableAmoled
|
amoledThemeEnabled = userPrefs.enableAmoledTheme
|
||||||
)
|
)
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val sysUiController = rememberSystemUiController()
|
val sysUiController = rememberSystemUiController()
|
||||||
@ -84,8 +87,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
UnittoApp(
|
UnittoApp(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
mainViewModel = mainViewModel,
|
settingsViewModel = settingsViewModel,
|
||||||
themesViewModel = themesViewModel,
|
|
||||||
themmoController = it
|
themmoController = it
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,21 +95,16 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
mainViewModel.saveLatestPairOfUnits()
|
|
||||||
super.onPause()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UnittoApp(
|
fun UnittoApp(
|
||||||
navController: NavHostController,
|
navController: NavHostController,
|
||||||
mainViewModel: MainViewModel,
|
settingsViewModel: SettingsViewModel,
|
||||||
themesViewModel: ThemesViewModel,
|
|
||||||
themmoController: ThemmoController
|
themmoController: ThemmoController
|
||||||
) {
|
) {
|
||||||
val secondViewModel: SecondViewModel = hiltViewModel()
|
val secondViewModel: SecondViewModel = hiltViewModel()
|
||||||
|
val mainViewModel: MainViewModel = hiltViewModel()
|
||||||
NavHost(
|
NavHost(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = MAIN_SCREEN
|
startDestination = MAIN_SCREEN
|
||||||
@ -139,19 +136,32 @@ fun UnittoApp(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settingGraph(
|
||||||
|
settingsViewModel = settingsViewModel,
|
||||||
|
themmoController = themmoController,
|
||||||
|
navController = navController
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun NavGraphBuilder.settingGraph(
|
||||||
|
settingsViewModel: SettingsViewModel,
|
||||||
|
themmoController: ThemmoController,
|
||||||
|
navController: NavHostController
|
||||||
|
) {
|
||||||
|
navigation(SETTINGS_SCREEN, SETTINGS_GRAPH) {
|
||||||
composable(SETTINGS_SCREEN) {
|
composable(SETTINGS_SCREEN) {
|
||||||
SettingsScreen(
|
SettingsScreen(
|
||||||
mainViewModel = mainViewModel,
|
viewModel = settingsViewModel,
|
||||||
navigateUpAction = { navController.navigateUp() },
|
navigateUpAction = { navController.navigateUp() }
|
||||||
navControllerAction = { route -> navController.navigate(route) }
|
) { route -> navController.navigate(route) }
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
composable(THEMES_SCREEN) {
|
composable(THEMES_SCREEN) {
|
||||||
ThemesScreen(
|
ThemesScreen(
|
||||||
navigateUpAction = { navController.navigateUp() },
|
navigateUpAction = { navController.navigateUp() },
|
||||||
themmoController = themmoController,
|
themmoController = themmoController,
|
||||||
viewModel = themesViewModel
|
viewModel = settingsViewModel
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ object NavRoutes {
|
|||||||
const val LEFT_LIST_SCREEN = "LeftScreen"
|
const val LEFT_LIST_SCREEN = "LeftScreen"
|
||||||
const val RIGHT_LIST_SCREEN = "RightScreen"
|
const val RIGHT_LIST_SCREEN = "RightScreen"
|
||||||
|
|
||||||
|
const val SETTINGS_GRAPH = "SettingsGraph"
|
||||||
const val SETTINGS_SCREEN = "SettingsScreen"
|
const val SETTINGS_SCREEN = "SettingsScreen"
|
||||||
const val THEMES_SCREEN = "ThemesScreen"
|
const val THEMES_SCREEN = "ThemesScreen"
|
||||||
const val ABOUT_SCREEN = "AboutScreen"
|
const val ABOUT_SCREEN = "AboutScreen"
|
||||||
|
@ -34,8 +34,8 @@ object Separator {
|
|||||||
*/
|
*/
|
||||||
val SEPARATORS: Map<Int, Int> by lazy {
|
val SEPARATORS: Map<Int, Int> by lazy {
|
||||||
mapOf(
|
mapOf(
|
||||||
|
Separator.SPACES to R.string.spaces,
|
||||||
Separator.PERIOD to R.string.period,
|
Separator.PERIOD to R.string.period,
|
||||||
Separator.COMMA to R.string.comma,
|
Separator.COMMA to R.string.comma
|
||||||
Separator.SPACES to R.string.spaces
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,8 @@ import javax.inject.Inject
|
|||||||
/**
|
/**
|
||||||
* Represents user preferences that are user across the app
|
* Represents user preferences that are user across the app
|
||||||
*
|
*
|
||||||
* @property themingMode [ThemingMode] from Themmo
|
* @property themingMode [ThemingMode] from Themmo. Nullable just to indicate that preferences are
|
||||||
|
* still loading.
|
||||||
* @property enableDynamicTheme Use dynamic color scheme
|
* @property enableDynamicTheme Use dynamic color scheme
|
||||||
* @property enableAmoledTheme Use amoled color scheme
|
* @property enableAmoledTheme Use amoled color scheme
|
||||||
* @property digitsPrecision Current [PRECISIONS]. Number of digits in fractional part
|
* @property digitsPrecision Current [PRECISIONS]. Number of digits in fractional part
|
||||||
@ -48,15 +49,15 @@ import javax.inject.Inject
|
|||||||
* @property enableAnalytics Whether or not user wants to share application usage data
|
* @property enableAnalytics Whether or not user wants to share application usage data
|
||||||
*/
|
*/
|
||||||
data class UserPreferences(
|
data class UserPreferences(
|
||||||
val themingMode: ThemingMode,
|
val themingMode: ThemingMode? = null,
|
||||||
val enableDynamicTheme: Boolean,
|
val enableDynamicTheme: Boolean = false,
|
||||||
val enableAmoledTheme: Boolean,
|
val enableAmoledTheme: Boolean = false,
|
||||||
val digitsPrecision: Int,
|
val digitsPrecision: Int = 3,
|
||||||
val separator: Int,
|
val separator: Int = Separator.SPACES,
|
||||||
val outputFormat: Int,
|
val outputFormat: Int = OutputFormat.PLAIN,
|
||||||
val latestLeftSideUnit: String,
|
val latestLeftSideUnit: String = MyUnitIDS.kilometer,
|
||||||
val latestRightSideUnit: String,
|
val latestRightSideUnit: String = MyUnitIDS.mile,
|
||||||
val enableAnalytics: Boolean
|
val enableAnalytics: Boolean = true
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,14 +25,13 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.firebase.analytics.FirebaseAnalytics
|
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.sadellie.unitto.data.KEY_0
|
import com.sadellie.unitto.data.KEY_0
|
||||||
import com.sadellie.unitto.data.KEY_DOT
|
import com.sadellie.unitto.data.KEY_DOT
|
||||||
import com.sadellie.unitto.data.KEY_MINUS
|
import com.sadellie.unitto.data.KEY_MINUS
|
||||||
import com.sadellie.unitto.data.preferences.MAX_PRECISION
|
import com.sadellie.unitto.data.preferences.MAX_PRECISION
|
||||||
import com.sadellie.unitto.data.preferences.OutputFormat
|
import com.sadellie.unitto.data.preferences.OutputFormat
|
||||||
import com.sadellie.unitto.data.preferences.Separator
|
import com.sadellie.unitto.data.preferences.UserPreferences
|
||||||
import com.sadellie.unitto.data.preferences.UserPreferencesRepository
|
import com.sadellie.unitto.data.preferences.UserPreferencesRepository
|
||||||
import com.sadellie.unitto.data.units.AbstractUnit
|
import com.sadellie.unitto.data.units.AbstractUnit
|
||||||
import com.sadellie.unitto.data.units.AllUnitsRepository
|
import com.sadellie.unitto.data.units.AllUnitsRepository
|
||||||
@ -56,55 +55,7 @@ class MainViewModel @Inject constructor(
|
|||||||
private val application: Application,
|
private val application: Application,
|
||||||
private val allUnitsRepository: AllUnitsRepository
|
private val allUnitsRepository: AllUnitsRepository
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
var precision: Int by mutableStateOf(3)
|
private var userPrefs = UserPreferences()
|
||||||
private set
|
|
||||||
var separator: Int by mutableStateOf(Separator.SPACES)
|
|
||||||
private set
|
|
||||||
var outputFormat: Int by mutableStateOf(OutputFormat.PLAIN)
|
|
||||||
private set
|
|
||||||
var enableAnalytics: Boolean by mutableStateOf(false)
|
|
||||||
private set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [UserPreferencesRepository.updateDigitsPrecision]
|
|
||||||
*/
|
|
||||||
fun updatePrecision(precision: Int) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
userPrefsRepository.updateDigitsPrecision(precision)
|
|
||||||
convertValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [UserPreferencesRepository.updateSeparator]
|
|
||||||
*/
|
|
||||||
fun updateSeparator(separator: Int) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
userPrefsRepository.updateSeparator(separator)
|
|
||||||
convertValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [UserPreferencesRepository.updateOutputFormat]
|
|
||||||
*/
|
|
||||||
fun updateOutputFormat(outputFormat: Int) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
userPrefsRepository.updateOutputFormat(outputFormat)
|
|
||||||
convertValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See [UserPreferencesRepository.updateEnableAnalytics]
|
|
||||||
*/
|
|
||||||
fun updateEnableAnalytics(enableAnalytics: Boolean) {
|
|
||||||
viewModelScope.launch {
|
|
||||||
userPrefsRepository.updateEnableAnalytics(enableAnalytics)
|
|
||||||
FirebaseAnalytics.getInstance(application)
|
|
||||||
.setAnalyticsCollectionEnabled(enableAnalytics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit we converting from (left side)
|
* Unit we converting from (left side)
|
||||||
@ -130,7 +81,11 @@ class MainViewModel @Inject constructor(
|
|||||||
private fun convertValue() {
|
private fun convertValue() {
|
||||||
// Converting value using a specified precision
|
// Converting value using a specified precision
|
||||||
val convertedValue: BigDecimal =
|
val convertedValue: BigDecimal =
|
||||||
unitFrom.convert(unitTo, mainUIState.inputValue.toBigDecimal(), precision)
|
unitFrom.convert(
|
||||||
|
unitTo,
|
||||||
|
mainUIState.inputValue.toBigDecimal(),
|
||||||
|
userPrefs.digitsPrecision
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There is a very interesting bug when trailing zeros are not stripped when input
|
* There is a very interesting bug when trailing zeros are not stripped when input
|
||||||
@ -138,11 +93,11 @@ class MainViewModel @Inject constructor(
|
|||||||
* is zero, than we make sure there are no trailing zeros.
|
* is zero, than we make sure there are no trailing zeros.
|
||||||
*/
|
*/
|
||||||
val resultValue =
|
val resultValue =
|
||||||
if (convertedValue == BigDecimal.ZERO.setScale(precision, RoundingMode.HALF_EVEN)) {
|
if (convertedValue == BigDecimal.ZERO.setScale(userPrefs.digitsPrecision, RoundingMode.HALF_EVEN)) {
|
||||||
KEY_0
|
KEY_0
|
||||||
} else {
|
} else {
|
||||||
// Setting result value using a specified OutputFormat
|
// Setting result value using a specified OutputFormat
|
||||||
when (outputFormat) {
|
when (userPrefs.outputFormat) {
|
||||||
OutputFormat.ALLOW_ENGINEERING -> convertedValue.toString()
|
OutputFormat.ALLOW_ENGINEERING -> convertedValue.toString()
|
||||||
OutputFormat.FORCE_ENGINEERING -> convertedValue.toEngineeringString()
|
OutputFormat.FORCE_ENGINEERING -> convertedValue.toEngineeringString()
|
||||||
else -> convertedValue.toPlainString()
|
else -> convertedValue.toPlainString()
|
||||||
@ -183,6 +138,8 @@ class MainViewModel @Inject constructor(
|
|||||||
updateCurrenciesBasicUnits()
|
updateCurrenciesBasicUnits()
|
||||||
// We can't call outside of this block. It will set precision to 0 in that case
|
// We can't call outside of this block. It will set precision to 0 in that case
|
||||||
convertValue()
|
convertValue()
|
||||||
|
// Saving latest pair
|
||||||
|
saveLatestPairOfUnits()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +166,8 @@ class MainViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
// We also need to increment counter for the selected unit
|
// We also need to increment counter for the selected unit
|
||||||
incrementCounter(clickedUnit)
|
incrementCounter(clickedUnit)
|
||||||
|
// Saving latest pair
|
||||||
|
saveLatestPairOfUnits()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changed units, now we can convert
|
// Changed units, now we can convert
|
||||||
@ -278,7 +237,10 @@ class MainViewModel @Inject constructor(
|
|||||||
unitFrom = unitTo.also {
|
unitFrom = unitTo.also {
|
||||||
unitTo = unitFrom
|
unitTo = unitFrom
|
||||||
}
|
}
|
||||||
viewModelScope.launch { updateCurrenciesBasicUnits() }
|
viewModelScope.launch {
|
||||||
|
updateCurrenciesBasicUnits()
|
||||||
|
saveLatestPairOfUnits()
|
||||||
|
}
|
||||||
// Swapped, can convert now
|
// Swapped, can convert now
|
||||||
convertValue()
|
convertValue()
|
||||||
}
|
}
|
||||||
@ -382,11 +344,9 @@ class MainViewModel @Inject constructor(
|
|||||||
/**
|
/**
|
||||||
* Saves latest pair of units into datastore
|
* Saves latest pair of units into datastore
|
||||||
*/
|
*/
|
||||||
fun saveLatestPairOfUnits() {
|
private suspend fun saveLatestPairOfUnits() {
|
||||||
viewModelScope.launch {
|
|
||||||
userPrefsRepository.updateLatestPairOfUnits(unitFrom, unitTo)
|
userPrefsRepository.updateLatestPairOfUnits(unitFrom, unitTo)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Observes changes in user preferences and updated values in this ViewModel.
|
* Observes changes in user preferences and updated values in this ViewModel.
|
||||||
@ -395,36 +355,27 @@ class MainViewModel @Inject constructor(
|
|||||||
* values recompose when actually needed. For example, when you change output format, composable
|
* values recompose when actually needed. For example, when you change output format, composable
|
||||||
* in MainActivity will not be recomposed.
|
* in MainActivity will not be recomposed.
|
||||||
*/
|
*/
|
||||||
private fun observePreferenceChanges() {
|
suspend private fun observePreferenceChanges() {
|
||||||
viewModelScope.launch {
|
userPrefsRepository.userPreferencesFlow.collect {
|
||||||
userPrefsRepository.userPreferencesFlow.collect { userPref ->
|
userPrefs = it
|
||||||
precision = userPref.digitsPrecision
|
convertValue()
|
||||||
separator = userPref.separator.also { Formatter.setSeparator(it) }
|
|
||||||
outputFormat = userPref.outputFormat
|
|
||||||
enableAnalytics = userPref.enableAnalytics.also {
|
|
||||||
// Maybe this is unnecessary
|
|
||||||
if (it != enableAnalytics) FirebaseAnalytics.getInstance(application)
|
|
||||||
.setAnalyticsCollectionEnabled(enableAnalytics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
observePreferenceChanges()
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val snapshot = userPrefsRepository.userPreferencesFlow.first()
|
userPrefs = userPrefsRepository.userPreferencesFlow.first()
|
||||||
|
|
||||||
// First we load latest pair of units
|
// First we load latest pair of units
|
||||||
unitFrom = try {
|
unitFrom = try {
|
||||||
allUnitsRepository.getById(snapshot.latestLeftSideUnit)
|
allUnitsRepository.getById(userPrefs.latestLeftSideUnit)
|
||||||
} catch (e: java.util.NoSuchElementException) {
|
} catch (e: java.util.NoSuchElementException) {
|
||||||
Log.w("MainViewModel", "No unit with the given unitId")
|
Log.w("MainViewModel", "No unit with the given unitId")
|
||||||
allUnitsRepository.getById(MyUnitIDS.kilometer)
|
allUnitsRepository.getById(MyUnitIDS.kilometer)
|
||||||
}
|
}
|
||||||
|
|
||||||
unitTo = try {
|
unitTo = try {
|
||||||
allUnitsRepository.getById(snapshot.latestRightSideUnit)
|
allUnitsRepository.getById(userPrefs.latestRightSideUnit)
|
||||||
} catch (e: java.util.NoSuchElementException) {
|
} catch (e: java.util.NoSuchElementException) {
|
||||||
Log.w("MainViewModel", "No unit with the given unitId")
|
Log.w("MainViewModel", "No unit with the given unitId")
|
||||||
allUnitsRepository.getById(MyUnitIDS.mile)
|
allUnitsRepository.getById(MyUnitIDS.mile)
|
||||||
@ -440,6 +391,7 @@ class MainViewModel @Inject constructor(
|
|||||||
mainUIState = mainUIState.copy(isLoadingDatabase = false)
|
mainUIState = mainUIState.copy(isLoadingDatabase = false)
|
||||||
updateCurrenciesBasicUnits()
|
updateCurrenciesBasicUnits()
|
||||||
convertValue()
|
convertValue()
|
||||||
|
observePreferenceChanges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.screens.about
|
package com.sadellie.unitto.screens.setttings
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
@ -33,7 +33,6 @@ import com.sadellie.unitto.data.NavRoutes.THEMES_SCREEN
|
|||||||
import com.sadellie.unitto.data.preferences.OUTPUT_FORMAT
|
import com.sadellie.unitto.data.preferences.OUTPUT_FORMAT
|
||||||
import com.sadellie.unitto.data.preferences.PRECISIONS
|
import com.sadellie.unitto.data.preferences.PRECISIONS
|
||||||
import com.sadellie.unitto.data.preferences.SEPARATORS
|
import com.sadellie.unitto.data.preferences.SEPARATORS
|
||||||
import com.sadellie.unitto.screens.MainViewModel
|
|
||||||
import com.sadellie.unitto.screens.common.UnittoLargeTopAppBar
|
import com.sadellie.unitto.screens.common.UnittoLargeTopAppBar
|
||||||
import com.sadellie.unitto.screens.openLink
|
import com.sadellie.unitto.screens.openLink
|
||||||
import com.sadellie.unitto.screens.setttings.components.AlertDialogWithList
|
import com.sadellie.unitto.screens.setttings.components.AlertDialogWithList
|
||||||
@ -42,7 +41,7 @@ import com.sadellie.unitto.screens.setttings.components.SettingsListItem
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(
|
fun SettingsScreen(
|
||||||
mainViewModel: MainViewModel,
|
viewModel: SettingsViewModel,
|
||||||
navigateUpAction: () -> Unit,
|
navigateUpAction: () -> Unit,
|
||||||
navControllerAction: (String) -> Unit
|
navControllerAction: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
@ -121,8 +120,8 @@ fun SettingsScreen(
|
|||||||
SettingsListItem(
|
SettingsListItem(
|
||||||
stringResource(R.string.send_usage_statistics),
|
stringResource(R.string.send_usage_statistics),
|
||||||
stringResource(R.string.send_usage_statistics_support),
|
stringResource(R.string.send_usage_statistics_support),
|
||||||
mainViewModel.enableAnalytics
|
viewModel.userPrefs.enableAnalytics
|
||||||
) { mainViewModel.updateEnableAnalytics(it) }
|
) { viewModel.updateEnableAnalytics(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// THIRD PARTY
|
// THIRD PARTY
|
||||||
@ -164,8 +163,8 @@ fun SettingsScreen(
|
|||||||
AlertDialogWithList(
|
AlertDialogWithList(
|
||||||
title = stringResource(id = R.string.precision_setting),
|
title = stringResource(id = R.string.precision_setting),
|
||||||
listItems = PRECISIONS,
|
listItems = PRECISIONS,
|
||||||
selectedItemIndex = mainViewModel.precision,
|
selectedItemIndex = viewModel.userPrefs.digitsPrecision,
|
||||||
selectAction = { mainViewModel.updatePrecision(it) },
|
selectAction = { viewModel.updatePrecision(it) },
|
||||||
dismissAction = { resetDialog() },
|
dismissAction = { resetDialog() },
|
||||||
supportText = stringResource(id = R.string.precision_setting_info)
|
supportText = stringResource(id = R.string.precision_setting_info)
|
||||||
)
|
)
|
||||||
@ -174,8 +173,8 @@ fun SettingsScreen(
|
|||||||
AlertDialogWithList(
|
AlertDialogWithList(
|
||||||
title = stringResource(id = R.string.separator_setting),
|
title = stringResource(id = R.string.separator_setting),
|
||||||
listItems = SEPARATORS,
|
listItems = SEPARATORS,
|
||||||
selectedItemIndex = mainViewModel.separator,
|
selectedItemIndex = viewModel.userPrefs.separator,
|
||||||
selectAction = { mainViewModel.updateSeparator(it) },
|
selectAction = { viewModel.updateSeparator(it) },
|
||||||
dismissAction = { resetDialog() }
|
dismissAction = { resetDialog() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -183,8 +182,8 @@ fun SettingsScreen(
|
|||||||
AlertDialogWithList(
|
AlertDialogWithList(
|
||||||
title = stringResource(id = R.string.output_format_setting),
|
title = stringResource(id = R.string.output_format_setting),
|
||||||
listItems = OUTPUT_FORMAT,
|
listItems = OUTPUT_FORMAT,
|
||||||
selectedItemIndex = mainViewModel.outputFormat,
|
selectedItemIndex = viewModel.userPrefs.outputFormat,
|
||||||
selectAction = { mainViewModel.updateOutputFormat(it) },
|
selectAction = { viewModel.updateOutputFormat(it) },
|
||||||
dismissAction = { resetDialog() },
|
dismissAction = { resetDialog() },
|
||||||
supportText = stringResource(id = R.string.output_format_setting_info)
|
supportText = stringResource(id = R.string.output_format_setting_info)
|
||||||
)
|
)
|
||||||
|
@ -16,27 +16,29 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.screens.theming
|
package com.sadellie.unitto.screens.setttings
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.google.firebase.analytics.FirebaseAnalytics
|
||||||
|
import com.sadellie.unitto.data.preferences.UserPreferences
|
||||||
import com.sadellie.unitto.data.preferences.UserPreferencesRepository
|
import com.sadellie.unitto.data.preferences.UserPreferencesRepository
|
||||||
|
import com.sadellie.unitto.screens.Formatter
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import io.github.sadellie.themmo.ThemingMode
|
import io.github.sadellie.themmo.ThemingMode
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ThemesViewModel @Inject constructor(
|
class SettingsViewModel @Inject constructor(
|
||||||
private val userPrefsRepository: UserPreferencesRepository
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
|
private val application: Application,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
var themingMode: ThemingMode? by mutableStateOf(null)
|
var userPrefs: UserPreferences by mutableStateOf(UserPreferences())
|
||||||
var enableDynamic by mutableStateOf(false)
|
|
||||||
var enableAmoled by mutableStateOf(false)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see [UserPreferencesRepository.updateThemingMode]
|
* @see [UserPreferencesRepository.updateThemingMode]
|
||||||
@ -66,18 +68,49 @@ class ThemesViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect saved theming options. Used on app launch.
|
* See [UserPreferencesRepository.updateDigitsPrecision]
|
||||||
*/
|
*/
|
||||||
private fun collectThemeOptions() {
|
fun updatePrecision(precision: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val userPref = userPrefsRepository.userPreferencesFlow.first()
|
userPrefsRepository.updateDigitsPrecision(precision)
|
||||||
themingMode = userPref.themingMode
|
}
|
||||||
enableDynamic = userPref.enableDynamicTheme
|
}
|
||||||
enableAmoled = userPref.enableAmoledTheme
|
|
||||||
|
/**
|
||||||
|
* See [UserPreferencesRepository.updateSeparator]
|
||||||
|
*/
|
||||||
|
fun updateSeparator(separator: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateSeparator(separator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See [UserPreferencesRepository.updateOutputFormat]
|
||||||
|
*/
|
||||||
|
fun updateOutputFormat(outputFormat: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateOutputFormat(outputFormat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See [UserPreferencesRepository.updateEnableAnalytics]
|
||||||
|
*/
|
||||||
|
fun updateEnableAnalytics(enableAnalytics: Boolean) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateEnableAnalytics(enableAnalytics)
|
||||||
|
FirebaseAnalytics.getInstance(application)
|
||||||
|
.setAnalyticsCollectionEnabled(enableAnalytics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
collectThemeOptions()
|
viewModelScope.launch {
|
||||||
|
userPrefsRepository.userPreferencesFlow.collect {
|
||||||
|
userPrefs = it
|
||||||
|
Formatter.setSeparator(it.separator)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.screens.theming
|
package com.sadellie.unitto.screens.setttings
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.expandVertically
|
import androidx.compose.animation.expandVertically
|
||||||
@ -36,7 +36,7 @@ import io.github.sadellie.themmo.ThemmoController
|
|||||||
fun ThemesScreen(
|
fun ThemesScreen(
|
||||||
navigateUpAction: () -> Unit = {},
|
navigateUpAction: () -> Unit = {},
|
||||||
themmoController: ThemmoController,
|
themmoController: ThemmoController,
|
||||||
viewModel: ThemesViewModel
|
viewModel: SettingsViewModel
|
||||||
) {
|
) {
|
||||||
UnittoLargeTopAppBar(
|
UnittoLargeTopAppBar(
|
||||||
title = stringResource(R.string.theme_setting),
|
title = stringResource(R.string.theme_setting),
|
Loading…
x
Reference in New Issue
Block a user