Merge branch 'master' of https://github.com/tachiyomiorg/tachiyomi into sync-part-final

This commit is contained in:
KaiserBh 2023-11-20 07:49:10 +11:00
commit 389d40ab41
No known key found for this signature in database
GPG Key ID: 14D73B142042BBA9
33 changed files with 1026 additions and 81 deletions

View File

@ -165,7 +165,6 @@ dependencies {
implementation(compose.ui.util)
implementation(compose.accompanist.webview)
implementation(compose.accompanist.permissions)
implementation(compose.accompanist.themeadapter)
implementation(compose.accompanist.systemuicontroller)
lintChecks(compose.lintchecks)

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Close
@ -20,7 +21,6 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.TopAppBar
@ -43,7 +43,6 @@ import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.VisualTransformation
@ -62,10 +61,11 @@ const val SEARCH_DEBOUNCE_MILLIS = 250L
@Composable
fun AppBar(
title: String?,
modifier: Modifier = Modifier,
backgroundColor: Color? = null,
// Text
title: String?,
subtitle: String? = null,
// Up button
navigateUp: (() -> Unit)? = null,
@ -90,7 +90,7 @@ fun AppBar(
if (isActionMode) {
AppBarTitle(actionModeCounter.toString())
} else {
AppBarTitle(title, subtitle)
AppBarTitle(title, subtitle = subtitle)
}
},
navigateUp = navigateUp,
@ -110,10 +110,11 @@ fun AppBar(
@Composable
fun AppBar(
modifier: Modifier = Modifier,
backgroundColor: Color? = null,
// Title
titleContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
backgroundColor: Color? = null,
// Up button
navigateUp: (() -> Unit)? = null,
navigationIcon: ImageVector? = null,
@ -140,7 +141,7 @@ fun AppBar(
} else {
navigateUp?.let {
IconButton(onClick = it) {
UpIcon(navigationIcon)
UpIcon(navigationIcon = navigationIcon)
}
}
}
@ -160,9 +161,10 @@ fun AppBar(
@Composable
fun AppBarTitle(
title: String?,
modifier: Modifier = Modifier,
subtitle: String? = null,
) {
Column {
Column(modifier = modifier) {
title?.let {
Text(
text = it,
@ -258,11 +260,12 @@ fun AppBarActions(
*/
@Composable
fun SearchToolbar(
searchQuery: String?,
onChangeSearchQuery: (String?) -> Unit,
modifier: Modifier = Modifier,
titleContent: @Composable () -> Unit = {},
navigateUp: (() -> Unit)? = null,
searchEnabled: Boolean = true,
searchQuery: String?,
onChangeSearchQuery: (String?) -> Unit,
placeholderText: String? = null,
onSearch: (String) -> Unit = {},
onClickCloseSearch: () -> Unit = { onChangeSearchQuery(null) },
@ -274,6 +277,7 @@ fun SearchToolbar(
val focusRequester = remember { FocusRequester() }
AppBar(
modifier = modifier,
titleContent = {
if (searchQuery == null) return@AppBar titleContent()
@ -390,12 +394,16 @@ fun SearchToolbar(
}
@Composable
fun UpIcon(navigationIcon: ImageVector? = null) {
fun UpIcon(
modifier: Modifier = Modifier,
navigationIcon: ImageVector? = null,
) {
val icon = navigationIcon
?: Icons.AutoMirrored.Outlined.ArrowBack
Icon(
imageVector = icon,
contentDescription = stringResource(MR.strings.action_bar_up_description),
modifier = modifier,
)
}

View File

@ -50,7 +50,7 @@ object CommonMangaItemDefaults {
const val BrowseFavoriteCoverAlpha = 0.34f
}
private val ContinueReadingButtonSize = 32.dp
private val ContinueReadingButtonSize = 28.dp
private val ContinueReadingButtonGridPadding = 6.dp
private val ContinueReadingButtonListSpacing = 8.dp

View File

@ -67,7 +67,7 @@ fun MangaToolbar(
},
navigationIcon = {
IconButton(onClick = onBackClicked) {
UpIcon(Icons.Outlined.Close.takeIf { isActionMode })
UpIcon(navigationIcon = Icons.Outlined.Close.takeIf { isActionMode })
}
},
actions = {

View File

@ -85,8 +85,6 @@ object SettingsDataScreen : SearchableSettings {
@Composable
private fun getBackupAndRestoreGroup(backupPreferences: BackupPreferences): Preference.PreferenceGroup {
val context = LocalContext.current
val backupIntervalPref = backupPreferences.backupInterval()
val backupInterval by backupIntervalPref.collectAsState()
val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState()
return Preference.PreferenceGroup(
@ -98,7 +96,7 @@ object SettingsDataScreen : SearchableSettings {
// Automatic backups
Preference.PreferenceItem.ListPreference(
pref = backupIntervalPref,
pref = backupPreferences.backupInterval(),
title = stringResource(MR.strings.pref_backup_interval),
entries = mapOf(
0 to stringResource(MR.strings.off),
@ -113,12 +111,6 @@ object SettingsDataScreen : SearchableSettings {
true
},
),
Preference.PreferenceItem.ListPreference(
pref = backupPreferences.numberOfBackups(),
enabled = backupInterval != 0,
title = stringResource(MR.strings.pref_backup_slots),
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
),
Preference.PreferenceItem.InfoPreference(
stringResource(MR.strings.backup_info) + "\n\n" +
stringResource(MR.strings.last_auto_backup_info, relativeTimeSpanString(lastAutoBackup)),

View File

@ -245,10 +245,12 @@ object SettingsReaderScreen : SearchableSettings {
val navModePref = readerPreferences.navigationModeWebtoon()
val dualPageSplitPref = readerPreferences.dualPageSplitWebtoon()
val rotateToFitPref = readerPreferences.dualPageRotateToFitWebtoon()
val webtoonSidePaddingPref = readerPreferences.webtoonSidePadding()
val navMode by navModePref.collectAsState()
val dualPageSplit by dualPageSplitPref.collectAsState()
val rotateToFit by rotateToFitPref.collectAsState()
val webtoonSidePadding by webtoonSidePaddingPref.collectAsState()
return Preference.PreferenceGroup(
@ -300,6 +302,10 @@ object SettingsReaderScreen : SearchableSettings {
Preference.PreferenceItem.SwitchPreference(
pref = dualPageSplitPref,
title = stringResource(MR.strings.pref_dual_page_split),
onValueChanged = {
rotateToFitPref.set(false)
true
},
),
Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.dualPageInvertWebtoon(),
@ -307,6 +313,19 @@ object SettingsReaderScreen : SearchableSettings {
subtitle = stringResource(MR.strings.pref_dual_page_invert_summary),
enabled = dualPageSplit,
),
Preference.PreferenceItem.SwitchPreference(
pref = rotateToFitPref,
title = stringResource(MR.strings.pref_page_rotate),
onValueChanged = {
dualPageSplitPref.set(false)
true
},
),
Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.dualPageRotateToFitInvertWebtoon(),
title = stringResource(MR.strings.pref_page_rotate_invert),
enabled = rotateToFit,
),
Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.webtoonDoubleTapZoomEnabled(),
title = stringResource(MR.strings.pref_double_tap_zoom),

View File

@ -180,6 +180,19 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
)
}
val dualPageRotateToFitWebtoon by screenModel.preferences.dualPageRotateToFitWebtoon().collectAsState()
CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate),
pref = screenModel.preferences.dualPageRotateToFitWebtoon(),
)
if (dualPageRotateToFitWebtoon) {
CheckboxItem(
label = stringResource(MR.strings.pref_page_rotate_invert),
pref = screenModel.preferences.dualPageRotateToFitInvertWebtoon(),
)
}
CheckboxItem(
label = stringResource(MR.strings.pref_double_tap_zoom),
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(),

View File

@ -1,54 +1,62 @@
package eu.kanade.presentation.theme
import androidx.appcompat.view.ContextThemeWrapper
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import com.google.accompanist.themeadapter.material3.createMdc3Theme
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.domain.ui.model.AppTheme
import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
@Composable
fun TachiyomiTheme(content: @Composable () -> Unit) {
val context = LocalContext.current
val layoutDirection = LocalLayoutDirection.current
val (colorScheme, typography) = createMdc3Theme(
context = context,
layoutDirection = layoutDirection,
)
MaterialTheme(
colorScheme = colorScheme!!,
typography = typography!!,
content = content,
)
}
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.StrawberryColorScheme
import eu.kanade.presentation.theme.colorscheme.TachiyomiColorScheme
import eu.kanade.presentation.theme.colorscheme.TakoColorScheme
import eu.kanade.presentation.theme.colorscheme.TealTurqoiseColorScheme
import eu.kanade.presentation.theme.colorscheme.TidalWaveColorScheme
import eu.kanade.presentation.theme.colorscheme.YinYangColorScheme
import eu.kanade.presentation.theme.colorscheme.YotsubaColorScheme
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@Composable
fun TachiyomiTheme(
appTheme: AppTheme,
amoled: Boolean,
appTheme: AppTheme? = null,
amoled: Boolean? = null,
content: @Composable () -> Unit,
) {
val originalContext = LocalContext.current
val layoutDirection = LocalLayoutDirection.current
val themedContext = remember(appTheme, originalContext) {
val themeResIds = ThemingDelegate.getThemeResIds(appTheme, amoled)
themeResIds.fold(originalContext) { context, themeResId ->
ContextThemeWrapper(context, themeResId)
}
}
val (colorScheme, typography) = createMdc3Theme(
context = themedContext,
layoutDirection = layoutDirection,
)
MaterialTheme(
colorScheme = colorScheme!!,
typography = typography!!,
colorScheme = getThemeColorScheme(appTheme, amoled),
content = content,
)
}
@Composable
@ReadOnlyComposable
private fun getThemeColorScheme(
appTheme: AppTheme?,
amoled: Boolean?,
): ColorScheme {
val uiPreferences = Injekt.get<UiPreferences>()
val colorScheme = when (appTheme ?: uiPreferences.appTheme().get()) {
AppTheme.DEFAULT -> TachiyomiColorScheme
AppTheme.MONET -> MonetColorScheme(LocalContext.current)
AppTheme.GREEN_APPLE -> GreenAppleColorScheme
AppTheme.LAVENDER -> LavenderColorScheme
AppTheme.MIDNIGHT_DUSK -> MidnightDuskColorScheme
AppTheme.STRAWBERRY_DAIQUIRI -> StrawberryColorScheme
AppTheme.TAKO -> TakoColorScheme
AppTheme.TEALTURQUOISE -> TealTurqoiseColorScheme
AppTheme.TIDAL_WAVE -> TidalWaveColorScheme
AppTheme.YINYANG -> YinYangColorScheme
AppTheme.YOTSUBA -> YotsubaColorScheme
else -> TachiyomiColorScheme
}
return colorScheme.getColorScheme(
isSystemInDarkTheme(),
amoled ?: uiPreferences.themeDarkAmoled().get(),
)
}

View File

@ -0,0 +1,26 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.ColorScheme
import androidx.compose.ui.graphics.Color
internal abstract class BaseColorScheme {
abstract val darkScheme: ColorScheme
abstract val lightScheme: ColorScheme
fun getColorScheme(isDark: Boolean, isAmoled: Boolean): ColorScheme {
return (if (isDark) darkScheme else lightScheme)
.let {
if (isDark && isAmoled) {
it.copy(
background = Color.Black,
onBackground = Color.White,
surface = Color.Black,
onSurface = Color.White,
)
} else {
it
}
}
}
}

View File

@ -0,0 +1,71 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Green Apple theme
* Original color scheme by CarlosEsco, Jays2Kings and CrepeTF
* M3 colors generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary #188140
* Secondary #188140
* Tertiary #D33131
* Neutral #5D5F5B
*/
internal object GreenAppleColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFF7ADB8F),
onPrimary = Color(0xFF003915),
primaryContainer = Color(0xFF005322),
onPrimaryContainer = Color(0xFF96F8A9),
inversePrimary = Color(0xFF006D2F),
secondary = Color(0xFF7ADB8F),
onSecondary = Color(0xFF003915),
secondaryContainer = Color(0xFF005322),
onSecondaryContainer = Color(0xFF96F8A9),
tertiary = Color(0xFFFFB3AA),
onTertiary = Color(0xFF680006),
tertiaryContainer = Color(0xFF93000D),
onTertiaryContainer = Color(0xFFFFDAD5),
background = Color(0xFF1A1C19),
onBackground = Color(0xFFE1E3DD),
surface = Color(0xFF1A1C19),
onSurface = Color(0xFFE1E3DD),
surfaceVariant = Color(0xFF414941),
onSurfaceVariant = Color(0xFFC1C8BE),
surfaceTint = Color(0xFF7ADB8F),
inverseSurface = Color(0xFFE1E3DD),
inverseOnSurface = Color(0xFF1A1C19),
outline = Color(0xFF8B9389),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF006D2F),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFF96F8A9),
onPrimaryContainer = Color(0xFF002109),
inversePrimary = Color(0xFF7ADB8F),
secondary = Color(0xFF006D2F),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFF96F8A9),
onSecondaryContainer = Color(0xFF002109),
tertiary = Color(0xFFB91D22),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFFFFDAD5),
onTertiaryContainer = Color(0xFF410003),
background = Color(0xFFFBFDF7),
onBackground = Color(0xFF1A1C19),
surface = Color(0xFFFBFDF7),
onSurface = Color(0xFF1A1C19),
surfaceVariant = Color(0xFFDDE5DA),
onSurfaceVariant = Color(0xFF414941),
surfaceTint = Color(0xFF006D2F),
inverseSurface = Color(0xFF2F312E),
inverseOnSurface = Color(0xFFF0F2EC),
outline = Color(0xFF717970),
)
}

View File

@ -0,0 +1,70 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Lavender theme
* Color scheme by Osyx
*
* Key colors:
* Primary #A177FF
* Secondary #A177FF
* Tertiary #5E25E1
* Neutral #111129
*/
internal object LavenderColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFA177FF),
onPrimary = Color(0xFF111129),
primaryContainer = Color(0xFFA177FF),
onPrimaryContainer = Color(0xFF111129),
inversePrimary = Color(0xFF006D2F),
secondary = Color(0xFFA177FF),
onSecondary = Color(0xFF111129),
secondaryContainer = Color(0xFFA177FF),
onSecondaryContainer = Color(0xFF111129),
tertiary = Color(0xFF5E25E1),
onTertiary = Color(0xFFE8E8E8),
tertiaryContainer = Color(0xFF111129),
onTertiaryContainer = Color(0xFFDEE8FF),
background = Color(0xFF111129),
onBackground = Color(0xFFDEE8FF),
surface = Color(0xFF111129),
onSurface = Color(0xFFDEE8FF),
surfaceVariant = Color(0x2CB6B6B6),
onSurfaceVariant = Color(0xFFE8E8E8),
surfaceTint = Color(0xFFA177FF),
inverseSurface = Color(0xFF221247),
inverseOnSurface = Color(0xFFDEE8FF),
outline = Color(0xA8905FFF),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF7B46AF),
onPrimary = Color(0xFFEDE2FF),
primaryContainer = Color(0xFF7B46AF),
onPrimaryContainer = Color(0xFFEDE2FF),
inversePrimary = Color(0xFFD6BAFF),
secondary = Color(0xFF7B46AF),
onSecondary = Color(0xFFEDE2FF),
secondaryContainer = Color(0xFF7B46AF),
onSecondaryContainer = Color(0xFFEDE2FF),
tertiary = Color(0xFFEDE2FF),
onTertiary = Color(0xFF7B46AF),
tertiaryContainer = Color(0xFFEDE2FF),
onTertiaryContainer = Color(0xFF7B46AF),
background = Color(0xFFEDE2FF),
onBackground = Color(0xFF1B1B22),
surface = Color(0xFFEDE2FF),
onSurface = Color(0xFF1B1B22),
surfaceVariant = Color(0xFFB9B0CC),
onSurfaceVariant = Color(0xD849454E),
surfaceTint = Color(0xFF7B46AF),
inverseSurface = Color(0xFF313033),
inverseOnSurface = Color(0xFFF3EFF4),
outline = Color(0xFF7B46AF),
)
}

View File

@ -0,0 +1,71 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Midnight Dusk theme
* Original color scheme by CrepeTF
* M3 color scheme generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary #F02475
* Secondary #F02475
* Tertiary #7A5733
* Neutral #16151D
*/
internal object MidnightDuskColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFF02475),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFBD1C5C),
onPrimaryContainer = Color(0xFFFFFFFF),
inversePrimary = Color(0xFFF02475),
secondary = Color(0xFFF02475),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFF02475),
onSecondaryContainer = Color(0xFFFFFFFF),
tertiary = Color(0xFF55971C),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF386412),
onTertiaryContainer = Color(0xFFE5E1E5),
background = Color(0xFF16151D),
onBackground = Color(0xFFE5E1E5),
surface = Color(0xFF16151D),
onSurface = Color(0xFFE5E1E5),
surfaceVariant = Color(0xFF524346),
onSurfaceVariant = Color(0xFFD6C1C4),
surfaceTint = Color(0xFFF02475),
inverseSurface = Color(0xFF333043),
inverseOnSurface = Color(0xFFFFFFFF),
outline = Color(0xFF9F8C8F),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFFBB0054),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFFFD9E1),
onPrimaryContainer = Color(0xFF3F0017),
inversePrimary = Color(0xFFFFB1C4),
secondary = Color(0xFFBB0054),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFFFD9E1),
onSecondaryContainer = Color(0xFF3F0017),
tertiary = Color(0xFF006638),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF00894b),
onTertiaryContainer = Color(0xFF2D1600),
background = Color(0xFFFFFBFF),
onBackground = Color(0xFF1C1B1F),
surface = Color(0xFFFFFBFF),
onSurface = Color(0xFF1C1B1F),
surfaceVariant = Color(0xFFF3DDE0),
onSurfaceVariant = Color(0xFF524346),
surfaceTint = Color(0xFFBB0054),
inverseSurface = Color(0xFF313033),
inverseOnSurface = Color(0xFFF4F0F4),
outline = Color(0xFF847376),
)
}

View File

@ -0,0 +1,125 @@
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
internal class MonetColorScheme(context: Context) : BaseColorScheme() {
private val monet = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
MonetSystemColorScheme(context)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
val seed = WallpaperManager.getInstance(context)
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM)
?.primaryColor
?.toArgb()
if (seed != null) {
MonetCompatColorScheme(context, seed)
} else {
TachiyomiColorScheme
}
} else {
TachiyomiColorScheme
}
override val darkScheme
get() = monet.darkScheme
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)
private class MonetSystemColorScheme(context: Context) : BaseColorScheme() {
override val lightScheme = dynamicLightColorScheme(context)
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)
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<UiModeManager>()?.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(),
)
}
}
}

