From 8d11ef324444cadfc0dad5171cf6351fefee9d7d Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Sat, 27 Dec 2025 00:30:42 +0600 Subject: [PATCH] Use materilalKolor for monet compat color scheme (cherry picked from commit 9a11ec8ead41cb7199e10f3c7464790a0bd3b1ad) --- app/build.gradle.kts | 1 + .../presentation/theme/TachiyomiTheme.kt | 25 ++++-- .../theme/colorscheme/BaseColorScheme.kt | 13 ++- .../theme/colorscheme/MonetColorScheme.kt | 88 ++----------------- gradle/libs.versions.toml | 3 + 5 files changed, 42 insertions(+), 88 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7bb58571d..995a21888 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -265,6 +265,7 @@ dependencies { implementation(libs.compose.grid) implementation(libs.reorderable) implementation(libs.bundles.markdown) + implementation(libs.materialKolor) // Logging implementation(libs.logcat) diff --git a/app/src/main/java/eu/kanade/presentation/theme/TachiyomiTheme.kt b/app/src/main/java/eu/kanade/presentation/theme/TachiyomiTheme.kt index 6da538015..debf500fa 100644 --- a/app/src/main/java/eu/kanade/presentation/theme/TachiyomiTheme.kt +++ b/app/src/main/java/eu/kanade/presentation/theme/TachiyomiTheme.kt @@ -1,10 +1,11 @@ package eu.kanade.presentation.theme +import android.content.Context import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import eu.kanade.domain.ui.UiPreferences import eu.kanade.domain.ui.model.AppTheme @@ -53,26 +54,36 @@ private fun BaseTachiyomiTheme( isAmoled: Boolean, content: @Composable () -> Unit, ) { + val context = LocalContext.current + val isDark = isSystemInDarkTheme() MaterialTheme( - colorScheme = getThemeColorScheme(appTheme, isAmoled), + colorScheme = remember(appTheme, isDark, isAmoled) { + getThemeColorScheme( + context = context, + appTheme = appTheme, + isDark = isDark, + isAmoled = isAmoled, + ) + }, content = content, ) } -@Composable -@ReadOnlyComposable private fun getThemeColorScheme( + context: Context, appTheme: AppTheme, + isDark: Boolean, isAmoled: Boolean, ): ColorScheme { val colorScheme = if (appTheme == AppTheme.MONET) { - MonetColorScheme(LocalContext.current) + MonetColorScheme(context) } else { colorSchemes.getOrDefault(appTheme, TachiyomiColorScheme) } return colorScheme.getColorScheme( - isSystemInDarkTheme(), - isAmoled, + isDark = isDark, + isAmoled = isAmoled, + overrideDarkSurfaceContainers = appTheme != AppTheme.MONET, ) } diff --git a/app/src/main/java/eu/kanade/presentation/theme/colorscheme/BaseColorScheme.kt b/app/src/main/java/eu/kanade/presentation/theme/colorscheme/BaseColorScheme.kt index 22dd9a0a7..4ad2bfb80 100644 --- a/app/src/main/java/eu/kanade/presentation/theme/colorscheme/BaseColorScheme.kt +++ b/app/src/main/java/eu/kanade/presentation/theme/colorscheme/BaseColorScheme.kt @@ -14,16 +14,25 @@ internal abstract class BaseColorScheme { private val surfaceContainerHigh = Color(0xFF131313) private val surfaceContainerHighest = Color(0xFF1B1B1B) - fun getColorScheme(isDark: Boolean, isAmoled: Boolean): ColorScheme { + fun getColorScheme( + isDark: Boolean, + isAmoled: Boolean, + overrideDarkSurfaceContainers: Boolean, + ): ColorScheme { if (!isDark) return lightScheme if (!isAmoled) return darkScheme - return darkScheme.copy( + val amoledScheme = darkScheme.copy( background = Color.Black, onBackground = Color.White, surface = Color.Black, onSurface = Color.White, + ) + + if (!overrideDarkSurfaceContainers) return amoledScheme + + return amoledScheme.copy( surfaceVariant = surfaceContainer, // Navigation bar background (ThemePrefWidget) surfaceContainerLowest = surfaceContainer, surfaceContainerLow = surfaceContainer, diff --git a/app/src/main/java/eu/kanade/presentation/theme/colorscheme/MonetColorScheme.kt b/app/src/main/java/eu/kanade/presentation/theme/colorscheme/MonetColorScheme.kt index adcbaf62f..fb670babe 100644 --- a/app/src/main/java/eu/kanade/presentation/theme/colorscheme/MonetColorScheme.kt +++ b/app/src/main/java/eu/kanade/presentation/theme/colorscheme/MonetColorScheme.kt @@ -1,22 +1,15 @@ package eu.kanade.presentation.theme.colorscheme -import android.annotation.SuppressLint -import android.app.UiModeManager import android.app.WallpaperManager import android.content.Context -import android.graphics.Bitmap import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.material3.ColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.ui.graphics.Color -import androidx.core.content.getSystemService -import com.google.android.material.color.utilities.Hct -import com.google.android.material.color.utilities.MaterialDynamicColors -import com.google.android.material.color.utilities.QuantizerCelebi -import com.google.android.material.color.utilities.SchemeContent -import com.google.android.material.color.utilities.Score +import com.materialkolor.ktx.DynamicScheme +import com.materialkolor.toColorScheme internal class MonetColorScheme(context: Context) : BaseColorScheme() { @@ -28,7 +21,7 @@ internal class MonetColorScheme(context: Context) : BaseColorScheme() { ?.primaryColor ?.toArgb() if (seed != null) { - MonetCompatColorScheme(context, seed) + MonetCompatColorScheme(Color(seed)) } else { TachiyomiColorScheme } @@ -41,19 +34,6 @@ internal class MonetColorScheme(context: Context) : BaseColorScheme() { override val lightScheme get() = monet.lightScheme - - companion object { - @Suppress("Unused") - @SuppressLint("RestrictedApi") - fun extractSeedColorFromImage(bitmap: Bitmap): Int? { - val width = bitmap.width - val height = bitmap.height - val bitmapPixels = IntArray(width * height) - bitmap.getPixels(bitmapPixels, 0, width, 0, 0, width, height) - return Score.score(QuantizerCelebi.quantize(bitmapPixels, 128), 1, 0)[0] - .takeIf { it != 0 } // Don't take fallback color - } - } } @RequiresApi(Build.VERSION_CODES.S) @@ -62,64 +42,14 @@ private class MonetSystemColorScheme(context: Context) : BaseColorScheme() { override val darkScheme = dynamicDarkColorScheme(context) } -private class MonetCompatColorScheme(context: Context, seed: Int) : BaseColorScheme() { - - override val lightScheme = generateColorSchemeFromSeed(context = context, seed = seed, dark = false) - override val darkScheme = generateColorSchemeFromSeed(context = context, seed = seed, dark = true) +internal class MonetCompatColorScheme(seed: Color) : BaseColorScheme() { + override val lightScheme = generateColorSchemeFromSeed(seed = seed, dark = false) + override val darkScheme = generateColorSchemeFromSeed(seed = seed, dark = true) companion object { - private fun Int.toComposeColor(): Color = Color(this) - - @SuppressLint("PrivateResource", "RestrictedApi") - private fun generateColorSchemeFromSeed(context: Context, seed: Int, dark: Boolean): ColorScheme { - val scheme = SchemeContent( - Hct.fromInt(seed), - dark, - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - context.getSystemService()?.contrast?.toDouble() ?: 0.0 - } else { - 0.0 - }, - ) - val dynamicColors = MaterialDynamicColors() - return ColorScheme( - primary = dynamicColors.primary().getArgb(scheme).toComposeColor(), - onPrimary = dynamicColors.onPrimary().getArgb(scheme).toComposeColor(), - primaryContainer = dynamicColors.primaryContainer().getArgb(scheme).toComposeColor(), - onPrimaryContainer = dynamicColors.onPrimaryContainer().getArgb(scheme).toComposeColor(), - inversePrimary = dynamicColors.inversePrimary().getArgb(scheme).toComposeColor(), - secondary = dynamicColors.secondary().getArgb(scheme).toComposeColor(), - onSecondary = dynamicColors.onSecondary().getArgb(scheme).toComposeColor(), - secondaryContainer = dynamicColors.secondaryContainer().getArgb(scheme).toComposeColor(), - onSecondaryContainer = dynamicColors.onSecondaryContainer().getArgb(scheme).toComposeColor(), - tertiary = dynamicColors.tertiary().getArgb(scheme).toComposeColor(), - onTertiary = dynamicColors.onTertiary().getArgb(scheme).toComposeColor(), - tertiaryContainer = dynamicColors.tertiary().getArgb(scheme).toComposeColor(), - onTertiaryContainer = dynamicColors.onTertiaryContainer().getArgb(scheme).toComposeColor(), - background = dynamicColors.background().getArgb(scheme).toComposeColor(), - onBackground = dynamicColors.onBackground().getArgb(scheme).toComposeColor(), - surface = dynamicColors.surface().getArgb(scheme).toComposeColor(), - onSurface = dynamicColors.onSurface().getArgb(scheme).toComposeColor(), - surfaceVariant = dynamicColors.surfaceVariant().getArgb(scheme).toComposeColor(), - onSurfaceVariant = dynamicColors.onSurfaceVariant().getArgb(scheme).toComposeColor(), - surfaceTint = dynamicColors.surfaceTint().getArgb(scheme).toComposeColor(), - inverseSurface = dynamicColors.inverseSurface().getArgb(scheme).toComposeColor(), - inverseOnSurface = dynamicColors.inverseOnSurface().getArgb(scheme).toComposeColor(), - error = dynamicColors.error().getArgb(scheme).toComposeColor(), - onError = dynamicColors.onError().getArgb(scheme).toComposeColor(), - errorContainer = dynamicColors.errorContainer().getArgb(scheme).toComposeColor(), - onErrorContainer = dynamicColors.onErrorContainer().getArgb(scheme).toComposeColor(), - outline = dynamicColors.outline().getArgb(scheme).toComposeColor(), - outlineVariant = dynamicColors.outlineVariant().getArgb(scheme).toComposeColor(), - scrim = Color.Black, - surfaceBright = dynamicColors.surfaceBright().getArgb(scheme).toComposeColor(), - surfaceDim = dynamicColors.surfaceDim().getArgb(scheme).toComposeColor(), - surfaceContainer = dynamicColors.surfaceContainer().getArgb(scheme).toComposeColor(), - surfaceContainerHigh = dynamicColors.surfaceContainerHigh().getArgb(scheme).toComposeColor(), - surfaceContainerHighest = dynamicColors.surfaceContainerHighest().getArgb(scheme).toComposeColor(), - surfaceContainerLow = dynamicColors.surfaceContainerLow().getArgb(scheme).toComposeColor(), - surfaceContainerLowest = dynamicColors.surfaceContainerLowest().getArgb(scheme).toComposeColor(), - ) + fun generateColorSchemeFromSeed(seed: Color, dark: Boolean): ColorScheme { + return DynamicScheme(seedColor = seed, isDark = dark) + .toColorScheme(isAmoled = false) } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a932ad635..4c454cfcf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ ktlint-core = "1.8.0" firebase-bom = "34.7.0" markdown = "0.39.0" junit = "6.0.1" +materialKolor = "5.0.0-alpha04" [libraries] desugar = "com.android.tools:desugar_jdk_libs:2.1.5" @@ -106,6 +107,8 @@ markdown-coil = { module = "com.mikepenz:multiplatform-markdown-renderer-coil3", stringSimilarity = { module = "com.aallam.similarity:string-similarity-kotlin", version = "0.1.0" } +materialKolor = { module = "com.materialkolor:material-kolor", version.ref = "materialKolor" } + [plugins] google-services = { id = "com.google.gms.google-services", version = "4.4.4" } aboutLibraries = { id = "com.mikepenz.aboutlibraries.plugin.android", version.ref = "aboutlib_version" }