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_screen_colors">Color scheme</string>
|
||||||
<string name="preference_colors_default">Default</string>
|
<string name="preference_colors_default">Default</string>
|
||||||
<string name="preference_colors_bw">Black and White</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_screen_about">About</string>
|
||||||
<string name="preference_version">Version</string>
|
<string name="preference_version">Version</string>
|
||||||
<string name="preference_category_links">Links</string>
|
<string name="preference_category_links">Links</string>
|
||||||
|
|||||||
@ -67,5 +67,6 @@ dependencies {
|
|||||||
implementation(project(":i18n"))
|
implementation(project(":i18n"))
|
||||||
implementation(project(":base"))
|
implementation(project(":base"))
|
||||||
implementation(project(":crashreporter"))
|
implementation(project(":crashreporter"))
|
||||||
|
implementation(project(":material-color-utilities"))
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -20,6 +20,7 @@ internal val Context.dataStore: LauncherDataStore by dataStore(
|
|||||||
Migration_2_3(),
|
Migration_2_3(),
|
||||||
Migration_3_4(),
|
Migration_3_4(),
|
||||||
Migration_4_5(),
|
Migration_4_5(),
|
||||||
|
Migration_5_6(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
corruptionHandler = ReplaceFileCorruptionHandler {
|
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
|
package de.mm20.launcher2.preferences
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import scheme.Scheme
|
||||||
|
|
||||||
fun createFactorySettings(context: Context): Settings {
|
fun createFactorySettings(context: Context): Settings {
|
||||||
return Settings.newBuilder()
|
return Settings.newBuilder()
|
||||||
@ -10,6 +11,12 @@ fun createFactorySettings(context: Context): Settings {
|
|||||||
.setTheme(Settings.AppearanceSettings.Theme.System)
|
.setTheme(Settings.AppearanceSettings.Theme.System)
|
||||||
.setColorScheme(Settings.AppearanceSettings.ColorScheme.Default)
|
.setColorScheme(Settings.AppearanceSettings.ColorScheme.Default)
|
||||||
.setDimWallpaper(false)
|
.setDimWallpaper(false)
|
||||||
|
.setCustomColors(Settings.AppearanceSettings.CustomColors.newBuilder()
|
||||||
|
.setAdvancedMode(false)
|
||||||
|
.setBaseColors(DefaultCustomColorsBase)
|
||||||
|
.setLightScheme(DefaultLightCustomColorScheme)
|
||||||
|
.setDarkScheme(DefaultDarkCustomColorScheme)
|
||||||
|
)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
.setWeather(
|
.setWeather(
|
||||||
@ -70,7 +77,7 @@ fun createFactorySettings(context: Context): Settings {
|
|||||||
Settings.AppShortcutSearchSettings
|
Settings.AppShortcutSearchSettings
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
.setEnabled(true)
|
.setEnabled(true)
|
||||||
)
|
)
|
||||||
.setCalculatorSearch(
|
.setCalculatorSearch(
|
||||||
Settings.CalculatorSearchSettings
|
Settings.CalculatorSearchSettings
|
||||||
.newBuilder()
|
.newBuilder()
|
||||||
@ -140,4 +147,83 @@ fun createFactorySettings(context: Context): Settings {
|
|||||||
.setOpacity(1f)
|
.setOpacity(1f)
|
||||||
)
|
)
|
||||||
.build()
|
.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;
|
Default = 0;
|
||||||
BlackAndWhite = 1;
|
BlackAndWhite = 1;
|
||||||
DebugMaterialYouCompat = 2;
|
DebugMaterialYouCompat = 2;
|
||||||
|
Custom = 3;
|
||||||
}
|
}
|
||||||
ColorScheme color_scheme = 6;
|
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;
|
bool dim_wallpaper = 7;
|
||||||
}
|
}
|
||||||
AppearanceSettings appearance = 2;
|
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.cards.CardsSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreen
|
import de.mm20.launcher2.ui.settings.clockwidget.ClockWidgetSettingsScreen
|
||||||
import de.mm20.launcher2.ui.settings.colorscheme.ColorSchemeSettingsScreen
|
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.CrashReportScreen
|
||||||
import de.mm20.launcher2.ui.settings.crashreporter.CrashReporterScreen
|
import de.mm20.launcher2.ui.settings.crashreporter.CrashReporterScreen
|
||||||
import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
import de.mm20.launcher2.ui.settings.debug.DebugSettingsScreen
|
||||||
@ -88,6 +89,9 @@ class SettingsActivity : BaseActivity() {
|
|||||||
composable("settings/appearance/colorscheme") {
|
composable("settings/appearance/colorscheme") {
|
||||||
ColorSchemeSettingsScreen()
|
ColorSchemeSettingsScreen()
|
||||||
}
|
}
|
||||||
|
composable("settings/appearance/colorscheme/custom") {
|
||||||
|
CustomColorSchemeSettingsScreen()
|
||||||
|
}
|
||||||
composable("settings/appearance/cards") {
|
composable("settings/appearance/cards") {
|
||||||
CardsSettingsScreen()
|
CardsSettingsScreen()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,6 +71,7 @@ fun AppearanceSettingsScreen() {
|
|||||||
summary = when (colorScheme) {
|
summary = when (colorScheme) {
|
||||||
ColorScheme.Default -> stringResource(R.string.preference_colors_default)
|
ColorScheme.Default -> stringResource(R.string.preference_colors_default)
|
||||||
ColorScheme.BlackAndWhite -> stringResource(R.string.preference_colors_bw)
|
ColorScheme.BlackAndWhite -> stringResource(R.string.preference_colors_bw)
|
||||||
|
ColorScheme.Custom -> stringResource(R.string.preference_colors_custom)
|
||||||
else -> null
|
else -> null
|
||||||
},
|
},
|
||||||
onClick = {
|
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.Preference
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
|
||||||
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
|
||||||
|
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||||
import de.mm20.launcher2.ui.theme.colorSchemeAsState
|
import de.mm20.launcher2.ui.theme.colorSchemeAsState
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ColorSchemeSettingsScreen() {
|
fun ColorSchemeSettingsScreen() {
|
||||||
val viewModel: ColorSchemeSettingsScreenVM = viewModel()
|
val viewModel: ColorSchemeSettingsScreenVM = viewModel()
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
|
||||||
PreferenceScreen(title = stringResource(R.string.preference_screen_colors)) {
|
PreferenceScreen(title = stringResource(R.string.preference_screen_colors)) {
|
||||||
item {
|
item {
|
||||||
@ -36,6 +38,7 @@ fun ColorSchemeSettingsScreen() {
|
|||||||
val items = mutableListOf(
|
val items = mutableListOf(
|
||||||
AppearanceSettings.ColorScheme.Default to stringResource(R.string.preference_colors_default),
|
AppearanceSettings.ColorScheme.Default to stringResource(R.string.preference_colors_default),
|
||||||
AppearanceSettings.ColorScheme.BlackAndWhite to stringResource(R.string.preference_colors_bw),
|
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)) {
|
if (BuildConfig.DEBUG && isAtLeastApiLevel(27)) {
|
||||||
@ -47,7 +50,12 @@ fun ColorSchemeSettingsScreen() {
|
|||||||
Preference(
|
Preference(
|
||||||
title = cs.second,
|
title = cs.second,
|
||||||
icon = if (colorScheme == cs.first) Icons.Rounded.RadioButtonChecked else Icons.Rounded.RadioButtonUnchecked,
|
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 = {
|
controls = {
|
||||||
ColorSchemePreview(scheme)
|
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 -> {
|
else -> {
|
||||||
if (Build.VERSION.SDK_INT >= 27 && (Build.VERSION.SDK_INT < 31 || colorScheme == AppearanceSettings.ColorScheme.DebugMaterialYouCompat)) {
|
if (Build.VERSION.SDK_INT >= 27 && (Build.VERSION.SDK_INT < 31 || colorScheme == AppearanceSettings.ColorScheme.DebugMaterialYouCompat)) {
|
||||||
val wallpaperColors by wallpaperColorsAsState()
|
val wallpaperColors by wallpaperColorsAsState()
|
||||||
@ -71,7 +83,9 @@ fun colorSchemeAsState(colorScheme: AppearanceSettings.ColorScheme): MutableStat
|
|||||||
if (Build.VERSION.SDK_INT >= 31) {
|
if (Build.VERSION.SDK_INT >= 31) {
|
||||||
return remember(darkTheme) {
|
return remember(darkTheme) {
|
||||||
mutableStateOf(
|
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