View File

@ -0,0 +1,71 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Strawberry Daiquiri theme
* Original color scheme by Soitora
* M3 color scheme generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary #ED4A65
* Secondary #ED4A65
* Tertiary #775930
* Neutral #655C5C
*/
internal object StrawberryColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFFFB2B9),
onPrimary = Color(0xFF67001B),
primaryContainer = Color(0xFF91002A),
onPrimaryContainer = Color(0xFFFFDADD),
inversePrimary = Color(0xFFB61E40),
secondary = Color(0xFFFFB2B9),
onSecondary = Color(0xFF67001B),
secondaryContainer = Color(0xFF91002A),
onSecondaryContainer = Color(0xFFFFDADD),
tertiary = Color(0xFFE8C08E),
onTertiary = Color(0xFF432C06),
tertiaryContainer = Color(0xFF5D421B),
onTertiaryContainer = Color(0xFFFFDDB1),
background = Color(0xFF201A1A),
onBackground = Color(0xFFECDFDF),
surface = Color(0xFF201A1A),
onSurface = Color(0xFFECDFDF),
surfaceVariant = Color(0xFF534344),
onSurfaceVariant = Color(0xFFD7C1C2),
surfaceTint = Color(0xFFFFB2B9),
inverseSurface = Color(0xFFECDFDF),
inverseOnSurface = Color(0xFF201A1A),
outline = Color(0xFFA08C8D),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFFB61E40),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFFFDADD),
onPrimaryContainer = Color(0xFF40000D),
inversePrimary = Color(0xFFFFB2B9),
secondary = Color(0xFFB61E40),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFFFDADD),
onSecondaryContainer = Color(0xFF40000D),
tertiary = Color(0xFF775930),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFFFFDDB1),
onTertiaryContainer = Color(0xFF2A1800),
background = Color(0xFFFCFCFC),
onBackground = Color(0xFF201A1A),
surface = Color(0xFFFCFCFC),
onSurface = Color(0xFF201A1A),
surfaceVariant = Color(0xFFF4DDDD),
onSurfaceVariant = Color(0xFF534344),
surfaceTint = Color(0xFFB61E40),
inverseSurface = Color(0xFF362F2F),
inverseOnSurface = Color(0xFFFBEDED),
outline = Color(0xFF857374),
)
}

