From 5525609355ddfcf4516688d253add8deb05d47d0 Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Tue, 10 Jun 2025 18:41:18 +0200 Subject: [PATCH] Add material 3 high contrast theme --- .../ColorSchemesSettingsScreenVM.kt | 3 + core/i18n/src/main/res/values/strings.xml | 1 + .../preferences/LauncherSettingsData.kt | 4 + .../de/mm20/launcher2/themes/DefaultThemes.kt | 78 +++++++++++++++++++ .../mm20/launcher2/themes/ThemeRepository.kt | 14 ++++ 5 files changed, 100 insertions(+) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemesSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemesSettingsScreenVM.kt index a0acdb75..0a59622b 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemesSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/colorscheme/ColorSchemesSettingsScreenVM.kt @@ -11,6 +11,7 @@ import de.mm20.launcher2.preferences.ui.UiSettings import de.mm20.launcher2.themes.BlackAndWhiteThemeId import de.mm20.launcher2.themes.DefaultThemeId import de.mm20.launcher2.themes.Colors +import de.mm20.launcher2.themes.HighContrastThemeId import de.mm20.launcher2.themes.ThemeRepository import de.mm20.launcher2.themes.toLegacyJson import de.mm20.launcher2.ui.R @@ -32,6 +33,7 @@ class ColorSchemesSettingsScreenVM : ViewModel(), KoinComponent { val selectedColors = uiSettings.colors.map { when(it) { ColorsDescriptor.Default -> DefaultThemeId + ColorsDescriptor.HighContrast -> HighContrastThemeId ColorsDescriptor.BlackAndWhite -> BlackAndWhiteThemeId is ColorsDescriptor.Custom -> UUID.fromString(it.id) } @@ -49,6 +51,7 @@ class ColorSchemesSettingsScreenVM : ViewModel(), KoinComponent { fun selectTheme(colors: Colors) { uiSettings.setColors(when(colors.id) { DefaultThemeId -> ColorsDescriptor.Default + HighContrastThemeId -> ColorsDescriptor.HighContrast BlackAndWhiteThemeId -> ColorsDescriptor.BlackAndWhite else -> ColorsDescriptor.Custom(colors.id.toString()) }) diff --git a/core/i18n/src/main/res/values/strings.xml b/core/i18n/src/main/res/values/strings.xml index a56f1d75..78d56013 100644 --- a/core/i18n/src/main/res/values/strings.xml +++ b/core/i18n/src/main/res/values/strings.xml @@ -428,6 +428,7 @@ Dark Color scheme Default + High contrast Black and White Color palette Source for dynamic colors diff --git a/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt b/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt index ff320950..6cb71319 100644 --- a/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt +++ b/core/preferences/src/main/java/de/mm20/launcher2/preferences/LauncherSettingsData.kt @@ -212,6 +212,10 @@ sealed interface ColorsDescriptor { @SerialName("default") data object Default : ColorsDescriptor + @Serializable + @SerialName("high_contrast") + data object HighContrast : ColorsDescriptor + @Serializable @SerialName("bw") data object BlackAndWhite : ColorsDescriptor diff --git a/data/themes/src/main/java/de/mm20/launcher2/themes/DefaultThemes.kt b/data/themes/src/main/java/de/mm20/launcher2/themes/DefaultThemes.kt index ce694aab..ee2d9f11 100644 --- a/data/themes/src/main/java/de/mm20/launcher2/themes/DefaultThemes.kt +++ b/data/themes/src/main/java/de/mm20/launcher2/themes/DefaultThemes.kt @@ -4,6 +4,7 @@ import java.util.UUID val DefaultThemeId = UUID(0L, 0L) +val HighContrastThemeId = UUID(0L, 2L) val BlackAndWhiteThemeId = UUID(0L, 1L) val ExtraRoundShapesId = UUID(0L, 1L) val CutShapesId = UUID(0L, 2L) @@ -87,6 +88,83 @@ val DefaultDarkColorScheme = ColorScheme( scrim = ColorRef(CorePaletteColor.Neutral, 0), ) +val HighContrastLightColorScheme = ColorScheme( + primary = ColorRef(CorePaletteColor.Primary, 20), + onPrimary = ColorRef(CorePaletteColor.Primary, 100), + primaryContainer = ColorRef(CorePaletteColor.Primary, 30), + onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 100), + secondary = ColorRef(CorePaletteColor.Secondary, 20), + onSecondary = ColorRef(CorePaletteColor.Secondary, 100), + secondaryContainer = ColorRef(CorePaletteColor.Secondary, 30), + onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 100), + tertiary = ColorRef(CorePaletteColor.Tertiary, 20), + onTertiary = ColorRef(CorePaletteColor.Tertiary, 100), + tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 30), + onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 100), + error = ColorRef(CorePaletteColor.Error, 20), + onError = ColorRef(CorePaletteColor.Error, 100), + errorContainer = ColorRef(CorePaletteColor.Error, 30), + onErrorContainer = ColorRef(CorePaletteColor.Error, 100), + surfaceDim = ColorRef(CorePaletteColor.Neutral, 87), + surface = ColorRef(CorePaletteColor.Neutral, 98), + surfaceBright = ColorRef(CorePaletteColor.Neutral, 98), + surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 100), + surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 96), + surfaceContainer = ColorRef(CorePaletteColor.Neutral, 94), + surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 92), + surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 90), + onSurface = ColorRef(CorePaletteColor.Neutral, 0), + onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 0), + outline = ColorRef(CorePaletteColor.NeutralVariant, 20), + outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 30), + inverseSurface = ColorRef(CorePaletteColor.Neutral, 20), + inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 100), + inversePrimary = ColorRef(CorePaletteColor.Primary, 80), + surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 90), + surfaceTint = ColorRef(CorePaletteColor.Primary, 20), + background = ColorRef(CorePaletteColor.Neutral, 98), + onBackground = ColorRef(CorePaletteColor.Neutral, 0), + scrim = ColorRef(CorePaletteColor.Neutral, 0), +) + +val HighContrastDarkColorScheme = ColorScheme( + primary = ColorRef(CorePaletteColor.Primary, 95), + onPrimary = ColorRef(CorePaletteColor.Primary, 0), + primaryContainer = ColorRef(CorePaletteColor.Primary, 80), + onPrimaryContainer = ColorRef(CorePaletteColor.Primary, 0), + secondary = ColorRef(CorePaletteColor.Secondary, 95), + onSecondary = ColorRef(CorePaletteColor.Secondary, 0), + secondaryContainer = ColorRef(CorePaletteColor.Secondary, 80), + onSecondaryContainer = ColorRef(CorePaletteColor.Secondary, 0), + tertiary = ColorRef(CorePaletteColor.Tertiary, 95), + onTertiary = ColorRef(CorePaletteColor.Tertiary, 0), + tertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 80), + onTertiaryContainer = ColorRef(CorePaletteColor.Tertiary, 0), + error = ColorRef(CorePaletteColor.Error, 95), + onError = ColorRef(CorePaletteColor.Error, 0), + errorContainer = ColorRef(CorePaletteColor.Error, 80), + onErrorContainer = ColorRef(CorePaletteColor.Error, 0), + surfaceDim = ColorRef(CorePaletteColor.Neutral, 6), + surface = ColorRef(CorePaletteColor.Neutral, 6), + surfaceBright = ColorRef(CorePaletteColor.Neutral, 24), + surfaceContainerLowest = ColorRef(CorePaletteColor.Neutral, 4), + surfaceContainerLow = ColorRef(CorePaletteColor.Neutral, 10), + surfaceContainer = ColorRef(CorePaletteColor.Neutral, 12), + surfaceContainerHigh = ColorRef(CorePaletteColor.Neutral, 17), + surfaceContainerHighest = ColorRef(CorePaletteColor.Neutral, 22), + onSurface = ColorRef(CorePaletteColor.Neutral, 100), + onSurfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 100), + outline = ColorRef(CorePaletteColor.NeutralVariant, 95), + outlineVariant = ColorRef(CorePaletteColor.NeutralVariant, 80), + inverseSurface = ColorRef(CorePaletteColor.Neutral, 90), + inverseOnSurface = ColorRef(CorePaletteColor.Neutral, 0), + inversePrimary = ColorRef(CorePaletteColor.Primary, 20), + surfaceVariant = ColorRef(CorePaletteColor.NeutralVariant, 30), + surfaceTint = ColorRef(CorePaletteColor.Primary, 95), + background = ColorRef(CorePaletteColor.Neutral, 6), + onBackground = ColorRef(CorePaletteColor.Neutral, 100), + scrim = ColorRef(CorePaletteColor.Neutral, 0), +) val BlackAndWhiteLightColorScheme = ColorScheme( primary = StaticColor(0xFF000000.toInt()), diff --git a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt index abc10fa9..793d1a7a 100644 --- a/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt +++ b/data/themes/src/main/java/de/mm20/launcher2/themes/ThemeRepository.kt @@ -34,6 +34,7 @@ class ThemeRepository( fun getColors(id: UUID): Flow { if (id == DefaultThemeId) return flowOf(getDefaultColors()) + if (id == HighContrastThemeId) return flowOf(getHighContrastColors()) if (id == BlackAndWhiteThemeId) return flowOf(getBlackAndWhiteColors()) return database.themeDao().getColors(id).map { it?.let { Colors(it) } }.flowOn(Dispatchers.Default) } @@ -52,6 +53,7 @@ class ThemeRepository( fun getColorsOrDefault(theme: ColorsDescriptor?): Flow { return when(theme) { + is ColorsDescriptor.HighContrast -> flowOf(getHighContrastColors()) is ColorsDescriptor.BlackAndWhite -> flowOf(getBlackAndWhiteColors()) is ColorsDescriptor.Custom -> { val id = UUID.fromString(theme.id) @@ -64,6 +66,7 @@ class ThemeRepository( private fun getBuiltInColors(): List { return listOf( getDefaultColors(), + getHighContrastColors(), getBlackAndWhiteColors(), ) } @@ -79,6 +82,17 @@ class ThemeRepository( ) } + private fun getHighContrastColors(): Colors { + return Colors( + id = HighContrastThemeId, + builtIn = true, + name = context.getString(R.string.preference_colors_high_contrast), + corePalette = EmptyCorePalette, + lightColorScheme = HighContrastLightColorScheme, + darkColorScheme = HighContrastDarkColorScheme, + ) + } + private fun getBlackAndWhiteColors(): Colors { return Colors( id = BlackAndWhiteThemeId,