Add "Monochrome" theme (#1752)

This theme is mainly geared towards e-Ink displays with limited/no
colour capabilities. Previous themes like Yin & Yang would make heavy
use of greyscale colours which could look off on some devices.

This theme is probably not conformant to Material Design 3 colour
scheme guidelines, but it does boast some amazing WebAIM contrast
ratios (#FFFFFF text on #000000 background gets a ratio of 21:1, vice
versa too).

Initially, this was intended as a purely black and white theme but
some contrast issues arose, such as the download badges (tertiary
background, onTertiary text colour) having the same colour as unread
badges (primary/onPrimary), or the step indicators (stops) not being
visible on sliders (since they use the colours of the opposite state
track (active region stops are the colour of the inactive region track
and vice versa).

To mitigate this, each variant (dark/light) of the theme has one
additional grey mixed in for their tertiary and secondaryContainer
colours each. For the dark variant, this is a #A0A0A0 background for
#000000 text (8.03:1 contrast ratio) and for the light variant, it is
a #505050 background for #FFFFFF text (8.06:1 contrast ratio).
This results in distinct unread vs download badges and visible steps
in the sliders.

---------

Co-authored-by: Sunspark-007 <73711243+Sunspark-007@users.noreply.github.com>
Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 8b48d1016b851b425e4f66d44bca098220585c37)

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
MajorTanya 2025-02-25 00:22:48 +01:00 committed by Jobobby04
parent ab976d8b07
commit a97deb0036
8 changed files with 204 additions and 0 deletions

View File

@ -20,6 +20,7 @@ enum class AppTheme(val titleRes: StringResource?) {
TIDAL_WAVE(MR.strings.theme_tidalwave),
YINYANG(MR.strings.theme_yinyang),
YOTSUBA(MR.strings.theme_yotsuba),
MONOCHROME(MR.strings.theme_monochrome),
// Deprecated
DARK_BLUE(null),

View File

@ -13,6 +13,7 @@ import eu.kanade.presentation.theme.colorscheme.GreenAppleColorScheme
import eu.kanade.presentation.theme.colorscheme.LavenderColorScheme
import eu.kanade.presentation.theme.colorscheme.MidnightDuskColorScheme
import eu.kanade.presentation.theme.colorscheme.MonetColorScheme
import eu.kanade.presentation.theme.colorscheme.MonochromeColorScheme
import eu.kanade.presentation.theme.colorscheme.NordColorScheme
import eu.kanade.presentation.theme.colorscheme.StrawberryColorScheme
import eu.kanade.presentation.theme.colorscheme.TachiyomiColorScheme
@ -79,6 +80,7 @@ private val colorSchemes: Map<AppTheme, BaseColorScheme> = mapOf(
AppTheme.GREEN_APPLE to GreenAppleColorScheme,
AppTheme.LAVENDER to LavenderColorScheme,
AppTheme.MIDNIGHT_DUSK to MidnightDuskColorScheme,
AppTheme.MONOCHROME to MonochromeColorScheme,
AppTheme.NORD to NordColorScheme,
AppTheme.STRAWBERRY_DAIQUIRI to StrawberryColorScheme,
AppTheme.TAKO to TakoColorScheme,

View File

@ -0,0 +1,84 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
internal object MonochromeColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFFFFFFF),
onPrimary = Color(0xFF000000),
primaryContainer = Color(0xFFFFFFFF),
onPrimaryContainer = Color(0xFF000000),
secondary = Color(0xFFFFFFFF),
onSecondary = Color(0xFF000000),
secondaryContainer = Color(0xFF777777),
onSecondaryContainer = Color(0xFF000000),
tertiary = Color(0xFF777777),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFFFFFFFF),
onTertiaryContainer = Color(0xFF000000),
error = Color(0xFFFFFFFF),
onError = Color(0xFF000000),
errorContainer = Color(0xFFFFFFFF),
onErrorContainer = Color(0xFF000000),
background = Color(0xFF000000),
onBackground = Color(0xFFFFFFFF),
surface = Color(0xFF000000),
onSurface = Color(0xFFFFFFFF),
surfaceVariant = Color(0xFF000000),
onSurfaceVariant = Color(0xFFFFFFFF),
outline = Color(0xFFFFFFFF),
outlineVariant = Color(0xFFFFFFFF),
scrim = Color(0xFF000000),
inverseSurface = Color(0xFFFFFFFF),
inverseOnSurface = Color(0xFF000000),
inversePrimary = Color(0xFF000000),
surfaceDim = Color(0xFF000000),
surfaceBright = Color(0xFFFFFFFF),
surfaceContainerLowest = Color(0xFF000000),
surfaceContainerLow = Color(0xFF000000),
surfaceContainer = Color(0xFF000000),
surfaceContainerHigh = Color(0xFF000000),
surfaceContainerHighest = Color(0xFF000000),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF000000),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFF000000),
onPrimaryContainer = Color(0xFFFFFFFF),
secondary = Color(0xFF000000),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFF888888),
onSecondaryContainer = Color(0xFFFFFFFF),
tertiary = Color(0xFF888888),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF000000),
onTertiaryContainer = Color(0xFFFFFFFF),
error = Color(0xFF000000),
onError = Color(0xFFFFFFFF),
errorContainer = Color(0xFF000000),
onErrorContainer = Color(0xFFFFFFFF),
background = Color(0xFFFFFFFF),
onBackground = Color(0xFF000000),
surface = Color(0xFFFFFFFF),
onSurface = Color(0xFF000000),
surfaceVariant = Color(0xFFFFFFFF),
onSurfaceVariant = Color(0xFF000000),
outline = Color(0xFF000000),
outlineVariant = Color(0xFF000000),
scrim = Color(0xFF000000),
inverseSurface = Color(0xFF000000),
inverseOnSurface = Color(0xFFFFFFFF),
inversePrimary = Color(0xFFFFFFFF),
surfaceDim = Color(0xFFFFFFFF),
surfaceBright = Color(0xFFFFFFFF),
surfaceContainerLowest = Color(0xFFFFFFFF),
surfaceContainerLow = Color(0xFFFFFFFF),
surfaceContainer = Color(0xFFFFFFFF),
surfaceContainerHigh = Color(0xFFFFFFFF),
surfaceContainerHighest = Color(0xFFFFFFFF),
)
}