View File

@ -0,0 +1,80 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Default theme
* M3 colors generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary #2979FF
* Secondary #2979FF
* Tertiary #47A84A
* Neutral #919094
*/
internal object TachiyomiColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFB0C6FF),
onPrimary = Color(0xFF002D6E),
primaryContainer = Color(0xFF00429B),
onPrimaryContainer = Color(0xFFD9E2FF),
inversePrimary = Color(0xFF0058CA),
secondary = Color(0xFFB0C6FF),
onSecondary = Color(0xFF002D6E),
secondaryContainer = Color(0xFF00429B),
onSecondaryContainer = Color(0xFFD9E2FF),
tertiary = Color(0xFF7ADC77),
onTertiary = Color(0xFF003909),
tertiaryContainer = Color(0xFF005312),
onTertiaryContainer = Color(0xFF95F990),
background = Color(0xFF1B1B1F),
onBackground = Color(0xFFE3E2E6),
surface = Color(0xFF1B1B1F),
onSurface = Color(0xFFE3E2E6),
surfaceVariant = Color(0xFF44464F),
onSurfaceVariant = Color(0xFFC5C6D0),
surfaceTint = Color(0xFFB0C6FF),
inverseSurface = Color(0xFFE3E2E6),
inverseOnSurface = Color(0xFF1B1B1F),
error = Color(0xFFFFB4AB),
onError = Color(0xFF690005),
errorContainer = Color(0xFF93000A),
onErrorContainer = Color(0xFFFFDAD6),
outline = Color(0xFF8F9099),
outlineVariant = Color(0xFF44464F),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF0058CA),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFD9E2FF),
onPrimaryContainer = Color(0xFF001945),
inversePrimary = Color(0xFFB0C6FF),
secondary = Color(0xFF0058CA),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFD9E2FF),
onSecondaryContainer = Color(0xFF001945),
tertiary = Color(0xFF006E1B),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF95F990),
onTertiaryContainer = Color(0xFF002203),
background = Color(0xFFFEFBFF),
onBackground = Color(0xFF1B1B1F),
surface = Color(0xFFFEFBFF),
onSurface = Color(0xFF1B1B1F),
surfaceVariant = Color(0xFFE1E2EC),
onSurfaceVariant = Color(0xFF44464F),
surfaceTint = Color(0xFF0058CA),
inverseSurface = Color(0xFF303034),
inverseOnSurface = Color(0xFFF2F0F4),
error = Color(0xFFBA1A1A),
onError = Color(0xFFFFFFFF),
errorContainer = Color(0xFFFFDAD6),
onErrorContainer = Color(0xFF410002),
outline = Color(0xFF757780),
outlineVariant = Color(0xFFC5C6D0),
)
}

