Add custom color schemes
This commit is contained in:
parent
2ca05d34f0
commit
08731887cb
@ -387,6 +387,18 @@
|
||||
<string name="preference_screen_colors">Color scheme</string>
|
||||
<string name="preference_colors_default">Default</string>
|
||||
<string name="preference_colors_bw">Black and White</string>
|
||||
<string name="preference_colors_custom">Custom</string>
|
||||
<string name="preference_custom_colors_a1">Primary</string>
|
||||
<string name="preference_custom_colors_a2">Secondary</string>
|
||||
<string name="preference_custom_colors_a3">Tertiary</string>
|
||||
<string name="preference_custom_colors_n1">Neutral</string>
|
||||
<string name="preference_custom_colors_n2">Neutral Variant</string>
|
||||
<string name="preference_custom_colors_error">Error</string>
|
||||
<string name="preference_custom_colors_advanced_mode">Advanced mode</string>
|
||||
<string name="preference_custom_colors_simple_mode">Simple mode</string>
|
||||
<string name="preference_colors_auto_generate">Generate from primary color</string>
|
||||
<string name="preference_category_custom_colors_light">Light color scheme</string>
|
||||
<string name="preference_category_custom_colors_dark">Dark color scheme</string>
|
||||
<string name="preference_screen_about">About</string>
|
||||
<string name="preference_version">Version</string>
|
||||
<string name="preference_category_links">Links</string>
|
||||
|
||||
@ -67,5 +67,6 @@ dependencies {
|
||||
implementation(project(":i18n"))
|
||||
implementation(project(":base"))
|
||||
implementation(project(":crashreporter"))
|
||||
implementation(project(":material-color-utilities"))
|
||||
|
||||
}
|
||||
@ -20,6 +20,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
|
||||
Migration_2_3(),
|
||||
Migration_3_4(),
|
||||
Migration_4_5(),
|
||||
Migration_5_6(),
|
||||
)
|
||||
},
|
||||
corruptionHandler = ReplaceFileCorruptionHandler {
|
||||
@ -29,4 +30,4 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
|
||||
}
|
||||
)
|
||||
|
||||
internal const val SchemaVersion = 5
|
||||
internal const val SchemaVersion = 6
|
||||
@ -1,6 +1,7 @@
|
||||
package de.mm20.launcher2.preferences
|
||||
|
||||
import android.content.Context
|
||||
import scheme.Scheme
|
||||
|
||||
fun createFactorySettings(context: Context): Settings {
|
||||
return Settings.newBuilder()
|
||||
@ -10,6 +11,12 @@ fun createFactorySettings(context: Context): Settings {
|
||||
.setTheme(Settings.AppearanceSettings.Theme.System)
|
||||
.setColorScheme(Settings.AppearanceSettings.ColorScheme.Default)
|
||||
.setDimWallpaper(false)
|
||||
.setCustomColors(Settings.AppearanceSettings.CustomColors.newBuilder()
|
||||
.setAdvancedMode(false)
|
||||
.setBaseColors(DefaultCustomColorsBase)
|
||||
.setLightScheme(DefaultLightCustomColorScheme)
|
||||
.setDarkScheme(DefaultDarkCustomColorScheme)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
.setWeather(
|
||||
@ -70,7 +77,7 @@ fun createFactorySettings(context: Context): Settings {
|
||||
Settings.AppShortcutSearchSettings
|
||||
.newBuilder()
|
||||
.setEnabled(true)
|
||||
)
|
||||
)
|
||||
.setCalculatorSearch(
|
||||
Settings.CalculatorSearchSettings
|
||||
.newBuilder()
|
||||
@ -140,4 +147,83 @@ fun createFactorySettings(context: Context): Settings {
|
||||
.setOpacity(1f)
|
||||
)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
internal val DefaultCustomColorsBase: Settings.AppearanceSettings.CustomColors.BaseColors
|
||||
get() {
|
||||
val scheme = Scheme.light(0xFFACE330.toInt())
|
||||
return Settings.AppearanceSettings.CustomColors.BaseColors.newBuilder()
|
||||
.setAccent1(scheme.primary)
|
||||
.setAccent2(scheme.secondary)
|
||||
.setAccent3(scheme.tertiary)
|
||||
.setNeutral1(scheme.surface)
|
||||
.setNeutral2(scheme.surfaceVariant)
|
||||
.setError(scheme.error)
|
||||
.build()
|
||||
}
|
||||
|
||||
internal val DefaultLightCustomColorScheme: Settings.AppearanceSettings.CustomColors.Scheme
|
||||
get() {
|
||||
val scheme = Scheme.light(0xFFACE330.toInt())
|
||||
return Settings.AppearanceSettings.CustomColors.Scheme.newBuilder()
|
||||
.setPrimary(scheme.primary)
|
||||
.setOnPrimary(scheme.onPrimary)
|
||||
.setPrimaryContainer(scheme.primaryContainer)
|
||||
.setOnPrimaryContainer(scheme.onPrimaryContainer)
|
||||
.setSecondary(scheme.secondary)
|
||||
.setOnSecondary(scheme.onSecondary)
|
||||
.setSecondaryContainer(scheme.secondaryContainer)
|
||||
.setOnSecondaryContainer(scheme.onSecondaryContainer)
|
||||
.setTertiary(scheme.tertiary)
|
||||
.setOnTertiary(scheme.onTertiary)
|
||||
.setTertiaryContainer(scheme.tertiaryContainer)
|
||||
.setOnTertiaryContainer(scheme.onTertiaryContainer)
|
||||
.setBackground(scheme.background)
|
||||
.setOnBackground(scheme.onBackground)
|
||||
.setSurface(scheme.surface)
|
||||
.setOnSurface(scheme.onSurface)
|
||||
.setSurfaceVariant(scheme.surfaceVariant)
|
||||
.setOnSurfaceVariant(scheme.onSurfaceVariant)
|
||||
.setError(scheme.error)
|
||||
.setOnError(scheme.onError)
|
||||
.setErrorContainer(scheme.errorContainer)
|
||||
.setOnErrorContainer(scheme.onErrorContainer)
|
||||
.setInverseSurface(scheme.inverseSurface)
|
||||
.setInverseOnSurface(scheme.inverseOnSurface)
|
||||
.setInversePrimary(scheme.inversePrimary)
|
||||
.setOutline(scheme.outline)
|
||||
.build()
|
||||
}
|
||||
|
||||
internal val DefaultDarkCustomColorScheme: Settings.AppearanceSettings.CustomColors.Scheme
|
||||
get() {
|
||||
val scheme = Scheme.dark(0xFFACE330.toInt())
|
||||
return Settings.AppearanceSettings.CustomColors.Scheme.newBuilder()
|
||||
.setPrimary(scheme.primary)
|
||||
.setOnPrimary(scheme.onPrimary)
|
||||
.setPrimaryContainer(scheme.primaryContainer)
|
||||
.setOnPrimaryContainer(scheme.onPrimaryContainer)
|
||||
.setSecondary(scheme.secondary)
|
||||
.setOnSecondary(scheme.onSecondary)
|
||||
.setSecondaryContainer(scheme.secondaryContainer)
|
||||
.setOnSecondaryContainer(scheme.onSecondaryContainer)
|
||||
.setTertiary(scheme.tertiary)
|
||||
.setOnTertiary(scheme.onTertiary)
|
||||
.setTertiaryContainer(scheme.tertiaryContainer)
|
||||
.setOnTertiaryContainer(scheme.onTertiaryContainer)
|
||||
.setBackground(scheme.background)
|
||||
.setOnBackground(scheme.onBackground)
|
||||
.setSurface(scheme.surface)
|
||||
.setOnSurface(scheme.onSurface)
|
||||
.setSurfaceVariant(scheme.surfaceVariant)
|
||||
.setOnSurfaceVariant(scheme.onSurfaceVariant)
|
||||
.setError(scheme.error)
|
||||
.setOnError(scheme.onError)
|
||||
.setErrorContainer(scheme.errorContainer)
|
||||
.setOnErrorContainer(scheme.onErrorContainer)
|
||||
.setInverseSurface(scheme.inverseSurface)
|
||||
.setInverseOnSurface(scheme.inverseOnSurface)
|
||||
.setInversePrimary(scheme.inversePrimary)
|
||||
.setOutline(scheme.outline)
|
||||
.build()
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package de.mm20.launcher2.preferences.migrations
|
||||
|
||||
import de.mm20.launcher2.preferences.DefaultCustomColorsBase
|
||||
import de.mm20.launcher2.preferences.DefaultDarkCustomColorScheme
|
||||
import de.mm20.launcher2.preferences.DefaultLightCustomColorScheme
|
||||
import de.mm20.launcher2.preferences.Settings
|
||||
|
||||
class Migration_5_6: VersionedMigration(5, 6) {
|
||||
override suspend fun applyMigrations(builder: Settings.Builder): Settings.Builder {
|
||||
return builder.setAppearance(
|
||||
builder.appearance.toBuilder()
|
||||
.setCustomColors(Settings.AppearanceSettings.CustomColors.newBuilder()
|
||||
.setAdvancedMode(false)
|
||||
.setBaseColors(DefaultCustomColorsBase)
|
||||
.setLightScheme(DefaultLightCustomColorScheme)
|
||||
.setDarkScheme(DefaultDarkCustomColorScheme)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -16,8 +16,52 @@ message Settings {
|
||||
Default = 0;
|
||||
BlackAndWhite = 1;
|
||||
DebugMaterialYouCompat = 2;
|
||||
Custom = 3;
|
||||
}
|
||||
ColorScheme color_scheme = 6;
|
||||
message CustomColors {
|
||||
bool advanced_mode = 1;
|
||||
message BaseColors {
|
||||
uint32 accent1 = 1;
|
||||
uint32 accent2 = 2;
|
||||
uint32 accent3 = 3;
|
||||
uint32 neutral1 = 4;
|
||||
uint32 neutral2 = 5;
|
||||
uint32 error = 6;
|
||||
}
|
||||
BaseColors base_colors = 2;
|
||||
message Scheme {
|
||||
uint32 primary = 1;
|
||||
uint32 on_primary = 2;
|
||||
uint32 primary_container = 3;
|
||||
uint32 on_primary_container = 4;
|
||||
uint32 secondary = 5;
|
||||
uint32 on_secondary = 6;
|
||||
uint32 secondary_container = 7;
|
||||
uint32 on_secondary_container = 8;
|
||||
uint32 tertiary = 9;
|
||||
uint32 on_tertiary = 10;
|
||||
uint32 tertiary_container = 11;
|
||||
uint32 on_tertiary_container = 12;
|
||||
uint32 background = 13;
|
||||
uint32 on_background = 14;
|
||||
uint32 surface = 15;
|
||||
uint32 on_surface = 16;
|
||||
uint32 surface_variant = 17;
|
||||
uint32 on_surface_variant = 18;
|
||||
uint32 outline = 19;
|
||||
uint32 inverse_surface = 20;
|
||||
uint32 inverse_on_surface = 21;
|
||||
uint32 inverse_primary = 22;
|
||||
uint32 error = 23;
|
||||
uint32 on_error = 24;
|
||||
uint32 error_container = 25;
|
||||
uint32 on_error_container = 26;
|
||||
}
|
||||
Scheme light_scheme = 3;
|
||||
Scheme dark_scheme = 4;
|
||||
}
|
||||
CustomColors custom_colors = 8;
|
||||
bool dim_wallpaper = 7;
|
||||
}
|
||||
AppearanceSettings appearance = 2;
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
package de.mm20.launcher2.ui.component.preferences
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.godaddy.android.colorpicker.ClassicColorPicker
|
||||
import de.mm20.launcher2.ui.ktx.toHexString
|
||||
|
||||
@Composable
|
||||
fun ColorPreference(
|
||||
title: String,
|
||||
summary: String? = null,
|
||||
value: Color?,
|
||||
onValueChanged: (Color?) -> Unit = {}
|
||||
) {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
title = title,
|
||||
summary = summary,
|
||||
controls = {
|
||||
value?.let {
|
||||
Surface(
|
||||
color = it,
|
||||
shape = CircleShape,
|
||||
modifier = Modifier
|
||||
.padding(vertical = 12.dp)
|
||||
.size(36.dp)
|
||||
) {}
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
showDialog = true
|
||||
}
|
||||
)
|
||||
if (showDialog) {
|
||||
var color by remember(value) { mutableStateOf(value) }
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDialog = false },
|
||||
title = {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
|
||||
ClassicColorPicker(
|
||||
color = value ?: Color.Black,
|
||||
onColorChanged = {
|
||||
color = it.toColor()
|
||||
},
|
||||
showAlphaBar = false,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(200.dp)
|
||||
)
|
||||
|
||||
var hexValue by remember(color) {
|
||||
mutableStateOf(
|
||||
color?.toHexString() ?: "#000000"
|
||||
)
|
||||
}
|
||||
|
||||
TextField(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
value = hexValue,
|
||||
onValueChange = {
|
||||
hexValue = it
|
||||
if (Regex("#[0-9a-fA-F]{6}").matches(it)) {
|
||||
val hex = it.substring(1).toIntOrNull(16) ?: return@TextField
|
||||
color = Color(hex).copy(alpha = 1f)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
onValueChanged(color)
|
||||
showDialog = false
|
||||
}) {
|
||||
Text(stringResource(android.R.string.ok))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,7 @@ import de.mm20.launcher2.ui.settings.calendarwidget.CalendarWidgetSettingsScreen
|
||||
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.crashreporter.CrashReportScreen
|
||||
import de.mm20.launcher2.ui.settings.crashreporter.CrashReporterScreen
|
||||
import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
||||
@ -88,6 +89,9 @@ class SettingsActivity : BaseActivity() {
|
||||
composable("settings/appearance/colorscheme") {
|
||||
ColorSchemeSettingsScreen()
|
||||
}
|
||||
composable("settings/appearance/colorscheme/custom") {
|
||||
CustomColorSchemeSettingsScreen()
|
||||
}
|
||||
composable("settings/appearance/cards") {
|
||||
CardsSettingsScreen()
|
||||
}
|
||||
|
||||
@ -71,6 +71,7 @@ fun AppearanceSettingsScreen() {
|
||||
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 = {
|
||||
|
||||
@ -22,11 +22,13 @@ 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.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 {
|
||||
@ -36,6 +38,7 @@ fun ColorSchemeSettingsScreen() {
|
||||
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)) {
|
||||
@ -47,7 +50,12 @@ fun ColorSchemeSettingsScreen() {
|
||||
Preference(
|
||||
title = cs.second,
|
||||
icon = if (colorScheme == cs.first) Icons.Rounded.RadioButtonChecked else Icons.Rounded.RadioButtonUnchecked,
|
||||
onClick = { viewModel.setColorScheme(cs.first) },
|
||||
onClick = {
|
||||
viewModel.setColorScheme(cs.first)
|
||||
if (cs.first == AppearanceSettings.ColorScheme.Custom) {
|
||||
navController?.navigate("settings/appearance/colorscheme/custom")
|
||||
}
|
||||
},
|
||||
controls = {
|
||||
ColorSchemePreview(scheme)
|
||||
}
|
||||
|
||||
@ -0,0 +1,852 @@
|
||||
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.runtime.livedata.observeAsState
|
||||
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.observeAsState()
|
||||
|
||||
PreferenceScreen(
|
||||
title = stringResource(R.string.preference_screen_colors),
|
||||
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("Generate from primary color") },
|
||||
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.observeAsState()
|
||||
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.observeAsState()
|
||||
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 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()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
PreferenceCategory(stringResource(R.string.preference_category_custom_colors_light)) {
|
||||
val darkScheme by viewModel.darkScheme.observeAsState()
|
||||
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 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()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,194 @@
|
||||
package de.mm20.launcher2.ui.settings.colorscheme
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.preferences.LauncherDataStore
|
||||
import de.mm20.launcher2.preferences.Settings
|
||||
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.CustomColors
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
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 }.asLiveData()
|
||||
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.surfaceVariant)
|
||||
.setError(scheme.error)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val baseColors = dataStore.data.map { it.appearance.customColors.baseColors }.asLiveData()
|
||||
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 }.asLiveData()
|
||||
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 }.asLiveData()
|
||||
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)
|
||||
|
||||
return CustomColors.Scheme.newBuilder()
|
||||
.setPrimary(a1.tone(80))
|
||||
.setOnPrimary(a1.tone(20))
|
||||
.setPrimaryContainer(a1.tone(30))
|
||||
.setOnPrimaryContainer(a1.tone(90))
|
||||
.setSecondary(a2.tone(80))
|
||||
.setOnSecondary(a2.tone(20))
|
||||
.setSecondaryContainer(a2.tone(30))
|
||||
.setOnSecondaryContainer(a2.tone(90))
|
||||
.setTertiary(a3.tone(80))
|
||||
.setOnTertiary(a3.tone(20))
|
||||
.setTertiaryContainer(a3.tone(30))
|
||||
.setOnTertiaryContainer(a3.tone(90))
|
||||
.setError(error.tone(80))
|
||||
.setOnError(error.tone(20))
|
||||
.setErrorContainer(error.tone(30))
|
||||
.setOnErrorContainer(error.tone(80))
|
||||
.setBackground(n1.tone(10))
|
||||
.setOnBackground(n1.tone(90))
|
||||
.setSurface(n1.tone(10))
|
||||
.setOnSurface(n1.tone(90))
|
||||
.setSurfaceVariant(n2.tone(30))
|
||||
.setOnSurfaceVariant(n2.tone(80))
|
||||
.setOutline(n2.tone(60))
|
||||
.setInverseSurface(n1.tone(90))
|
||||
.setInverseOnSurface(n1.tone(20))
|
||||
.setInversePrimary(a1.tone(40))
|
||||
.build()
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
return CustomColors.Scheme.newBuilder()
|
||||
.setPrimary(a1.tone(40))
|
||||
.setOnPrimary(a1.tone(100))
|
||||
.setPrimaryContainer(a1.tone(90))
|
||||
.setOnPrimaryContainer(a1.tone(10))
|
||||
.setSecondary(a2.tone(40))
|
||||
.setOnSecondary(a2.tone(100))
|
||||
.setSecondaryContainer(a2.tone(90))
|
||||
.setOnSecondaryContainer(a2.tone(10))
|
||||
.setTertiary(a3.tone(40))
|
||||
.setOnTertiary(a3.tone(100))
|
||||
.setTertiaryContainer(a3.tone(90))
|
||||
.setOnTertiaryContainer(a3.tone(10))
|
||||
.setError(error.tone(40))
|
||||
.setOnError(error.tone(100))
|
||||
.setErrorContainer(error.tone(90))
|
||||
.setOnErrorContainer(error.tone(10))
|
||||
.setBackground(n1.tone(99))
|
||||
.setOnBackground(n1.tone(10))
|
||||
.setSurface(n1.tone(99))
|
||||
.setOnSurface(n1.tone(10))
|
||||
.setSurfaceVariant(n2.tone(90))
|
||||
.setOnSurfaceVariant(n2.tone(30))
|
||||
.setOutline(n2.tone(50))
|
||||
.setInverseSurface(n1.tone(20))
|
||||
.setInverseOnSurface(n1.tone(95))
|
||||
.setInversePrimary(a1.tone(80))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,18 @@ fun colorSchemeAsState(colorScheme: AppearanceSettings.ColorScheme): MutableStat
|
||||
)
|
||||
}
|
||||
}
|
||||
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 -> {
|
||||
if (Build.VERSION.SDK_INT >= 27 && (Build.VERSION.SDK_INT < 31 || colorScheme == AppearanceSettings.ColorScheme.DebugMaterialYouCompat)) {
|
||||
val wallpaperColors by wallpaperColorsAsState()
|
||||
@ -71,7 +83,9 @@ fun colorSchemeAsState(colorScheme: AppearanceSettings.ColorScheme): MutableStat
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
return remember(darkTheme) {
|
||||
mutableStateOf(
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(
|
||||
context
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package de.mm20.launcher2.ui.theme.colorscheme
|
||||
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import de.mm20.launcher2.preferences.Settings
|
||||
|
||||
fun CustomColorScheme(colors: Settings.AppearanceSettings.CustomColors.Scheme) : ColorScheme {
|
||||
return ColorScheme(
|
||||
primary = Color(colors.primary),
|
||||
onPrimary = Color(colors.onPrimary),
|
||||
primaryContainer = Color(colors.primaryContainer),
|
||||
onPrimaryContainer = Color(colors.onPrimaryContainer),
|
||||
secondary = Color(colors.secondary),
|
||||
onSecondary = Color(colors.onSecondary),
|
||||
secondaryContainer = Color(colors.secondaryContainer),
|
||||
onSecondaryContainer = Color(colors.onSecondaryContainer),
|
||||
tertiary = Color(colors.tertiary),
|
||||
onTertiary = Color(colors.onTertiary),
|
||||
tertiaryContainer = Color(colors.tertiaryContainer),
|
||||
onTertiaryContainer = Color(colors.onTertiaryContainer),
|
||||
background = Color(colors.background),
|
||||
onBackground = Color(colors.onBackground),
|
||||
surface = Color(colors.surface),
|
||||
onSurface = Color(colors.onSurface),
|
||||
surfaceVariant = Color(colors.surfaceVariant),
|
||||
onSurfaceVariant = Color(colors.onSurfaceVariant),
|
||||
outline = Color(colors.outline),
|
||||
inverseSurface = Color(colors.inverseSurface),
|
||||
inverseOnSurface = Color(colors.inverseOnSurface),
|
||||
inversePrimary = Color(colors.inversePrimary),
|
||||
surfaceTint = Color(colors.primary),
|
||||
error = Color(colors.error),
|
||||
onError = Color(colors.onError),
|
||||
errorContainer = Color(colors.errorContainer),
|
||||
onErrorContainer = Color(colors.onErrorContainer),
|
||||
)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user