Themeing improvements

- Add Tertiary color
- Add theme display from Tachiyomi
- Show color changes in theme display
This commit is contained in:
Syer10
2022-11-10 13:16:10 -05:00
parent 38334cbedd
commit f3e455b007
10 changed files with 428 additions and 84 deletions

View File

@@ -42,6 +42,14 @@ class UiPreferences(private val preferenceStore: PreferenceStore) {
return preferenceStore.getInt("color_secondary_dark", 0)
}
fun colorTertiaryLight(): Preference<Int> {
return preferenceStore.getInt("color_tertiary_light", 0)
}
fun colorTertiaryDark(): Preference<Int> {
return preferenceStore.getInt("color_tertiary_dark", 0)
}
fun startScreen(): Preference<StartScreen> {
return preferenceStore.getJsonObject("start_screen", StartScreen.Library, StartScreen.serializer())
}

View File

@@ -198,10 +198,14 @@
<string name="theme_dark">Dark</string>
<string name="theme_text">Text</string>
<string name="preset_themes">Preset themes</string>
<string name="theme_default">Default</string>
<string name="theme_legacy_blue">Legacy Blue</string>
<string name="theme_amoled">AMOLED</string>
<string name="color_primary">Primary</string>
<string name="color_primary_sub">Displayed most frequently across your app</string>
<string name="color_secondary">Secondary</string>
<string name="color_secondary_sub">Accents select parts of the UI</string>
<string name="color_tertiary">Tertiary</string>
<string name="window_decorations">Window decorations</string>
<string name="window_decorations_sub">Restart JUI when this setting is changed</string>

View File

@@ -16,31 +16,36 @@ import kotlinx.coroutines.CoroutineScope
data class AppColorsPreference(
val primary: Preference<Color>,
val secondary: Preference<Color>
val secondary: Preference<Color>,
val tertiary: Preference<Color>
)
class AppColorsPreferenceState(
val primaryStateFlow: PreferenceMutableStateFlow<Color>,
val secondaryStateFlow: PreferenceMutableStateFlow<Color>
val secondaryStateFlow: PreferenceMutableStateFlow<Color>,
val tertiaryStateFlow: PreferenceMutableStateFlow<Color>
)
fun UiPreferences.getLightColors(): AppColorsPreference {
return AppColorsPreference(
colorPrimaryLight().asColor(),
colorSecondaryLight().asColor()
colorSecondaryLight().asColor(),
colorTertiaryLight().asColor()
)
}
fun UiPreferences.getDarkColors(): AppColorsPreference {
return AppColorsPreference(
colorPrimaryDark().asColor(),
colorSecondaryDark().asColor()
colorSecondaryDark().asColor(),
colorTertiaryDark().asColor()
)
}
fun AppColorsPreference.asStateFlow(scope: CoroutineScope): AppColorsPreferenceState {
return AppColorsPreferenceState(
primary.asStateIn(scope),
secondary.asStateIn(scope)
secondary.asStateIn(scope),
tertiary.asStateIn(scope)
)
}

View File