View File

@ -0,0 +1,71 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Tako theme
* Original color scheme by ghostbear
* M3 color scheme generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary #F3B375
* Secondary #F3B375
* Tertiary #66577E
* Neutral #21212E
*/
internal object TakoColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFF3B375),
onPrimary = Color(0xFF38294E),
primaryContainer = Color(0xFFF3B375),
onPrimaryContainer = Color(0xFF38294E),
inversePrimary = Color(0xFF84531E),
secondary = Color(0xFFF3B375),
onSecondary = Color(0xFF38294E),
secondaryContainer = Color(0xFFF3B375),
onSecondaryContainer = Color(0xFF38294E),
tertiary = Color(0xFF66577E),
onTertiary = Color(0xFFF3B375),
tertiaryContainer = Color(0xFF4E4065),
onTertiaryContainer = Color(0xFFEDDCFF),
background = Color(0xFF21212E),
onBackground = Color(0xFFE3E0F2),
surface = Color(0xFF21212E),
onSurface = Color(0xFFE3E0F2),
surfaceVariant = Color(0xFF49454E),
onSurfaceVariant = Color(0xFFCBC4CE),
surfaceTint = Color(0xFF66577E),
inverseSurface = Color(0xFFE5E1E6),
inverseOnSurface = Color(0xFF1B1B1E),
outline = Color(0xFF958F99),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF66577E),
onPrimary = Color(0xFFF3B375),
primaryContainer = Color(0xFF66577E),
onPrimaryContainer = Color(0xFFF3B375),
inversePrimary = Color(0xFFD6BAFF),
secondary = Color(0xFF66577E),
onSecondary = Color(0xFFF3B375),
secondaryContainer = Color(0xFF66577E),
onSecondaryContainer = Color(0xFFF3B375),
tertiary = Color(0xFFF3B375),
onTertiary = Color(0xFF574360),
tertiaryContainer = Color(0xFFFDD6B0),
onTertiaryContainer = Color(0xFF221437),
background = Color(0xFFF7F5FF),
onBackground = Color(0xFF1B1B22),
surface = Color(0xFFF7F5FF),
onSurface = Color(0xFF1B1B22),
surfaceVariant = Color(0xFFE8E0EB),
onSurfaceVariant = Color(0xFF49454E),
surfaceTint = Color(0xFF66577E),
inverseSurface = Color(0xFF313033),
inverseOnSurface = Color(0xFFF3EFF4),
outline = Color(0xFF7A757E),
)
}

