mirror of
https://github.com/mihonapp/mihon.git
synced 2025-06-28 20:17:51 +02:00
Merge light and dark themes (#5470)
* Merge AMOLED and regular dark themes This allows all variants of dark themes to use black backgrounds as a separate preference. * Merge light and dark themes * Fix ReaderSeekBar color on Dark Blue theme * Color fixes * Fix Dark Blue bars ripple * Simplify night mode check
This commit is contained in:
@ -7,9 +7,9 @@ object PreferenceKeys {
|
||||
|
||||
const val themeMode = "pref_theme_mode_key"
|
||||
|
||||
const val themeLight = "pref_theme_light_key"
|
||||
const val appTheme = "pref_app_theme"
|
||||
|
||||
const val themeDark = "pref_theme_dark_key"
|
||||
const val themeDarkAmoled = "pref_theme_dark_amoled_key"
|
||||
|
||||
const val confirmExit = "pref_confirm_exit"
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package eu.kanade.tachiyomi.data.preference
|
||||
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
const val UNMETERED_NETWORK = "wifi"
|
||||
const val CHARGING = "ac"
|
||||
|
||||
@ -17,26 +19,18 @@ object PreferenceValues {
|
||||
system,
|
||||
}
|
||||
|
||||
// Keys are lowercase to match legacy string values
|
||||
enum class LightThemeVariant {
|
||||
default,
|
||||
blue,
|
||||
strawberrydaiquiri,
|
||||
yotsuba
|
||||
}
|
||||
|
||||
// Keys are lowercase to match legacy string values
|
||||
enum class DarkThemeVariant {
|
||||
default,
|
||||
blue,
|
||||
greenapple,
|
||||
midnightdusk,
|
||||
amoled,
|
||||
hotpink,
|
||||
}
|
||||
|
||||
/* ktlint-enable experimental:enum-entry-name-case */
|
||||
|
||||
enum class AppTheme(val titleResId: Int) {
|
||||
DEFAULT(R.string.theme_default),
|
||||
DARK_BLUE(R.string.theme_darkblue),
|
||||
GREEN_APPLE(R.string.theme_greenapple),
|
||||
HOT_PINK(R.string.theme_hotpink),
|
||||
MIDNIGHT_DUSK(R.string.theme_midnightdusk),
|
||||
STRAWBERRY_DAIQUIRI(R.string.theme_strawberrydaiquiri),
|
||||
YOTSUBA(R.string.theme_yotsuba)
|
||||
}
|
||||
|
||||
enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false) {
|
||||
NONE,
|
||||
HORIZONTAL(shouldInvertHorizontal = true),
|
||||
|
@ -1,7 +1,6 @@
|
||||
package eu.kanade.tachiyomi.data.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.Environment
|
||||
import androidx.core.content.edit
|
||||
import androidx.core.net.toUri
|
||||
@ -90,9 +89,9 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun themeMode() = flowPrefs.getEnum(Keys.themeMode, system)
|
||||
|
||||
fun themeLight() = flowPrefs.getEnum(Keys.themeLight, Values.LightThemeVariant.default)
|
||||
fun appTheme() = flowPrefs.getEnum(Keys.appTheme, Values.AppTheme.DEFAULT)
|
||||
|
||||
fun themeDark() = flowPrefs.getEnum(Keys.themeDark, Values.DarkThemeVariant.default)
|
||||
fun themeDarkAmoled() = flowPrefs.getBoolean(Keys.themeDarkAmoled, false)
|
||||
|
||||
fun pageTransitions() = flowPrefs.getBoolean(Keys.enableTransitions, true)
|
||||
|
||||
@ -325,15 +324,4 @@ class PreferencesHelper(val context: Context) {
|
||||
putInt(Keys.defaultChapterSortByAscendingOrDescending, if (manga.sortDescending()) Manga.CHAPTER_SORT_DESC else Manga.CHAPTER_SORT_ASC)
|
||||
}
|
||||
}
|
||||
|
||||
fun isDarkMode(): Boolean {
|
||||
return when (themeMode().get()) {
|
||||
light -> false
|
||||
dark -> true
|
||||
system -> {
|
||||
context.applicationContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
|
||||
Configuration.UI_MODE_NIGHT_YES
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.ui.base.activity
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DarkThemeVariant
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.LightThemeVariant
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.util.view.setSecureScreen
|
||||
@ -19,7 +19,7 @@ abstract class BaseThemedActivity : AppCompatActivity() {
|
||||
val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(getThemeResourceId(preferences))
|
||||
applyThemePreferences(preferences)
|
||||
|
||||
Injekt.get<PreferencesHelper>().incognitoMode()
|
||||
.asImmediateFlow {
|
||||
@ -31,23 +31,49 @@ abstract class BaseThemedActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getThemeResourceId(preferences: PreferencesHelper): Int {
|
||||
return if (preferences.isDarkMode()) {
|
||||
when (preferences.themeDark().get()) {
|
||||
DarkThemeVariant.default -> R.style.Theme_Tachiyomi_Dark
|
||||
DarkThemeVariant.blue -> R.style.Theme_Tachiyomi_Dark_Blue
|
||||
DarkThemeVariant.greenapple -> R.style.Theme_Tachiyomi_Dark_GreenApple
|
||||
DarkThemeVariant.midnightdusk -> R.style.Theme_Tachiyomi_Dark_MidnightDusk
|
||||
DarkThemeVariant.amoled -> R.style.Theme_Tachiyomi_Amoled
|
||||
DarkThemeVariant.hotpink -> R.style.Theme_Tachiyomi_Amoled_HotPink
|
||||
fun AppCompatActivity.applyThemePreferences(preferences: PreferencesHelper) {
|
||||
val resIds = mutableListOf<Int>()
|
||||
when (preferences.appTheme().get()) {
|
||||
PreferenceValues.AppTheme.DEFAULT -> {
|
||||
resIds += R.style.Theme_Tachiyomi
|
||||
}
|
||||
} else {
|
||||
when (preferences.themeLight().get()) {
|
||||
LightThemeVariant.default -> R.style.Theme_Tachiyomi_Light
|
||||
LightThemeVariant.blue -> R.style.Theme_Tachiyomi_Light_Blue
|
||||
LightThemeVariant.strawberrydaiquiri -> R.style.Theme_Tachiyomi_Light_StrawberryDaiquiri
|
||||
LightThemeVariant.yotsuba -> R.style.Theme_Tachiyomi_Light_Yotsuba
|
||||
PreferenceValues.AppTheme.DARK_BLUE -> {
|
||||
resIds += R.style.Theme_Tachiyomi_DarkBlue
|
||||
resIds += R.style.ThemeOverlay_Tachiyomi_ColoredBars
|
||||
}
|
||||
PreferenceValues.AppTheme.GREEN_APPLE -> {
|
||||
resIds += R.style.Theme_Tachiyomi_GreenApple
|
||||
}
|
||||
PreferenceValues.AppTheme.HOT_PINK -> {
|
||||
resIds += R.style.Theme_Tachiyomi_HotPink
|
||||
}
|
||||
PreferenceValues.AppTheme.MIDNIGHT_DUSK -> {
|
||||
resIds += R.style.Theme_Tachiyomi_MidnightDusk
|
||||
}
|
||||
PreferenceValues.AppTheme.STRAWBERRY_DAIQUIRI -> {
|
||||
resIds += R.style.Theme_Tachiyomi_StrawberryDaiquiri
|
||||
}
|
||||
PreferenceValues.AppTheme.YOTSUBA -> {
|
||||
resIds += R.style.Theme_Tachiyomi_Yotsuba
|
||||
}
|
||||
}
|
||||
|
||||
if (preferences.themeDarkAmoled().get()) {
|
||||
resIds += R.style.ThemeOverlay_Tachiyomi_Amoled
|
||||
}
|
||||
|
||||
resIds.forEach {
|
||||
setTheme(it)
|
||||
}
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
AppCompatDelegate.setDefaultNightMode(
|
||||
when (preferences.themeMode().get()) {
|
||||
PreferenceValues.ThemeMode.light -> AppCompatDelegate.MODE_NIGHT_NO
|
||||
PreferenceValues.ThemeMode.dark -> AppCompatDelegate.MODE_NIGHT_YES
|
||||
PreferenceValues.ThemeMode.system -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.toggle
|
||||
import eu.kanade.tachiyomi.databinding.ReaderActivityBinding
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity.Companion.applyThemePreferences
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst
|
||||
@ -61,6 +61,7 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import eu.kanade.tachiyomi.util.system.hasDisplayCutout
|
||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.popupMenu
|
||||
import eu.kanade.tachiyomi.util.view.setTooltip
|
||||
@ -138,7 +139,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
* Called when the activity is created. Initializes the presenter and configuration.
|
||||
*/
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(BaseThemedActivity.getThemeResourceId(preferences))
|
||||
applyThemePreferences(preferences)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
binding = ReaderActivityBinding.inflate(layoutInflater)
|
||||
@ -353,7 +354,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
|
||||
initBottomShortcuts()
|
||||
|
||||
val alpha = if (preferences.isDarkMode()) 230 else 242 // 90% dark 95% light
|
||||
val alpha = if (isNightMode()) 230 else 242 // 90% dark 95% light
|
||||
val toolbarColor = ColorUtils.setAlphaComponent(getThemeColor(R.attr.colorToolbar), alpha)
|
||||
listOf(
|
||||
binding.toolbarBottom,
|
||||
@ -852,7 +853,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
binding.readerContainer.setBackgroundResource(
|
||||
when (preferences.readerTheme().get()) {
|
||||
0 -> android.R.color.white
|
||||
2 -> R.color.background_dark
|
||||
2 -> R.color.reader_background_dark
|
||||
else -> android.R.color.black
|
||||
}
|
||||
)
|
||||
|
@ -1,10 +1,13 @@
|
||||
package eu.kanade.tachiyomi.ui.reader
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Canvas
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import androidx.appcompat.widget.AppCompatSeekBar
|
||||
import com.mikepenz.aboutlibraries.util.getThemeColor
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
/**
|
||||
* Seekbar to show current chapter progress.
|
||||
@ -41,4 +44,12 @@ class ReaderSeekBar @JvmOverloads constructor(
|
||||
}
|
||||
return super.onTouchEvent(event)
|
||||
}
|
||||
|
||||
init {
|
||||
// Set color to onPrimary when ColoredBars theme is applied
|
||||
if (context.getThemeColor(R.attr.colorToolbar) == context.getThemeColor(R.attr.colorPrimary)) {
|
||||
thumbTintList = ColorStateList.valueOf(context.getThemeColor(R.attr.colorOnPrimary))
|
||||
progressTintList = thumbTintList
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,62 +119,30 @@ class SettingsGeneralController : SettingsController() {
|
||||
}
|
||||
}
|
||||
listPreference {
|
||||
key = Keys.themeLight
|
||||
titleRes = R.string.pref_theme_light
|
||||
entriesRes = arrayOf(
|
||||
R.string.theme_light_default,
|
||||
R.string.theme_light_blue,
|
||||
R.string.theme_light_strawberrydaiquiri,
|
||||
R.string.theme_light_yotsuba
|
||||
)
|
||||
entryValues = arrayOf(
|
||||
Values.LightThemeVariant.default.name,
|
||||
Values.LightThemeVariant.blue.name,
|
||||
Values.LightThemeVariant.strawberrydaiquiri.name,
|
||||
Values.LightThemeVariant.yotsuba.name
|
||||
)
|
||||
defaultValue = Values.LightThemeVariant.default.name
|
||||
key = Keys.appTheme
|
||||
titleRes = R.string.pref_app_theme
|
||||
|
||||
val appThemes = Values.AppTheme.values()
|
||||
entriesRes = appThemes.map { it.titleResId }.toTypedArray()
|
||||
entryValues = appThemes.map { it.name }.toTypedArray()
|
||||
defaultValue = appThemes[0].name
|
||||
summary = "%s"
|
||||
|
||||
preferences.themeMode().asImmediateFlow { isVisible = it != Values.ThemeMode.dark }
|
||||
.launchIn(viewScope)
|
||||
|
||||
onChange {
|
||||
if (preferences.themeMode().get() != Values.ThemeMode.dark) {
|
||||
activity?.recreate()
|
||||
}
|
||||
activity?.recreate()
|
||||
true
|
||||
}
|
||||
}
|
||||
listPreference {
|
||||
key = Keys.themeDark
|
||||
titleRes = R.string.pref_theme_dark
|
||||
entriesRes = arrayOf(
|
||||
R.string.theme_dark_default,
|
||||
R.string.theme_dark_blue,
|
||||
R.string.theme_dark_greenapple,
|
||||
R.string.theme_dark_midnightdusk,
|
||||
R.string.theme_dark_amoled,
|
||||
R.string.theme_dark_amoled_hotpink
|
||||
)
|
||||
entryValues = arrayOf(
|
||||
Values.DarkThemeVariant.default.name,
|
||||
Values.DarkThemeVariant.blue.name,
|
||||
Values.DarkThemeVariant.greenapple.name,
|
||||
Values.DarkThemeVariant.midnightdusk.name,
|
||||
Values.DarkThemeVariant.amoled.name,
|
||||
Values.DarkThemeVariant.hotpink.name
|
||||
)
|
||||
defaultValue = Values.DarkThemeVariant.default.name
|
||||
summary = "%s"
|
||||
switchPreference {
|
||||
key = Keys.themeDarkAmoled
|
||||
titleRes = R.string.pref_dark_theme_pure_black
|
||||
defaultValue = false
|
||||
|
||||
preferences.themeMode().asImmediateFlow { isVisible = it != Values.ThemeMode.light }
|
||||
.launchIn(viewScope)
|
||||
|
||||
onChange {
|
||||
if (preferences.themeMode().get() != Values.ThemeMode.light) {
|
||||
activity?.recreate()
|
||||
}
|
||||
activity?.recreate()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.net.ConnectivityManager
|
||||
@ -38,7 +39,6 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.util.lang.truncateCenter
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -277,3 +277,10 @@ fun Context.createFileInCacheDir(name: String): File {
|
||||
fun Context.isTablet(): Boolean {
|
||||
return resources.configuration.smallestScreenWidthDp >= 720
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if current context is in night mode
|
||||
*/
|
||||
fun Context.isNightMode(): Boolean {
|
||||
return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||
}
|
||||
|
@ -25,10 +25,8 @@ import com.google.android.material.elevation.ElevationOverlayProvider
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||
|
||||
/**
|
||||
* Returns coordinates of view.
|
||||
@ -186,7 +184,7 @@ inline fun ChipGroup.setChips(
|
||||
* Applies elevation overlay to a MaterialCardView
|
||||
*/
|
||||
inline fun MaterialCardView.applyElevationOverlay() {
|
||||
if (Injekt.get<PreferencesHelper>().isDarkMode()) {
|
||||
if (context.isNightMode()) {
|
||||
val provider = ElevationOverlayProvider(context)
|
||||
setCardBackgroundColor(provider.compositeOverlay(cardBackgroundColor.defaultColor, cardElevation))
|
||||
}
|
||||
|
@ -9,11 +9,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.system.displayCompat
|
||||
import eu.kanade.tachiyomi.util.system.isNightMode
|
||||
import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
abstract class BaseBottomSheetDialog(context: Context) : BottomSheetDialog(context) {
|
||||
|
||||
@ -45,7 +43,7 @@ abstract class BaseBottomSheetDialog(context: Context) : BottomSheetDialog(conte
|
||||
window?.setNavigationBarTransparentCompat(context)
|
||||
val bottomSheet = rootView.parent as ViewGroup
|
||||
var flags = bottomSheet.systemUiVisibility
|
||||
flags = if (Injekt.get<PreferencesHelper>().isDarkMode()) {
|
||||
flags = if (context.isNightMode()) {
|
||||
flags and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
|
||||
} else {
|
||||
flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
|
||||
|
Reference in New Issue
Block a user