Little refactor for settings screen

This commit is contained in:
Sad Ellie 2022-07-23 22:23:40 +03:00
parent 685a3dfc56
commit 956a04bec6
9 changed files with 134 additions and 138 deletions

View File

@ -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
) )
} }

View File

@ -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"

View File

@ -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
) )
} }

View File

@ -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
) )
/** /**

View File

@ -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,10 +344,8 @@ 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)
}
} }
/** /**
@ -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()
} }
} }
} }

View File

@ -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

View File

@ -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)
) )

View File

@ -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)
}
}
} }
} }

View File

@ -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),