View File

@ -0,0 +1,63 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Teal Turqoise theme
*/
internal object TealTurqoiseColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFF40E0D0),
onPrimary = Color(0xFF000000),
primaryContainer = Color(0xFF40E0D0),
onPrimaryContainer = Color(0xFF000000),
inversePrimary = Color(0xFF008080),
secondary = Color(0xFF40E0D0),
onSecondary = Color(0xFF000000),
secondaryContainer = Color(0xFF18544E),
onSecondaryContainer = Color(0xFF40E0D0),
tertiary = Color(0xFFBF1F2F),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF200508),
onTertiaryContainer = Color(0xFFBF1F2F),
background = Color(0xFF202125),
onBackground = Color(0xFFDFDEDA),
surface = Color(0xFF202125),
onSurface = Color(0xFFDFDEDA),
surfaceVariant = Color(0xFF3F4947),
onSurfaceVariant = Color(0xFFDFDEDA),
surfaceTint = Color(0xFF40E0D0),
inverseSurface = Color(0xFFDFDEDA),
inverseOnSurface = Color(0xFF202125),
outline = Color(0xFF899391),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF008080),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFF008080),
onPrimaryContainer = Color(0xFFFFFFFF),
inversePrimary = Color(0xFF40E0D0),
secondary = Color(0xFF008080),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFBFDFDF),
onSecondaryContainer = Color(0xFF008080),
tertiary = Color(0xFFFF7F7F),
onTertiary = Color(0xFF000000),
tertiaryContainer = Color(0xFF2A1616),
onTertiaryContainer = Color(0xFFFF7F7F),
background = Color(0xFFFAFAFA),
onBackground = Color(0xFF050505),
surface = Color(0xFFFAFAFA),
onSurface = Color(0xFF050505),
surfaceVariant = Color(0xFFDAE5E2),
onSurfaceVariant = Color(0xFF050505),
surfaceTint = Color(0xFFBFDFDF),
inverseSurface = Color(0xFF050505),
inverseOnSurface = Color(0xFFFAFAFA),
outline = Color(0xFF6F7977),
)
}

