From 1a86aa018ed6489356171480ba1a76d22a3c7f42 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Wed, 23 Aug 2023 19:02:37 +0200 Subject: [PATCH] Custom color schemes v2 - part 3 Store preferences and apply color schemes --- .../launcher2/ui/settings/SettingsActivity.kt | 8 - .../appearance/AppearanceSettingsScreen.kt | 22 +- .../appearance/AppearanceSettingsScreenVM.kt | 27 +- .../colorscheme/ColorSchemeSettingsScreen.kt | 122 -- .../ColorSchemeSettingsScreenVM.kt | 33 - .../CustomColorSchemeSettingsScreen.kt | 1095 ----------------- .../CustomColorSchemeSettingsScreenVM.kt | 148 --- .../colorscheme/ThemesSettingsScreen.kt | 3 + .../colorscheme/ThemesSettingsScreenVM.kt | 29 +- .../mm20/launcher2/ui/theme/LauncherTheme.kt | 71 +- .../mm20/launcher2/preferences/DataStore.kt | 3 +- .../de/mm20/launcher2/preferences/Defaults.kt | 10 +- .../preferences/migrations/Migration_16_17.kt | 19 + .../preferences/src/main/proto/settings.proto | 6 +- .../mm20/launcher2/themes/ThemeRepository.kt | 3 +- 15 files changed, 93 insertions(+), 1506 deletions(-) delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreen.kt delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreenVM.kt delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreen.kt delete mode 100644 app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreenVM.kt create mode 100644 core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_16_17.kt diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt index 69f1c249..cb3f9a38 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/SettingsActivity.kt @@ -26,8 +26,6 @@ import de.mm20.launcher2.ui.settings.backup.BackupSettingsScreen import de.mm20.launcher2.ui.settings.buildinfo.BuildInfoSettingsScreen import de.mm20.launcher2.ui.settings.cards.CardsSettingsScreen import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreen -import de.mm20.launcher2.ui.settings.colorscheme.ColorSchemeSettingsScreen -import de.mm20.launcher2.ui.settings.colorscheme.CustomColorSchemeSettingsScreen import de.mm20.launcher2.ui.settings.colorscheme.ThemeSettingsScreen import de.mm20.launcher2.ui.settings.colorscheme.ThemesSettingsScreen import de.mm20.launcher2.ui.settings.crashreporter.CrashReportScreen @@ -98,12 +96,6 @@ class SettingsActivity : BaseActivity() { composable("settings/icons") { IconsSettingsScreen() } - composable("settings/appearance/colorscheme") { - ColorSchemeSettingsScreen() - } - composable("settings/appearance/colorscheme/custom") { - CustomColorSchemeSettingsScreen() - } composable("settings/appearance/themes") { ThemesSettingsScreen() } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt index 510d14e5..20700f08 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.preferences.Settings.AppearanceSettings import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme @@ -25,6 +26,7 @@ fun AppearanceSettingsScreen() { val viewModel: AppearanceSettingsScreenVM = viewModel() val context = LocalContext.current val navController = LocalNavController.current + val themeName by viewModel.colorSchemeName.collectAsStateWithLifecycle(null) PreferenceScreen(title = stringResource(id = R.string.preference_screen_appearance)) { item { PreferenceCategory { @@ -42,27 +44,9 @@ fun AppearanceSettingsScreen() { viewModel.setTheme(newValue) } ) - val colorScheme by viewModel.colorScheme.collectAsState() Preference( title = stringResource(id = R.string.preference_screen_colors), - summary = when (colorScheme) { - ColorScheme.Default -> stringResource(R.string.preference_colors_default) - ColorScheme.BlackAndWhite -> stringResource(R.string.preference_colors_bw) - ColorScheme.Custom -> stringResource(R.string.preference_colors_custom) - else -> null - }, - onClick = { - navController?.navigate("settings/appearance/colorscheme") - } - ) - Preference( - title = stringResource(id = R.string.preference_screen_colors), - summary = when (colorScheme) { - ColorScheme.Default -> stringResource(R.string.preference_colors_default) - ColorScheme.BlackAndWhite -> stringResource(R.string.preference_colors_bw) - ColorScheme.Custom -> stringResource(R.string.preference_colors_custom) - else -> null - }, + summary = themeName, onClick = { navController?.navigate("settings/appearance/themes") } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt index 4befa06f..c300bb35 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/appearance/AppearanceSettingsScreenVM.kt @@ -4,24 +4,27 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import de.mm20.launcher2.icons.IconService import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.preferences.Settings.AppearanceSettings.ColorScheme import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Font import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme -import kotlinx.coroutines.flow.Flow +import de.mm20.launcher2.themes.ThemeRepository import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject +import java.util.UUID class AppearanceSettingsScreenVM : ViewModel(), KoinComponent { private val dataStore: LauncherDataStore by inject() private val iconService: IconService by inject() + private val themeRepository: ThemeRepository by inject() val theme = dataStore.data.map { it.appearance.theme } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + fun setTheme(theme: Theme) { viewModelScope.launch { dataStore.updateData { @@ -32,20 +35,22 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent { } } - val colorScheme = dataStore.data.map { it.appearance.colorScheme } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setColorScheme(colorScheme: ColorScheme) { - viewModelScope.launch { - dataStore.updateData { - it.toBuilder() - .setAppearance(it.appearance.toBuilder().setColorScheme(colorScheme)) - .build() - } + val colorSchemeName = dataStore.data.map { + it.appearance.themeId?.takeIf { it.isNotEmpty() }?.let { + UUID.fromString(it) } } + .flatMapLatest { + themeRepository.getThemeOrDefault(it) + }.map { + it.name + } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + val font = dataStore.data.map { it.appearance.font } .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + fun setFont(font: Font) { viewModelScope.launch { dataStore.updateData { diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreen.kt deleted file mode 100644 index f35d82f2..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreen.kt +++ /dev/null @@ -1,122 +0,0 @@ -package de.mm20.launcher2.ui.settings.colorscheme - -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.RadioButtonChecked -import androidx.compose.material.icons.rounded.RadioButtonUnchecked -import androidx.compose.material3.ColorScheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.ktx.isAtLeastApiLevel -import de.mm20.launcher2.preferences.Settings.AppearanceSettings -import de.mm20.launcher2.ui.BuildConfig -import de.mm20.launcher2.ui.R -import de.mm20.launcher2.ui.component.preferences.Preference -import de.mm20.launcher2.ui.component.preferences.PreferenceCategory -import de.mm20.launcher2.ui.component.preferences.PreferenceScreen -import de.mm20.launcher2.ui.locals.LocalDarkTheme -import de.mm20.launcher2.ui.locals.LocalNavController -import de.mm20.launcher2.ui.theme.colorSchemeAsState - -@Composable -fun ColorSchemeSettingsScreen() { - val viewModel: ColorSchemeSettingsScreenVM = viewModel() - val navController = LocalNavController.current - - PreferenceScreen(title = stringResource(R.string.preference_screen_colors)) { - item { - PreferenceCategory { - val colorScheme by viewModel.colorScheme.collectAsState() - - val items = mutableListOf( - AppearanceSettings.ColorScheme.Default to stringResource(R.string.preference_colors_default), - AppearanceSettings.ColorScheme.BlackAndWhite to stringResource(R.string.preference_colors_bw), - AppearanceSettings.ColorScheme.Custom to stringResource(R.string.preference_colors_custom), - ) - - if (BuildConfig.DEBUG && isAtLeastApiLevel(27)) { - items.add(AppearanceSettings.ColorScheme.DebugMaterialYouCompat to "Material You Compat") - } - - for (cs in items) { - val scheme by colorSchemeAsState(cs.first, LocalDarkTheme.current) - Preference( - title = cs.second, - icon = if (colorScheme == cs.first) Icons.Rounded.RadioButtonChecked else Icons.Rounded.RadioButtonUnchecked, - onClick = { - viewModel.setColorScheme(cs.first) - if (cs.first == AppearanceSettings.ColorScheme.Custom) { - navController?.navigate("settings/appearance/colorscheme/custom") - } - }, - controls = { - ColorSchemePreview(scheme) - } - ) - } - } - } - } -} - -@Composable -fun ColorSchemePreview(colorScheme: ColorScheme) { - MaterialTheme(colorScheme = colorScheme) { - Box( - modifier = Modifier - .padding(vertical = 12.dp) - .width(72.dp) - .height(36.dp), - contentAlignment = Alignment.Center - ) { - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Surface( - tonalElevation = 1.dp, - color = MaterialTheme.colorScheme.surface, - modifier = Modifier - .size(36.dp) - ) {} - Surface( - tonalElevation = 1.dp, - color = MaterialTheme.colorScheme.surfaceVariant, - modifier = Modifier - .size(36.dp) - ) {} - } - Row( - verticalAlignment = Alignment.CenterVertically - ) { - Surface( - tonalElevation = 1.dp, - color = MaterialTheme.colorScheme.primary, - modifier = Modifier - .size(16.dp) - ) {} - Surface( - tonalElevation = 1.dp, - color = MaterialTheme.colorScheme.secondary, - modifier = Modifier - .padding(horizontal = 8.dp) - .size(16.dp) - ) {} - Surface( - tonalElevation = 1.dp, - color = MaterialTheme.colorScheme.tertiary, - modifier = Modifier - .size(16.dp) - ) {} - } - } - } - -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreenVM.kt deleted file mode 100644 index c33d169a..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemeSettingsScreenVM.kt +++ /dev/null @@ -1,33 +0,0 @@ -package de.mm20.launcher2.ui.settings.colorscheme - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.preferences.Settings.AppearanceSettings -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject - -class ColorSchemeSettingsScreenVM : ViewModel(), KoinComponent { - private val dataStore: LauncherDataStore by inject() - - val theme = dataStore.data.map { it.appearance.theme } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - - val colorScheme = dataStore.data.map { it.appearance.colorScheme } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setColorScheme(colorScheme: AppearanceSettings.ColorScheme) { - viewModelScope.launch { - dataStore.updateData { - it.toBuilder() - .setAppearance( - it.appearance.toBuilder() - .setColorScheme(colorScheme) - ).build() - } - } - } -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreen.kt deleted file mode 100644 index 08ce58f1..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreen.kt +++ /dev/null @@ -1,1095 +0,0 @@ -package de.mm20.launcher2.ui.settings.colorscheme - -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.MoreVert -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.res.stringResource -import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.ui.R -import de.mm20.launcher2.ui.component.preferences.ColorPreference -import de.mm20.launcher2.ui.component.preferences.PreferenceCategory -import de.mm20.launcher2.ui.component.preferences.PreferenceScreen - -@Composable -fun CustomColorSchemeSettingsScreen() { - val viewModel: CustomColorSchemeSettingsScreenVM = viewModel() - - val advancedMode by viewModel.advancedMode.collectAsState() - - PreferenceScreen( - title = stringResource(R.string.preference_screen_colors), - helpUrl = "https://kvaesitso.mm20.de/docs/user-guide/customization/color-schemes", - topBarActions = { - var showOverflowMenu by remember { mutableStateOf(false) } - IconButton(onClick = { showOverflowMenu = true }) { - Icon(imageVector = Icons.Rounded.MoreVert, contentDescription = null) - } - DropdownMenu( - expanded = showOverflowMenu, - onDismissRequest = { showOverflowMenu = false }) { - if (advancedMode == false) { - DropdownMenuItem( - text = { Text(stringResource(R.string.preference_colors_auto_generate)) }, - onClick = { - viewModel.generateFromPrimaryColor() - showOverflowMenu = false - } - ) - } - DropdownMenuItem( - text = { - Text( - stringResource( - if (advancedMode == true) { - R.string.preference_custom_colors_simple_mode - } else { - R.string.preference_custom_colors_advanced_mode - } - ) - - ) - }, - onClick = { - viewModel.setAdvancedMode(advancedMode?.not() ?: true) - showOverflowMenu = false - } - ) - } - } - ) { - if (advancedMode == false) { - item { - PreferenceCategory { - val baseColors by viewModel.baseColors.collectAsState() - ColorPreference( - title = stringResource(R.string.preference_custom_colors_a1), - value = baseColors?.let { Color(it.accent1) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setAccent1(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = stringResource(R.string.preference_custom_colors_a2), - value = baseColors?.let { Color(it.accent2) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setAccent2(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = stringResource(R.string.preference_custom_colors_a3), - value = baseColors?.let { Color(it.accent3) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setAccent3(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = stringResource(R.string.preference_custom_colors_n1), - value = baseColors?.let { Color(it.neutral1) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setNeutral1(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = stringResource(R.string.preference_custom_colors_n2), - value = baseColors?.let { Color(it.neutral2) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setNeutral2(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = stringResource(R.string.preference_custom_colors_error), - value = baseColors?.let { Color(it.error) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = baseColors ?: return@ColorPreference - viewModel.setBaseColors( - colors.toBuilder() - .setError(it.toArgb()) - .build() - ) - } - ) - } - } - } - if (advancedMode == true) { - item { - PreferenceCategory(stringResource(R.string.preference_category_custom_colors_light)) { - val lightScheme by viewModel.lightScheme.collectAsState() - ColorPreference( - title = "Primary", - value = lightScheme?.let { Color(it.primary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setPrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Primary", - value = lightScheme?.let { Color(it.onPrimary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnPrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Primary Container", - value = lightScheme?.let { Color(it.primaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setPrimaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Primary Container", - value = lightScheme?.let { Color(it.onPrimaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnPrimaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Secondary", - value = lightScheme?.let { Color(it.secondary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSecondary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Secondary", - value = lightScheme?.let { Color(it.onSecondary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnSecondary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Secondary Container", - value = lightScheme?.let { Color(it.secondaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSecondaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Secondary Container", - value = lightScheme?.let { Color(it.onSecondaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnSecondaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Tertiary", - value = lightScheme?.let { Color(it.tertiary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setTertiary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Tertiary", - value = lightScheme?.let { Color(it.onTertiary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnTertiary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Tertiary Container", - value = lightScheme?.let { Color(it.tertiaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setTertiaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Tertiary Container", - value = lightScheme?.let { Color(it.onTertiaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnTertiaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Background", - value = lightScheme?.let { Color(it.background) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setBackground(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Background", - value = lightScheme?.let { Color(it.onBackground) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnBackground(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface", - value = lightScheme?.let { Color(it.surface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurface(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Surface", - value = lightScheme?.let { Color(it.onSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnSurface(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Dim", - value = lightScheme?.let { Color(it.surfaceDim) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceDim(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Bright", - value = lightScheme?.let { Color(it.surfaceBright) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceBright(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Container Lowest", - value = lightScheme?.let { Color(it.surfaceContainerLowest) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceContainerLowest(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container Low", - value = lightScheme?.let { Color(it.surfaceContainerLow) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceContainerLow(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container", - value = lightScheme?.let { Color(it.surfaceContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container High", - value = lightScheme?.let { Color(it.surfaceContainerHigh) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceContainerHigh(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container Highest", - value = lightScheme?.let { Color(it.surfaceContainerHighest) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceContainerHighest(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Tint", - value = lightScheme?.let { Color(it.surfaceTint) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceTint(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Variant", - value = lightScheme?.let { Color(it.surfaceVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setSurfaceVariant(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Surface Variant", - value = lightScheme?.let { Color(it.onSurfaceVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnSurfaceVariant(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Error", - value = lightScheme?.let { Color(it.error) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setError(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Error", - value = lightScheme?.let { Color(it.onError) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnError(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Error Container", - value = lightScheme?.let { Color(it.errorContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setErrorContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Error Container", - value = lightScheme?.let { Color(it.onErrorContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOnErrorContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Inverse Primary", - value = lightScheme?.let { Color(it.inversePrimary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setInversePrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Inverse Surface", - value = lightScheme?.let { Color(it.inverseSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setInverseSurface(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Inverse On Surface", - value = lightScheme?.let { Color(it.inverseOnSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setInverseOnSurface(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Outline", - value = lightScheme?.let { Color(it.outline) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOutline(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Outline Variant", - value = lightScheme?.let { Color(it.outlineVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = lightScheme ?: return@ColorPreference - viewModel.setLightScheme( - colors.toBuilder() - .setOutlineVariant(it.toArgb()) - .build() - ) - } - ) - } - - PreferenceCategory(stringResource(R.string.preference_category_custom_colors_dark)) { - val darkScheme by viewModel.darkScheme.collectAsState() - ColorPreference( - title = "Primary", - value = darkScheme?.let { Color(it.primary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setPrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Primary", - value = darkScheme?.let { Color(it.onPrimary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnPrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Primary Container", - value = darkScheme?.let { Color(it.primaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setPrimaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Primary Container", - value = darkScheme?.let { Color(it.onPrimaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnPrimaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Secondary", - value = darkScheme?.let { Color(it.secondary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSecondary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Secondary", - value = darkScheme?.let { Color(it.onSecondary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnSecondary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Secondary Container", - value = darkScheme?.let { Color(it.secondaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSecondaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Secondary Container", - value = darkScheme?.let { Color(it.onSecondaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnSecondaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Tertiary", - value = darkScheme?.let { Color(it.tertiary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setTertiary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Tertiary", - value = darkScheme?.let { Color(it.onTertiary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnTertiary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Tertiary Container", - value = darkScheme?.let { Color(it.tertiaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setTertiaryContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Tertiary Container", - value = darkScheme?.let { Color(it.onTertiaryContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnTertiaryContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Background", - value = darkScheme?.let { Color(it.background) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setBackground(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Background", - value = darkScheme?.let { Color(it.onBackground) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnBackground(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface", - value = darkScheme?.let { Color(it.surface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurface(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Surface", - value = darkScheme?.let { Color(it.onSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnSurface(it.toArgb()) - .build() - ) - } - ) - - - ColorPreference( - title = "Surface Dim", - value = darkScheme?.let { Color(it.surfaceDim) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceDim(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Bright", - value = darkScheme?.let { Color(it.surfaceBright) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceBright(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Container Lowest", - value = darkScheme?.let { Color(it.surfaceContainerLowest) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceContainerLowest(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container Low", - value = darkScheme?.let { Color(it.surfaceContainerLow) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceContainerLow(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container", - value = darkScheme?.let { Color(it.surfaceContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container High", - value = darkScheme?.let { Color(it.surfaceContainerHigh) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceContainerHigh(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Surface Container Highest", - value = darkScheme?.let { Color(it.surfaceContainerHighest) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceContainerHighest(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Tint", - value = darkScheme?.let { Color(it.surfaceTint) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceTint(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Surface Variant", - value = darkScheme?.let { Color(it.surfaceVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setSurfaceVariant(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Surface Variant", - value = darkScheme?.let { Color(it.onSurfaceVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnSurfaceVariant(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Error", - value = darkScheme?.let { Color(it.error) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setError(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Error", - value = darkScheme?.let { Color(it.onError) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnError(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Error Container", - value = darkScheme?.let { Color(it.errorContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setErrorContainer(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "On Error Container", - value = darkScheme?.let { Color(it.onErrorContainer) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOnErrorContainer(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Inverse Primary", - value = darkScheme?.let { Color(it.inversePrimary) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setInversePrimary(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Inverse Surface", - value = darkScheme?.let { Color(it.inverseSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setInverseSurface(it.toArgb()) - .build() - ) - } - ) - ColorPreference( - title = "Inverse On Surface", - value = darkScheme?.let { Color(it.inverseOnSurface) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setInverseOnSurface(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Outline", - value = darkScheme?.let { Color(it.outline) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOutline(it.toArgb()) - .build() - ) - } - ) - - ColorPreference( - title = "Outline Variant", - value = darkScheme?.let { Color(it.outlineVariant) }, - onValueChanged = { - if (it == null) return@ColorPreference - val colors = darkScheme ?: return@ColorPreference - viewModel.setDarkScheme( - colors.toBuilder() - .setOutlineVariant(it.toArgb()) - .build() - ) - } - ) - } - } - } - } -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreenVM.kt deleted file mode 100644 index f324224d..00000000 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/CustomColorSchemeSettingsScreenVM.kt +++ /dev/null @@ -1,148 +0,0 @@ -package de.mm20.launcher2.ui.settings.colorscheme - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.preferences.Settings.AppearanceSettings.CustomColors -import de.mm20.launcher2.preferences.ktx.toSettingsColorsScheme -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject -import palettes.CorePalette -import palettes.TonalPalette -import scheme.Scheme - -class CustomColorSchemeSettingsScreenVM : ViewModel(), KoinComponent { - private val dataStore: LauncherDataStore by inject() - - val advancedMode = dataStore.data.map { it.appearance.customColors.advancedMode } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setAdvancedMode(advancedMode: Boolean) { - viewModelScope.launch { - val lightScheme = dataStore.updateData { - val customColors = it.appearance.customColors.toBuilder() - .setAdvancedMode(advancedMode) - it.toBuilder() - .setAppearance( - it.appearance.toBuilder() - .setCustomColors(customColors) - ) - .build() - }.appearance.customColors.lightScheme - - if (!advancedMode) { - setBaseColors(CustomColors.BaseColors - .newBuilder() - .setAccent1(lightScheme.primary) - .setAccent2(lightScheme.secondary) - .setAccent3(lightScheme.tertiary) - .setNeutral1(lightScheme.surface) - .setNeutral2(lightScheme.surface) - .setError(lightScheme.error) - .build() - ) - } - } - } - - fun generateFromPrimaryColor() { - viewModelScope.launch { - val primary = dataStore.data.map { it.appearance.customColors.baseColors.accent1 }.first() - val scheme = Scheme.light(primary) - setBaseColors( - CustomColors.BaseColors.newBuilder() - .setAccent1(scheme.primary) - .setAccent2(scheme.secondary) - .setAccent3(scheme.tertiary) - .setNeutral1(scheme.surface) - .setNeutral2(scheme.outline) - .setError(scheme.error) - .build() - ) - } - } - - val baseColors = dataStore.data.map { it.appearance.customColors.baseColors } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setBaseColors(baseColors: CustomColors.BaseColors) { - viewModelScope.launch { - dataStore.updateData { - it.toBuilder() - .setAppearance( - it.appearance.toBuilder() - .setCustomColors( - it.appearance.customColors.toBuilder() - .setBaseColors(baseColors) - ) - ) - .build() - } - setDarkScheme(baseColorsToDarkScheme(baseColors)) - setLightScheme(baseColorsToLightScheme(baseColors)) - } - } - - val darkScheme = dataStore.data.map { it.appearance.customColors.darkScheme } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setDarkScheme(darkScheme: CustomColors.Scheme) { - viewModelScope.launch { - dataStore.updateData { - it.toBuilder() - .setAppearance( - it.appearance.toBuilder() - .setCustomColors( - it.appearance.customColors.toBuilder() - .setDarkScheme(darkScheme) - ) - ) - .build() - } - } - } - - val lightScheme = dataStore.data.map { it.appearance.customColors.lightScheme } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - fun setLightScheme(lightScheme: CustomColors.Scheme) { - viewModelScope.launch { - dataStore.updateData { - it.toBuilder() - .setAppearance( - it.appearance.toBuilder() - .setCustomColors( - it.appearance.customColors.toBuilder() - .setLightScheme(lightScheme) - ) - ) - .build() - } - } - } - - private fun baseColorsToDarkScheme(baseColors: CustomColors.BaseColors): CustomColors.Scheme { - val a1 = TonalPalette.fromInt(baseColors.accent1) - val a2 = TonalPalette.fromInt(baseColors.accent2) - val a3 = TonalPalette.fromInt(baseColors.accent3) - val n1 = TonalPalette.fromInt(baseColors.neutral1) - val n2 = TonalPalette.fromInt(baseColors.neutral2) - val error = TonalPalette.fromInt(baseColors.error) - - val scheme = Scheme.darkFromCorePalette(CorePalette(a1, a2, a3, n1, n2, error)) - return scheme.toSettingsColorsScheme() - } - - private fun baseColorsToLightScheme(baseColors: CustomColors.BaseColors): CustomColors.Scheme { - val a1 = TonalPalette.fromInt(baseColors.accent1) - val a2 = TonalPalette.fromInt(baseColors.accent2) - val a3 = TonalPalette.fromInt(baseColors.accent3) - val n1 = TonalPalette.fromInt(baseColors.neutral1) - val n2 = TonalPalette.fromInt(baseColors.neutral2) - val error = TonalPalette.fromInt(baseColors.error) - - val scheme = Scheme.lightFromCorePalette(CorePalette(a1, a2, a3, n1, n2, error)) - return scheme.toSettingsColorsScheme() - } -} \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreen.kt index 9909af74..5c5e67f8 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreen.kt @@ -77,6 +77,9 @@ fun ThemesSettingsScreen() { ) } } + }, + onClick = { + viewModel.selectTheme(theme) } ) Row( diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreenVM.kt index c98d8e59..b8447da5 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ThemesSettingsScreenVM.kt @@ -2,20 +2,31 @@ package de.mm20.launcher2.ui.settings.colorscheme import android.util.Log import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.google.protobuf.ByteString +import de.mm20.launcher2.ktx.toBytes +import de.mm20.launcher2.preferences.LauncherDataStore import de.mm20.launcher2.themes.DefaultThemeId import de.mm20.launcher2.themes.Theme import de.mm20.launcher2.themes.ThemeRepository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject import java.util.UUID -class ThemesSettingsScreenVM: ViewModel(), KoinComponent { +class ThemesSettingsScreenVM : ViewModel(), KoinComponent { private val themeRepository: ThemeRepository by inject() + private val dataStore: LauncherDataStore by inject() - val selectedTheme: Flow = flowOf(DefaultThemeId) + val selectedTheme: Flow = dataStore.data.map { + it.appearance.themeId?.takeIf { it.isNotEmpty() }?.let { + UUID.fromString(it) + } ?: DefaultThemeId + } val themes: Flow> = themeRepository.getThemes() fun getTheme(id: UUID): Flow { @@ -23,7 +34,19 @@ class ThemesSettingsScreenVM: ViewModel(), KoinComponent { } fun updateTheme(theme: Theme) { - Log.d("MM20", "updateTheme: $theme") themeRepository.updateTheme(theme) } + + fun selectTheme(theme: Theme) { + viewModelScope.launch { + dataStore.updateData { + it.toBuilder() + .setAppearance( + it.appearance.toBuilder() + .setThemeId(theme.id.toString()) + ) + .build() + } + } + } } \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/theme/LauncherTheme.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/theme/LauncherTheme.kt index 9525271a..67859341 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/theme/LauncherTheme.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/theme/LauncherTheme.kt @@ -18,12 +18,15 @@ import de.mm20.launcher2.preferences.Settings import de.mm20.launcher2.preferences.Settings.AppearanceSettings import de.mm20.launcher2.themes.DefaultThemeId import de.mm20.launcher2.themes.Theme +import de.mm20.launcher2.themes.ThemeRepository import de.mm20.launcher2.ui.locals.LocalDarkTheme import de.mm20.launcher2.ui.theme.colorscheme.* import de.mm20.launcher2.ui.theme.typography.DefaultTypography import de.mm20.launcher2.ui.theme.typography.getDeviceDefaultTypography +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import org.koin.androidx.compose.inject +import java.util.UUID @Composable @@ -33,15 +36,17 @@ fun LauncherTheme( val context = LocalContext.current val dataStore: LauncherDataStore by inject() + val themeRepository: ThemeRepository by inject() - val colorSchemePreference by remember { + val theme by remember { dataStore.data.map { - if (it.easterEgg) Settings.AppearanceSettings.ColorScheme.EasterEgg - else it.appearance.colorScheme + it.appearance.themeId.takeIf { it.isNotEmpty() }?.let { + UUID.fromString(it) + } + }.flatMapLatest { + themeRepository.getThemeOrDefault(it) } - }.collectAsState( - AppearanceSettings.ColorScheme.Default - ) + }.collectAsState(themeRepository.getDefaultTheme()) val themePreference by remember { dataStore.data.map { it.appearance.theme } }.collectAsState( AppearanceSettings.Theme.System @@ -62,7 +67,11 @@ fun LauncherTheme( } }.collectAsState(RoundedCornerShape(0f)) - val colorScheme by colorSchemeAsState(colorSchemePreference, darkTheme) + val colorScheme = if (darkTheme) { + darkColorSchemeOf(theme) + } else { + lightColorSchemeOf(theme) + } val font by remember { dataStore.data.map { it.appearance.font } }.collectAsState( AppearanceSettings.Font.Outfit @@ -90,54 +99,6 @@ fun LauncherTheme( } } -@Composable -fun colorSchemeAsState( - colorScheme: AppearanceSettings.ColorScheme, - darkTheme: Boolean -): MutableState { - val dataStore: LauncherDataStore by inject() - - when (colorScheme) { - AppearanceSettings.ColorScheme.BlackAndWhite -> { - return remember(darkTheme) { - mutableStateOf( - if (darkTheme) DarkBlackAndWhiteColorScheme else LightBlackAndWhiteColorScheme - ) - } - } - AppearanceSettings.ColorScheme.EasterEgg -> { - return remember(darkTheme) { - mutableStateOf( - if (darkTheme) DarkEasterEggColorScheme else LightEasterEggColorScheme - ) - } - } - AppearanceSettings.ColorScheme.Custom -> { - val colors by remember(darkTheme) { - dataStore.data.map { if (darkTheme) it.appearance.customColors.darkScheme else it.appearance.customColors.lightScheme } - }.collectAsState(null) - val state = remember(colors, darkTheme) { - mutableStateOf( - colors?.let { CustomColorScheme(it) } - ?: if (darkTheme) DarkDefaultColorScheme else LightDefaultColorScheme - ) - } - return state - } - else -> { - val scheme = if (darkTheme) { - darkColorSchemeOf(Theme(DefaultThemeId, name = "")) - } else { - lightColorSchemeOf(Theme(DefaultThemeId, name = "")) - } - return remember(scheme, darkTheme) { - mutableStateOf(scheme) - } - } - } - -} - fun getTypography(context: Context, font: AppearanceSettings.Font?): Typography { return when (font) { AppearanceSettings.Font.SystemDefault -> getDeviceDefaultTypography(context) diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt index b5af78bf..309d05c7 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/DataStore.kt @@ -22,7 +22,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore( } ) -internal const val SchemaVersion = 16 +internal const val SchemaVersion = 17 internal fun getMigrations(context: Context): List> { return listOf( @@ -42,5 +42,6 @@ internal fun getMigrations(context: Context): List> { Migration_13_14(), Migration_14_15(), Migration_15_16(), + Migration_16_17(), ) } \ No newline at end of file diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt index 12d65ab4..036e8563 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/Defaults.kt @@ -5,6 +5,7 @@ import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.preferences.Settings.SearchBarSettings.SearchBarColors import de.mm20.launcher2.preferences.ktx.toSettingsColorsScheme import scheme.Scheme +import java.util.UUID fun createFactorySettings(context: Context): Settings { return Settings.newBuilder() @@ -12,16 +13,9 @@ fun createFactorySettings(context: Context): Settings { Settings.AppearanceSettings .newBuilder() .setTheme(Settings.AppearanceSettings.Theme.System) - .setColorScheme(Settings.AppearanceSettings.ColorScheme.Default) .setDimWallpaper(false) .setBlurWallpaper(true) - .setCustomColors( - Settings.AppearanceSettings.CustomColors.newBuilder() - .setAdvancedMode(false) - .setBaseColors(DefaultCustomColorsBase) - .setLightScheme(DefaultLightCustomColorScheme) - .setDarkScheme(DefaultDarkCustomColorScheme) - ) + .setThemeId(UUID(0L, 0L).toString()) .setFont(Settings.AppearanceSettings.Font.Outfit) .build() ) diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_16_17.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_16_17.kt new file mode 100644 index 00000000..cd4fa76c --- /dev/null +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/migrations/Migration_16_17.kt @@ -0,0 +1,19 @@ +package de.mm20.launcher2.preferences.migrations + +import de.mm20.launcher2.preferences.Settings +import java.util.UUID + +class Migration_16_17: VersionedMigration(16, 17) { + override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder { + return builder.setAppearance( + builder.appearance.toBuilder() + .setThemeId( + when(builder.appearance.colorScheme) { + Settings.AppearanceSettings.ColorScheme.BlackAndWhite -> UUID(0L, 1L) + Settings.AppearanceSettings.ColorScheme.Custom -> UUID(1L, 1L) + else -> UUID(0L, 0L) + }.toString() + ) + ) + } +} \ No newline at end of file diff --git a/core/preferences/src/main/proto/settings.proto b/core/preferences/src/main/proto/settings.proto index 8547184d..bd7ec589 100644 --- a/core/preferences/src/main/proto/settings.proto +++ b/core/preferences/src/main/proto/settings.proto @@ -19,7 +19,7 @@ message Settings { Custom = 3; EasterEgg = 4; } - ColorScheme color_scheme = 6; + ColorScheme color_scheme = 6 [deprecated = true]; message CustomColors { bool advanced_mode = 1; message BaseColors { @@ -72,7 +72,7 @@ message Settings { Scheme light_scheme = 3; Scheme dark_scheme = 4; } - CustomColors custom_colors = 8; + CustomColors custom_colors = 8 [deprecated = true]; bool dim_wallpaper = 7; /** @@ -87,6 +87,8 @@ message Settings { Font font = 10; bool blur_wallpaper = 11; + // UUID of the selected theme + string theme_id = 12; } AppearanceSettings appearance = 2; diff --git a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt index bb947631..613b3318 100644 --- a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt +++ b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt @@ -44,7 +44,8 @@ class ThemeRepository( } } - fun getThemeOrDefault(id: UUID): Flow { + fun getThemeOrDefault(id: UUID?): Flow { + if (id == null) return flowOf(getDefaultTheme()) return getTheme(id).map { it ?: getDefaultTheme() } }