View File

@ -33,6 +33,7 @@ private val themeResources: Map<AppTheme, Int> = mapOf(
AppTheme.GREEN_APPLE to R.style.Theme_Tachiyomi_GreenApple,
AppTheme.LAVENDER to R.style.Theme_Tachiyomi_Lavender,
AppTheme.MIDNIGHT_DUSK to R.style.Theme_Tachiyomi_MidnightDusk,
AppTheme.MONOCHROME to R.style.Theme_Tachiyomi_Monochrome,
AppTheme.NORD to R.style.Theme_Tachiyomi_Nord,
AppTheme.STRAWBERRY_DAIQUIRI to R.style.Theme_Tachiyomi_StrawberryDaiquiri,
AppTheme.TAKO to R.style.Theme_Tachiyomi_Tako,

View File

@ -451,6 +451,45 @@
<item name="colorSurfaceContainerLowest">@color/nord_surfaceContainerLowest</item>
</style>
<!--== Monochrome Theme ==-->
<style name="Theme.Tachiyomi.Monochrome">
<!-- Theme Colors -->
<item name="colorPrimary">@color/monochrome_primary</item>
<item name="colorOnPrimary">@color/monochrome_onPrimary</item>
<item name="colorPrimaryContainer">@color/monochrome_primaryContainer</item>
<item name="colorOnPrimaryContainer">@color/monochrome_onPrimaryContainer</item>
<item name="colorSecondary">@color/monochrome_secondary</item>
<item name="colorOnSecondary">@color/monochrome_onSecondary</item>
<item name="colorSecondaryContainer">@color/monochrome_secondaryContainer</item>
<item name="colorOnSecondaryContainer">@color/monochrome_onSecondaryContainer</item>
<item name="colorTertiary">@color/monochrome_tertiary</item>
<item name="colorOnTertiary">@color/monochrome_onTertiary</item>
<item name="colorTertiaryContainer">@color/monochrome_tertiaryContainer</item>
<item name="colorOnTertiaryContainer">@color/monochrome_onTertiaryContainer</item>
<item name="colorError">@color/monochrome_error</item>
<item name="colorOnError">@color/monochrome_onError</item>
<item name="colorErrorContainer">@color/monochrome_errorContainer</item>
<item name="colorOnErrorContainer">@color/monochrome_onErrorContainer</item>
<item name="android:colorBackground">@color/monochrome_background</item>
<item name="colorOnBackground">@color/monochrome_onBackground</item>
<item name="colorSurface">@color/monochrome_surface</item>
<item name="colorOnSurface">@color/monochrome_onSurface</item>
<item name="colorSurfaceVariant">@color/monochrome_surfaceVariant</item>
<item name="colorOnSurfaceVariant">@color/monochrome_onSurfaceVariant</item>
<item name="colorOutline">@color/monochrome_outline</item>
<item name="colorOutlineVariant">@color/monochrome_outlineVariant</item>
<item name="colorSurfaceInverse">@color/monochrome_inverseSurface</item>
<item name="colorOnSurfaceInverse">@color/monochrome_inverseOnSurface</item>
<item name="colorPrimaryInverse">@color/monochrome_inversePrimary</item>
<item name="colorSurfaceDim">@color/monochrome_surfaceDim</item>
<item name="colorSurfaceBright">@color/monochrome_surfaceBright</item>
<item name="colorSurfaceContainerLowest">@color/monochrome_surfaceContainerLowest</item>
<item name="colorSurfaceContainerLow">@color/monochrome_surfaceContainerLow</item>
<item name="colorSurfaceContainer">@color/monochrome_surfaceContainer</item>
<item name="colorSurfaceContainerHigh">@color/monochrome_surfaceContainerHigh</item>
<item name="colorSurfaceContainerHighest">@color/monochrome_surfaceContainerHighest</item>
</style>
<!--== AMOLED Mode Overlay ==-->
<style name="ThemeOverlay.Tachiyomi.Amoled" parent="" />

View File

@ -231,6 +231,7 @@
<string name="theme_greenapple">Green Apple</string>
<string name="theme_lavender">Lavender</string>
<string name="theme_midnightdusk">Midnight Dusk</string>
<string name="theme_monochrome">Monochrome</string>
<string name="theme_nord">Nord</string>
<string name="theme_strawberrydaiquiri">Strawberry Daiquiri</string>
<string name="theme_tako">Tako</string>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="monochrome_primary">#FFFFFF</color>
<color name="monochrome_onPrimary">#000000</color>
<color name="monochrome_primaryContainer">#FFFFFF</color>
<color name="monochrome_onPrimaryContainer">#000000</color>
<color name="monochrome_secondary">#FFFFFF</color>
<color name="monochrome_onSecondary">#000000</color>
<color name="monochrome_secondaryContainer">#777777</color>
<color name="monochrome_onSecondaryContainer">#000000</color>
<color name="monochrome_tertiary">#777777</color>
<color name="monochrome_onTertiary">#FFFFFF</color>
<color name="monochrome_tertiaryContainer">#FFFFFF</color>
<color name="monochrome_onTertiaryContainer">#000000</color>
<color name="monochrome_error">#FFFFFF</color>
<color name="monochrome_onError">#000000</color>
<color name="monochrome_errorContainer">#FFFFFF</color>
<color name="monochrome_onErrorContainer">#000000</color>
<color name="monochrome_background">#000000</color>
<color name="monochrome_onBackground">#FFFFFF</color>
<color name="monochrome_surface">#000000</color>
<color name="monochrome_onSurface">#FFFFFF</color>
<color name="monochrome_surfaceVariant">#000000</color>
<color name="monochrome_onSurfaceVariant">#FFFFFF</color>
<color name="monochrome_outline">#FFFFFF</color>
<color name="monochrome_outlineVariant">#FFFFFF</color>
<color name="monochrome_scrim">#000000</color>
<color name="monochrome_inverseSurface">#FFFFFF</color>
<color name="monochrome_inverseOnSurface">#000000</color>
<color name="monochrome_inversePrimary">#000000</color>
<color name="monochrome_surfaceDim">#000000</color>
<color name="monochrome_surfaceBright">#FFFFFF</color>
<color name="monochrome_surfaceContainerLowest">#000000</color>
<color name="monochrome_surfaceContainerLow">#000000</color>
<color name="monochrome_surfaceContainer">#000000</color>
<color name="monochrome_surfaceContainerHigh">#000000</color>
<color name="monochrome_surfaceContainerHighest">#000000</color>
</resources>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="monochrome_primary">#000000</color>
<color name="monochrome_onPrimary">#FFFFFF</color>
<color name="monochrome_primaryContainer">#000000</color>
<color name="monochrome_onPrimaryContainer">#FFFFFF</color>
<color name="monochrome_secondary">#000000</color>
<color name="monochrome_onSecondary">#FFFFFF</color>
<color name="monochrome_secondaryContainer">#888888</color>
<color name="monochrome_onSecondaryContainer">#FFFFFF</color>
<color name="monochrome_tertiary">#888888</color>
<color name="monochrome_onTertiary">#FFFFFF</color>
<color name="monochrome_tertiaryContainer">#000000</color>
<color name="monochrome_onTertiaryContainer">#FFFFFF</color>
<color name="monochrome_error">#000000</color>
<color name="monochrome_onError">#FFFFFF</color>
<color name="monochrome_errorContainer">#000000</color>
<color name="monochrome_onErrorContainer">#FFFFFF</color>
<color name="monochrome_background">#FFFFFF</color>
<color name="monochrome_onBackground">#000000</color>
<color name="monochrome_surface">#FFFFFF</color>
<color name="monochrome_onSurface">#000000</color>
<color name="monochrome_surfaceVariant">#FFFFFF</color>
<color name="monochrome_onSurfaceVariant">#000000</color>
<color name="monochrome_outline">#000000</color>
<color name="monochrome_outlineVariant">#000000</color>
<color name="monochrome_scrim">#000000</color>
<color name="monochrome_inverseSurface">#000000</color>
<color name="monochrome_inverseOnSurface">#FFFFFF</color>
<color name="monochrome_inversePrimary">#FFFFFF</color>
<color name="monochrome_surfaceDim">#000000</color>
<color name="monochrome_surfaceBright">#FFFFFF</color>
<color name="monochrome_surfaceContainerLowest">#FFFFFF</color>
<color name="monochrome_surfaceContainerLow">#FFFFFF</color>
<color name="monochrome_surfaceContainer">#FFFFFF</color>
<color name="monochrome_surfaceContainerHigh">#FFFFFF</color>
<color name="monochrome_surfaceContainerHighest">#FFFFFF</color>
</resources>