View File

@ -0,0 +1,70 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Tidal Wave theme
* Original color scheme by NahutabDevelop
*
* Key colors:
* Primary #004152
* Secondary #5ed4fc
* Tertiary #92f7bc
* Neutral #16151D
*/
internal object TidalWaveColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFF5ed4fc),
onPrimary = Color(0xFF003544),
primaryContainer = Color(0xFF004d61),
onPrimaryContainer = Color(0xFFb8eaff),
inversePrimary = Color(0xFFa12b03),
secondary = Color(0xFF5ed4fc),
onSecondary = Color(0xFF003544),
secondaryContainer = Color(0xFF004d61),
onSecondaryContainer = Color(0xFFb8eaff),
tertiary = Color(0xFF92f7bc),
onTertiary = Color(0xFF001c3b),
tertiaryContainer = Color(0xFFc3fada),
onTertiaryContainer = Color(0xFF78ffd6),
background = Color(0xFF001c3b),
onBackground = Color(0xFFd5e3ff),
surface = Color(0xFF001c3b),
onSurface = Color(0xFFd5e3ff),
surfaceVariant = Color(0xFF40484c),
onSurfaceVariant = Color(0xFFbfc8cc),
surfaceTint = Color(0xFF5ed4fc),
inverseSurface = Color(0xFFffe3c4),
inverseOnSurface = Color(0xFF001c3b),
outline = Color(0xFF8a9296),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF006780),
onPrimary = Color(0xFFffffff),
primaryContainer = Color(0xFFB4D4DF),
onPrimaryContainer = Color(0xFF001f28),
inversePrimary = Color(0xFFff987f),
secondary = Color(0xFF006780),
onSecondary = Color(0xFFffffff),
secondaryContainer = Color(0xFFb8eaff),
onSecondaryContainer = Color(0xFF001f28),
tertiary = Color(0xFF92f7bc),
onTertiary = Color(0xFF001c3b),
tertiaryContainer = Color(0xFFc3fada),
onTertiaryContainer = Color(0xFF78ffd6),
background = Color(0xFFfdfbff),
onBackground = Color(0xFF001c3b),
surface = Color(0xFFfdfbff),
onSurface = Color(0xFF001c3b),
surfaceVariant = Color(0xFFdce4e8),
onSurfaceVariant = Color(0xFF40484c),
surfaceTint = Color(0xFF006780),
inverseSurface = Color(0xFF020400),
inverseOnSurface = Color(0xFFffe3c4),
outline = Color(0xFF70787c),
)
}

View File

@ -0,0 +1,65 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Yin & Yang theme
* Original color scheme by Riztard
* M3 colors generated by yours truly + tweaked manually
*/
internal object YinYangColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFFFFFFF),
onPrimary = Color(0xFF5A5A5A),
primaryContainer = Color(0xFFFFFFFF),
onPrimaryContainer = Color(0xFF000000),
inversePrimary = Color(0xFFCECECE),
secondary = Color(0xFFFFFFFF),
onSecondary = Color(0xFF5A5A5A),
secondaryContainer = Color(0xFF717171),
onSecondaryContainer = Color(0xFFE4E4E4),
tertiary = Color(0xFF000000),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFF00419E),
onTertiaryContainer = Color(0xFFD8E2FF),
background = Color(0xFF1E1E1E),
onBackground = Color(0xFFE6E6E6),
surface = Color(0xFF1E1E1E),
onSurface = Color(0xFFE6E6E6),
surfaceVariant = Color(0xFF4E4E4E),
onSurfaceVariant = Color(0xFFD1D1D1),
surfaceTint = Color(0xFFFFFFFF),
inverseSurface = Color(0xFFE6E6E6),
inverseOnSurface = Color(0xFF1E1E1E),
outline = Color(0xFF999999),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFF000000),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFF000000),
onPrimaryContainer = Color(0xFFFFFFFF),
inversePrimary = Color(0xFFA6A6A6),
secondary = Color(0xFF000000),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFDDDDDD),
onSecondaryContainer = Color(0xFF0C0C0C),
tertiary = Color(0xFFFFFFFF),
onTertiary = Color(0xFF000000),
tertiaryContainer = Color(0xFFD8E2FF),
onTertiaryContainer = Color(0xFF001947),
background = Color(0xFFFDFDFD),
onBackground = Color(0xFF222222),
surface = Color(0xFFFDFDFD),
onSurface = Color(0xFF222222),
surfaceVariant = Color(0xFFEDEDED),
onSurfaceVariant = Color(0xFF515151),
surfaceTint = Color(0xFF000000),
inverseSurface = Color(0xFF333333),
inverseOnSurface = Color(0xFFF4F4F4),
outline = Color(0xFF838383),
)
}

