Custom color schemes v2 - part 3

Store preferences and apply color schemes
This commit is contained in:
MM20 2023-08-23 19:02:37 +02:00
parent f128469f68
commit 1a86aa018e
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
15 changed files with 93 additions and 1506 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -77,6 +77,9 @@ fun ThemesSettingsScreen() {
)
}
}
},
onClick = {
viewModel.selectTheme(theme)
}
)
Row(

View File

@ -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<UUID?> = flowOf(DefaultThemeId)
val selectedTheme: Flow<UUID?> = dataStore.data.map {
it.appearance.themeId?.takeIf { it.isNotEmpty() }?.let {
UUID.fromString(it)
} ?: DefaultThemeId
}
val themes: Flow<List<Theme>> = themeRepository.getThemes()
fun getTheme(id: UUID): Flow<Theme?> {
@ -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()
}
}
}
}

View File

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

View File

@ -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<DataMigration<Settings>> {
return listOf(
@ -42,5 +42,6 @@ internal fun getMigrations(context: Context): List<DataMigration<Settings>> {
Migration_13_14(),
Migration_14_15(),
Migration_15_16(),
Migration_16_17(),
)
}

View File

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

View File

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

View File

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

View File

@ -44,7 +44,8 @@ class ThemeRepository(
}
}
fun getThemeOrDefault(id: UUID): Flow<Theme> {
fun getThemeOrDefault(id: UUID?): Flow<Theme> {
if (id == null) return flowOf(getDefaultTheme())
return getTheme(id).map { it ?: getDefaultTheme() }
}