@@ -23,6 +23,7 @@ import ca.gosyer.jui.domain.ui.service.UiPreferences
import ca.gosyer.jui.ui.base.LocalViewModels
import ca.gosyer.jui.ui.base.theme.ThemeScrollbarStyle.getScrollbarStyle
import ca.gosyer.jui.uicore.components.LocalScrollbarStyle
import ca.gosyer.jui.uicore.theme.ExtraColors
import ca.gosyer.jui.uicore.theme.Theme
import ca.gosyer.jui.uicore.theme.themes
import ca.gosyer.jui.uicore.vm.ContextWrapper
@@ -42,17 +43,19 @@ import me.tatarka.inject.annotations.Inject
fun AppTheme(content: @Composable () -> Unit) {
val viewModels = LocalViewModels.current
val vm = remember { viewModels.appThemeViewModel() }
val colors = vm.getColors()
val (colors, extraColors) = vm.getColors()
/*val systemUiController = rememberSystemUiController()*/
DisposableEffect(vm) {
onDispose(vm::onDispose)
}
MaterialTheme(colors = colors) {
CompositionLocalProvider(
LocalScrollbarStyle provides getScrollbarStyle(),
content = content
)
ExtraColors.WithExtraColors(extraColors) {
CompositionLocalProvider(
LocalScrollbarStyle provides getScrollbarStyle(),
content = content
)
}
}
}
@@ -70,7 +73,7 @@ class AppThemeViewModel @Inject constructor(
private val baseThemeScope = CoroutineScope(baseThemeJob)
@Composable
fun getColors(): Colors {
fun getColors(): Pair<Colors, ExtraColors> {
val themeMode by themeMode.collectAsState()
val lightTheme by lightTheme.collectAsState()
val darkTheme by darkTheme.collectAsState()
@@ -88,8 +91,9 @@ class AppThemeViewModel @Inject constructor(
val primary by colors.primaryStateFlow.collectAsState()
val secondary by colors.secondaryStateFlow.collectAsState()
val tertiary by colors.tertiaryStateFlow.collectAsState()
return getMaterialColors(baseTheme.colors, primary, secondary)
return getMaterialColors(baseTheme.colors, primary, secondary) to getExtraColors(baseTheme.extraColors, tertiary)
}
@Composable
@@ -131,6 +135,16 @@ class AppThemeViewModel @Inject constructor(
)
}
private fun getExtraColors(
baseExtraColors: ExtraColors,
colorTertiary: Color
): ExtraColors {
val tertiary = colorTertiary.takeOrElse { baseExtraColors.tertiary }
return baseExtraColors.copy(
tertiary = tertiary
)
}
override fun onDispose() {
baseThemeScope.cancel()
scope.cancel()

View File

@@ -24,6 +24,7 @@ import ca.gosyer.jui.domain.manga.model.Manga
import ca.gosyer.jui.domain.source.model.Source
import ca.gosyer.jui.i18n.MR
import ca.gosyer.jui.uicore.resources.stringResource
import ca.gosyer.jui.uicore.theme.extraColors
@Composable
fun LibraryMangaBadges(
@@ -52,9 +53,9 @@ fun LibraryMangaBadges(
if (showUnread && unread != null && unread > 0) {
Text(
text = unread.toString(),
modifier = Modifier.background(MaterialTheme.colors.primary).then(BadgesInnerPadding),
modifier = Modifier.background(MaterialTheme.extraColors.tertiary).then(BadgesInnerPadding),
style = MaterialTheme.typography.caption,
color = MaterialTheme.colors.onPrimary
color = MaterialTheme.extraColors.onTertiary
)
}
if (showDownloaded && downloaded != null && downloaded > 0) {

View File

@@ -6,39 +6,54 @@
package ca.gosyer.jui.ui.settings
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.add
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Colors
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.primarySurface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import ca.gosyer.jui.domain.ui.model.ThemeMode
import ca.gosyer.jui.domain.ui.service.UiPreferences
import ca.gosyer.jui.i18n.MR
@@ -53,13 +68,16 @@ import ca.gosyer.jui.ui.base.theme.getLightColors
import ca.gosyer.jui.ui.main.components.bottomNav
import ca.gosyer.jui.ui.viewModel
import ca.gosyer.jui.uicore.components.VerticalScrollbar
import ca.gosyer.jui.uicore.components.mangaAspectRatio
import ca.gosyer.jui.uicore.components.rememberScrollbarAdapter
import ca.gosyer.jui.uicore.components.scrollbarPadding
import ca.gosyer.jui.uicore.components.secondaryItemAlpha
import ca.gosyer.jui.uicore.insets.navigationBars
import ca.gosyer.jui.uicore.insets.statusBars
import ca.gosyer.jui.uicore.prefs.PreferenceMutableStateFlow
import ca.gosyer.jui.uicore.resources.stringResource
import ca.gosyer.jui.uicore.theme.Theme
import ca.gosyer.jui.uicore.theme.ExtraColors
import ca.gosyer.jui.uicore.theme.extraColors
import ca.gosyer.jui.uicore.theme.themes
import ca.gosyer.jui.uicore.vm.ContextWrapper
import ca.gosyer.jui.uicore.vm.ViewModel
@@ -75,12 +93,16 @@ class SettingsAppearanceScreen : Screen {
@Composable
override fun Content() {
val vm = viewModel { themesViewModel() }
val appThemeVM = viewModel { appThemeViewModel() }
val (colors, extraColors) = appThemeVM.getColors()
SettingsAppearanceScreenContent(
activeColors = vm.getActiveColors(),
themeMode = vm.themeMode,
lightTheme = vm.lightTheme,
darkTheme = vm.darkTheme,
windowDecorations = vm.windowDecorations
windowDecorations = vm.windowDecorations,
customColors = colors,
customExtraColors = extraColors
)
}
}
@@ -112,12 +134,16 @@ fun SettingsAppearanceScreenContent(
themeMode: PreferenceMutableStateFlow<ThemeMode>,
lightTheme: PreferenceMutableStateFlow<Int>,
darkTheme: PreferenceMutableStateFlow<Int>,
windowDecorations: PreferenceMutableStateFlow<Boolean>
windowDecorations: PreferenceMutableStateFlow<Boolean>,
customColors: Colors,
customExtraColors: ExtraColors
) {
val isLight = MaterialTheme.colors.isLight
val themesForCurrentMode = remember(isLight) {
themes.filter { it.colors.isLight == isLight }
}
val currentLightTheme by lightTheme.collectAsState()
val currentDarkTheme by darkTheme.collectAsState()
Scaffold(
modifier = Modifier.windowInsetsPadding(
@@ -138,7 +164,7 @@ fun SettingsAppearanceScreenContent(
WindowInsets.navigationBars.only(
WindowInsetsSides.Bottom
)
).asPaddingValues()
).asPaddingValues(),
) {
item {
ChoicePreference(
@@ -156,16 +182,51 @@ fun SettingsAppearanceScreenContent(
stringResource(MR.strings.preset_themes),
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 4.dp)
)
LazyRow(modifier = Modifier.padding(horizontal = 8.dp)) {
LazyRow(
modifier = Modifier
.animateContentSize()
.padding(vertical = 8.dp),
contentPadding = PaddingValues(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
items(themesForCurrentMode) { theme ->
ThemeItem(
theme,
onClick = {
(if (isLight) lightTheme else darkTheme).value = it.id
activeColors.primaryStateFlow.value = it.colors.primary
activeColors.secondaryStateFlow.value = it.colors.secondary
Column(
modifier = Modifier
.width(114.dp)
.padding(top = 8.dp),
) {
val isSelected = (isLight && currentLightTheme == theme.id) ||
(!isLight && currentDarkTheme == theme.id)
MaterialTheme(
colors = if (isSelected) customColors else theme.colors,
) {
ExtraColors.WithExtraColors(
if (isSelected) customExtraColors else theme.extraColors
) {
AppThemePreviewItem(
selected = isSelected,
onClick = {
(if (isLight) lightTheme else darkTheme).value = theme.id
activeColors.primaryStateFlow.value = theme.colors.primary
activeColors.secondaryStateFlow.value = theme.colors.secondary
activeColors.tertiaryStateFlow.value = theme.extraColors.tertiary
},
)
}
}
)
Text(
text = stringResource(theme.titleRes),
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.secondaryItemAlpha(),
color = MaterialTheme.colors.onSurface,
textAlign = TextAlign.Center,
maxLines = 2,
style = MaterialTheme.typography.body2,
)
}
}
}
}
@@ -185,6 +246,14 @@ fun SettingsAppearanceScreenContent(
unsetColor = MaterialTheme.colors.secondary
)
}
item {
ColorPreference(
preference = activeColors.tertiaryStateFlow,
title = stringResource(MR.strings.color_tertiary),
subtitle = stringResource(MR.strings.color_secondary_sub),
unsetColor = MaterialTheme.extraColors.tertiary
)
}
if (showWindowDecorationsOption) {
item {
SwitchPreference(
@@ -213,55 +282,132 @@ fun SettingsAppearanceScreenContent(
}
@Composable
private fun ThemeItem(
theme: Theme,
onClick: (Theme) -> Unit
fun AppThemePreviewItem(
selected: Boolean,
onClick: () -> Unit,
) {
val borders = MaterialTheme.shapes.small
val borderColor = if (theme.colors.isLight) {
Color.Black.copy(alpha = 0.25f)
} else {
Color.White.copy(alpha = 0.15f)
}
Surface(
onClick = { onClick(theme) },
elevation = 4.dp,
color = theme.colors.background,
shape = borders,
val dividerColor = MaterialTheme.colors.onSurface.copy(alpha = 0.2F)
Column(
modifier = Modifier
.size(100.dp, 160.dp)
.padding(8.dp)
.border(1.dp, borderColor, borders)
.fillMaxWidth()
.aspectRatio(9f / 16f)
.border(
width = 4.dp,
color = if (selected) {
MaterialTheme.colors.primary
} else {
dividerColor
},
shape = RoundedCornerShape(17.dp),
)
.padding(4.dp)
.clip(RoundedCornerShape(13.dp))
.background(MaterialTheme.colors.background)
.clickable(onClick = onClick),
) {
Column {
// App Bar
Row(
modifier = Modifier
.fillMaxWidth()
.height(40.dp)
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
Modifier
.fillMaxWidth()
.weight(1f)
.padding(6.dp)
modifier = Modifier
.fillMaxHeight(0.8f)
.weight(0.7f)
.padding(end = 4.dp)
.background(
color = MaterialTheme.colors.onSurface,
shape = MaterialTheme.shapes.small,
),
)
Box(
modifier = Modifier.weight(0.3f),
contentAlignment = Alignment.CenterEnd,
) {
Text(stringResource(MR.strings.theme_text), fontSize = 11.sp)
Button(
onClick = {},
enabled = false,
contentPadding = PaddingValues(),
modifier = Modifier
.align(Alignment.BottomStart)
.size(40.dp, 20.dp),
content = {},
colors = ButtonDefaults.buttonColors(
disabledBackgroundColor = theme.colors.primary
if (selected) {
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = null,
tint = MaterialTheme.colors.primary,
)
}
}
}
// Cover
Box(
modifier = Modifier
.padding(start = 8.dp, top = 2.dp)
.background(
color = dividerColor,
shape = MaterialTheme.shapes.small,
)
Surface(
Modifier
.size(24.dp)
.align(Alignment.BottomEnd),
shape = MaterialTheme.shapes.small.copy(CornerSize(percent = 50)),
color = theme.colors.secondary,
elevation = 6.dp,
content = { }
.fillMaxWidth(0.5f)
.aspectRatio(mangaAspectRatio),
) {
Row(
modifier = Modifier
.padding(4.dp)
.size(width = 24.dp, height = 16.dp)
.clip(RoundedCornerShape(5.dp)),
) {
Box(
modifier = Modifier
.fillMaxHeight()
.width(12.dp)
.background(MaterialTheme.extraColors.tertiary),
)
Box(
modifier = Modifier
.fillMaxHeight()
.width(12.dp)
.background(MaterialTheme.colors.secondary),
)
}
}
// Bottom bar
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
contentAlignment = Alignment.BottomCenter,
) {
Surface(
elevation = 3.dp,
) {
Row(
modifier = Modifier
.height(32.dp)
.fillMaxWidth()
.background(MaterialTheme.colors.primarySurface)
.padding(horizontal = 8.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
modifier = Modifier
.size(17.dp)
.background(
color = MaterialTheme.colors.primary,
shape = CircleShape,
),
)
Box(
modifier = Modifier
.padding(start = 8.dp)
.alpha(0.6f)
.height(17.dp)
.weight(1f)
.background(
color = MaterialTheme.colors.onSurface,
shape = MaterialTheme.shapes.small,
),
)
}
}
}
}

View File

@@ -0,0 +1,21 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.uicore.components
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.ui.unit.dp
private val horizontal = 16.dp
private val vertical = 8.dp
val horizontalPadding = horizontal
val verticalPadding = vertical
val topPaddingValues = PaddingValues(top = vertical)
const val ReadItemAlpha = .38f
const val SecondaryItemAlpha = .78f

View File

@@ -11,6 +11,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.alpha
fun Modifier.selectedBackground(isSelected: Boolean): Modifier = composed {
if (isSelected) {
@@ -20,3 +21,5 @@ fun Modifier.selectedBackground(isSelected: Boolean): Modifier = composed {
this
}
}
fun Modifier.secondaryItemAlpha(): Modifier = this.alpha(SecondaryItemAlpha)

View File

@@ -0,0 +1,62 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package ca.gosyer.jui.uicore.theme
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.graphics.Color
@Stable
class ExtraColors(
tertiary: Color,
onTertiary: Color,
) {
var tertiary by mutableStateOf(tertiary, structuralEqualityPolicy())
internal set
var onTertiary by mutableStateOf(onTertiary, structuralEqualityPolicy())
internal set
fun copy(
tertiary: Color = this.tertiary,
onTertiary: Color = this.onTertiary,
): ExtraColors = ExtraColors(
tertiary,
onTertiary,
)
override fun toString(): String {
return "ExtraColors(" +
"tertiary=$tertiary, " +
"onTertiary=$onTertiary, " +
")"
}
companion object {
@Composable
fun WithExtraColors(extraColors: ExtraColors, content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalExtraColors provides extraColors,
content = content
)
}
}
}
val MaterialTheme.extraColors: ExtraColors
@Composable
get() = LocalExtraColors.current
private val LocalExtraColors = staticCompositionLocalOf<ExtraColors> {
error("The AppColors composable must be called before usage")
}

View File

@@ -10,21 +10,92 @@ import androidx.compose.material.Colors
import androidx.compose.material.darkColors
import androidx.compose.material.lightColors
import androidx.compose.ui.graphics.Color
import ca.gosyer.jui.i18n.MR
import dev.icerock.moko.resources.StringResource
data class Theme(
val id: Int,
val colors: Colors
val titleRes: StringResource,
val colors: Colors,
val extraColors: ExtraColors
)
fun tachiyomiLightColors(
primary: Color = Color(0xFF0057CE),
primaryVariant: Color = Color(0xFF001947),
secondary: Color = Color(0xFF0057CE),
secondaryVariant: Color = Color(0xFF018786),
background: Color = Color(0xFFFDFBFF),
surface: Color = Color(0xFFFDFBFF),
error: Color = Color(0xFFB00020),
onPrimary: Color = Color.White,
onSecondary: Color = Color.White,
onBackground: Color = Color(0xFF1B1B1E),
onSurface: Color = Color(0xFF1B1B1E),
onError: Color = Color.White
) = lightColors(
primary = primary,
primaryVariant = primaryVariant,
secondary = secondary,
secondaryVariant = secondaryVariant,
background = background,
surface = surface,
error = error,
onPrimary = onPrimary,
onSecondary = onSecondary,
onBackground = onBackground,
onSurface = onSurface,
onError = onError
)
fun tachiyomiDarkColors(
primary: Color = Color(0xFFAEC6FF),
primaryVariant: Color = Color(0xFF00419E),
secondary: Color = Color(0xFFAEC6FF),
secondaryVariant: Color = Color(0xFF00419E),
background: Color = Color(0xFF1B1B1E),
surface: Color = Color(0xFF1B1B1E),
error: Color = Color(0xFFCF6679),
onPrimary: Color = Color(0xFF002C71),
onSecondary: Color = Color(0xFF002C71),
onBackground: Color = Color(0xFFE4E2E6),
onSurface: Color = Color(0xFFE4E2E6),
onError: Color = Color.White
) = darkColors(
primary = primary,
primaryVariant = primaryVariant,
secondary = secondary,
secondaryVariant = secondaryVariant,
background = background,
surface = surface,
error = error,
onPrimary = onPrimary,
onSecondary = onSecondary,
onBackground = onBackground,
onSurface = onSurface,
onError = onError
)
fun extraColors(
tertiary: Color = Color(0xFF006E17),
onTertiary: Color = Color.White,
) = ExtraColors(
tertiary = tertiary,
onTertiary = onTertiary
)
val themes = listOf(
// Pure white
Theme(
1,
lightColors()
),
// Tachiyomi 0.x default colors
Theme(
1,
MR.strings.theme_default,
tachiyomiLightColors(),
extraColors()
),
// Tachiyomi 0.x legacy blue theme
Theme(
2,
MR.strings.theme_legacy_blue,
lightColors(
primary = Color(0xFF2979FF),
primaryVariant = Color(0xFF2979FF),
@@ -32,20 +103,29 @@ val themes = listOf(
secondary = Color(0xFF2979FF),
secondaryVariant = Color(0xFF2979FF),
onSecondary = Color.White
)
),
extraColors()
),
// Tachiyomi 0.x dark theme
Theme(
3,
darkColors()
MR.strings.theme_default,
tachiyomiDarkColors(),
extraColors(
tertiary = Color(0xFF7ADC77),
onTertiary = Color(0xFF003907)
)
),
// AMOLED theme
Theme(
4,
darkColors(
MR.strings.theme_amoled,
tachiyomiDarkColors(
primary = Color.Black,
onPrimary = Color.White,
background = Color.Black
)
background = Color.Black,
surface = Color.Black
),
extraColors()
)
)