View File

@ -0,0 +1,71 @@
package eu.kanade.presentation.theme.colorscheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
/**
* Colors for Yotsuba theme
* Original color scheme by ztimms73
* M3 colors generated by Material Theme Builder (https://goo.gle/material-theme-builder-web)
*
* Key colors:
* Primary 0xFFAE3200
* Secondary 0xFFAE3200
* Tertiary 0xFF6B5E2F
* Neutral 0xFF655C5A
*/
internal object YotsubaColorScheme : BaseColorScheme() {
override val darkScheme = darkColorScheme(
primary = Color(0xFFFFB59D),
onPrimary = Color(0xFF5F1600),
primaryContainer = Color(0xFF862200),
onPrimaryContainer = Color(0xFFFFDBCF),
inversePrimary = Color(0xFFAE3200),
secondary = Color(0xFFFFB59D),
onSecondary = Color(0xFF5F1600),
secondaryContainer = Color(0xFF862200),
onSecondaryContainer = Color(0xFFFFDBCF),
tertiary = Color(0xFFD7C68D),
onTertiary = Color(0xFF3A2F05),
tertiaryContainer = Color(0xFF524619),
onTertiaryContainer = Color(0xFFF5E2A7),
background = Color(0xFF211A18),
onBackground = Color(0xFFEDE0DD),
surface = Color(0xFF211A18),
onSurface = Color(0xFFEDE0DD),
surfaceVariant = Color(0xFF53433F),
onSurfaceVariant = Color(0xFFD8C2BC),
surfaceTint = Color(0xFFFFB59D),
inverseSurface = Color(0xFFEDE0DD),
inverseOnSurface = Color(0xFF211A18),
outline = Color(0xFFA08C87),
)
override val lightScheme = lightColorScheme(
primary = Color(0xFFAE3200),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFFFDBCF),
onPrimaryContainer = Color(0xFF3B0A00),
inversePrimary = Color(0xFFFFB59D),
secondary = Color(0xFFAE3200),
onSecondary = Color(0xFFFFFFFF),
secondaryContainer = Color(0xFFFFDBCF),
onSecondaryContainer = Color(0xFF3B0A00),
tertiary = Color(0xFF6B5E2F),
onTertiary = Color(0xFFFFFFFF),
tertiaryContainer = Color(0xFFF5E2A7),
onTertiaryContainer = Color(0xFF231B00),
background = Color(0xFFFCFCFC),
onBackground = Color(0xFF211A18),
surface = Color(0xFFFCFCFC),
onSurface = Color(0xFF211A18),
surfaceVariant = Color(0xFFF5DED8),
onSurfaceVariant = Color(0xFF53433F),
surfaceTint = Color(0xFFAE3200),
inverseSurface = Color(0xFF362F2D),
inverseOnSurface = Color(0xFFFBEEEB),
outline = Color(0xFF85736E),
)
}

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.Application
import android.app.PendingIntent
import android.content.BroadcastReceiver
@ -12,7 +11,6 @@ import android.os.Build
import android.os.Looper
import android.webkit.WebView
import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
@ -39,6 +37,7 @@ import eu.kanade.tachiyomi.di.PreferenceModule
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.WebViewUtil
import eu.kanade.tachiyomi.util.system.animatorDurationScale
import eu.kanade.tachiyomi.util.system.cancelNotification
@ -157,7 +156,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
callFactory(callFactoryInit)
diskCache(diskCacheInit)
crossfade((300 * this@App.animatorDurationScale).toInt())
allowRgb565(getSystemService<ActivityManager>()!!.isLowRamDevice)
allowRgb565(DeviceUtil.isLowRamDevice(this@App))
if (networkPreferences.verboseLogging().get()) logger(DebugLogger())
// Coil spawns a new thread for every image load by default

View File

@ -295,9 +295,6 @@ object Migrations {
}
}
if (oldVersion < 84) {
if (backupPreferences.numberOfBackups().get() == 1) {
backupPreferences.numberOfBackups().set(2)
}
if (backupPreferences.backupInterval().get() == 0) {
backupPreferences.backupInterval().set(12)
BackupCreateJob.setupTask(context)

View File

@ -42,7 +42,6 @@ import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import tachiyomi.domain.history.interactor.GetHistory
@ -60,7 +59,6 @@ class BackupCreator(
private val handler: DatabaseHandler = Injekt.get()
private val sourceManager: SourceManager = Injekt.get()
private val backupPreferences: BackupPreferences = Injekt.get()
private val getCategories: GetCategories = Injekt.get()
private val getFavorites: GetFavorites = Injekt.get()
private val getHistory: GetHistory = Injekt.get()
@ -98,11 +96,10 @@ class BackupCreator(
dir = dir.createDirectory("automatic")
// Delete older backups
val numberOfBackups = backupPreferences.numberOfBackups().get()
dir.listFiles { _, filename -> Backup.filenameRegex.matches(filename) }
.orEmpty()
.sortedByDescending { it.name }
.drop(numberOfBackups - 1)
.drop(MAX_AUTO_BACKUPS - 1)
.forEach { it.delete() }
// Create new file to place backup
@ -269,3 +266,5 @@ class BackupCreator(
}
}
}
private val MAX_AUTO_BACKUPS: Int = 4

View File

@ -86,6 +86,10 @@ class ReaderPreferences(
fun dualPageRotateToFitInvert() = preferenceStore.getBoolean("pref_dual_page_rotate_invert", false)
fun dualPageRotateToFitWebtoon() = preferenceStore.getBoolean("pref_dual_page_rotate_webtoon", false)
fun dualPageRotateToFitInvertWebtoon() = preferenceStore.getBoolean("pref_dual_page_rotate_invert_webtoon", false)
// endregion
// region Color filter

View File

@ -62,6 +62,18 @@ class WebtoonConfig(
readerPreferences.dualPageInvertWebtoon()
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.dualPageRotateToFitWebtoon()
.register(
{ dualPageRotateToFit = it },
{ imagePropertyChangedListener?.invoke() },
)
readerPreferences.dualPageRotateToFitInvertWebtoon()
.register(
{ dualPageRotateToFitInvert = it },
{ imagePropertyChangedListener?.invoke() },
)
readerPreferences.webtoonDoubleTapZoomEnabled()
.register(
{ doubleTapZoom = it },

View File

@ -210,6 +210,10 @@ class WebtoonPageHolder(
}
private fun process(imageStream: BufferedInputStream): InputStream {
if (viewer.config.dualPageRotateToFit) {
return rotateDualPage(imageStream)
}
if (viewer.config.dualPageSplit) {
val isDoublePage = ImageUtil.isWideImage(imageStream)
if (isDoublePage) {
@ -221,6 +225,16 @@ class WebtoonPageHolder(
return imageStream
}
private fun rotateDualPage(imageStream: BufferedInputStream): InputStream {
val isDoublePage = ImageUtil.isWideImage(imageStream)
return if (isDoublePage) {
val rotation = if (viewer.config.dualPageRotateToFitInvert) -90f else 90f
ImageUtil.rotateImage(imageStream, rotation)
} else {
imageStream
}
}
/**
* Called when the page has an error.
*/

View File

@ -1,13 +1,16 @@
package eu.kanade.tachiyomi.util.system
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.os.Build
import androidx.core.content.getSystemService
import logcat.LogPriority
import tachiyomi.core.util.system.logcat
object DeviceUtil {
val isMiui by lazy {
val isMiui: Boolean by lazy {
getSystemProperty("ro.miui.ui.version.name")?.isNotEmpty() ?: false
}
@ -16,7 +19,7 @@ object DeviceUtil {
*
* @return MIUI major version code (e.g., 13) or null if can't be parsed.
*/
val miuiMajorVersion by lazy {
val miuiMajorVersion: Int? by lazy {
if (!isMiui) return@lazy null
Build.VERSION.INCREMENTAL
@ -41,11 +44,11 @@ object DeviceUtil {
}
}
val isSamsung by lazy {
val isSamsung: Boolean by lazy {
Build.MANUFACTURER.equals("samsung", ignoreCase = true)
}
val oneUiVersion by lazy {
val oneUiVersion: Double? by lazy {
try {
val semPlatformIntField = Build.VERSION::class.java.getDeclaredField("SEM_PLATFORM_INT")
val version = semPlatformIntField.getInt(null) - 90000
@ -65,6 +68,20 @@ object DeviceUtil {
"com.zui.resolver",
)
/**
* ActivityManager#isLowRamDevice is based on a system property, which isn't
* necessarily trustworthy. 1GB is supposedly the regular threshold.
*
* Instead, we consider anything with less than 3GB of RAM as low memory
* considering how heavy image processing can be.
*/
fun isLowRamDevice(context: Context): Boolean {
val memInfo = ActivityManager.MemoryInfo()
context.getSystemService<ActivityManager>()!!.getMemoryInfo(memInfo)
val totalMemBytes = memInfo.totalMem
return totalMemBytes < 3L * 1024 * 1024 * 1024
}
@SuppressLint("PrivateApi")
private fun getSystemProperty(key: String?): String? {
return try {

View File

@ -11,8 +11,6 @@ class BackupPreferences(
fun backupsDirectory() = preferenceStore.getString("backup_directory", folderProvider.path())
fun numberOfBackups() = preferenceStore.getInt("backup_slots", 2)
fun backupInterval() = preferenceStore.getInt("backup_interval", 12)
fun lastAutoBackupTimestamp() = preferenceStore.getLong(Preference.appStateKey("last_auto_backup_timestamp"), 0L)

View File

@ -23,7 +23,6 @@ glance = "androidx.glance:glance-appwidget:1.0.0"
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
accompanist-themeadapter = { module = "com.google.accompanist:accompanist-themeadapter-material3", version.ref = "accompanist" }
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
lintchecks = { module = "com.slack.lint.compose:compose-lint-checks", version = "1.2.0" }

View File

@ -38,8 +38,13 @@ multiplatformResources {
tasks {
val localesConfigTask = registerLocalesConfigTask(project)
preBuild {
dependsOn(localesConfigTask)
}
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf(
"-Xexpect-actual-classes",
)
}
}

View File

@ -476,7 +476,6 @@
<string name="pref_restore_backup_summ">Restore library from backup file</string>
<string name="pref_backup_directory">Backup location</string>
<string name="pref_backup_interval">Automatic backup frequency</string>
<string name="pref_backup_slots">Maximum automatic backups</string>
<string name="action_create">Create</string>
<string name="backup_created">Backup created</string>
<string name="invalid_backup_file">Invalid backup file</string>

View File

@ -35,3 +35,11 @@ android {
consumerProguardFile("consumer-proguard.pro")
}
}
tasks {
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf(
"-Xexpect-actual-classes",
)
}
}

View File

@ -41,6 +41,7 @@ android {
tasks {
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.freeCompilerArgs += listOf(
"-Xexpect-actual-classes",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
)
}