mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 06:17:57 +01:00 
			
		
		
		
	Match ReaderActivity theme with the rest of the app (#5450)
* Match ReaderActivity theme with the rest of the app * Fix viewer inset when fullscreen reader is off * Fix incorrect toolbar color after recreate * Remove animated inset * Move isDarkMode to PreferencesHelper
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| 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 | ||||
| @@ -10,6 +11,7 @@ import com.tfcporciuncula.flow.Preference | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode | ||||
| import eu.kanade.tachiyomi.data.preference.PreferenceValues.ThemeMode.* | ||||
| import eu.kanade.tachiyomi.data.track.TrackService | ||||
| import eu.kanade.tachiyomi.data.track.anilist.Anilist | ||||
| import eu.kanade.tachiyomi.ui.reader.setting.OrientationType | ||||
| @@ -84,7 +86,7 @@ class PreferencesHelper(val context: Context) { | ||||
|  | ||||
|     fun showLibraryUpdateErrors() = prefs.getBoolean(Keys.showLibraryUpdateErrors, true) | ||||
|  | ||||
|     fun themeMode() = flowPrefs.getEnum(Keys.themeMode, Values.ThemeMode.system) | ||||
|     fun themeMode() = flowPrefs.getEnum(Keys.themeMode, system) | ||||
|  | ||||
|     fun themeLight() = flowPrefs.getEnum(Keys.themeLight, Values.LightThemeVariant.default) | ||||
|  | ||||
| @@ -322,4 +324,15 @@ 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 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,14 +1,11 @@ | ||||
| package eu.kanade.tachiyomi.ui.base.activity | ||||
|  | ||||
| import android.content.res.Configuration.UI_MODE_NIGHT_MASK | ||||
| import android.content.res.Configuration.UI_MODE_NIGHT_YES | ||||
| import android.os.Bundle | ||||
| import androidx.appcompat.app.AppCompatActivity | ||||
| 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.ThemeMode | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.data.preference.asImmediateFlow | ||||
| import eu.kanade.tachiyomi.util.view.setSecureScreen | ||||
| @@ -22,29 +19,7 @@ abstract class BaseThemedActivity : AppCompatActivity() { | ||||
|     val preferences: PreferencesHelper by injectLazy() | ||||
|  | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         val isDarkMode = when (preferences.themeMode().get()) { | ||||
|             ThemeMode.light -> false | ||||
|             ThemeMode.dark -> true | ||||
|             ThemeMode.system -> resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES | ||||
|         } | ||||
|         val themeId = if (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 | ||||
|             } | ||||
|         } 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 | ||||
|             } | ||||
|         } | ||||
|         setTheme(themeId) | ||||
|         setTheme(getThemeResourceId(preferences)) | ||||
|  | ||||
|         Injekt.get<PreferencesHelper>().incognitoMode() | ||||
|             .asImmediateFlow { | ||||
| @@ -54,4 +29,26 @@ abstract class BaseThemedActivity : AppCompatActivity() { | ||||
|  | ||||
|         super.onCreate(savedInstanceState) | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|                 } | ||||
|             } 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 | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -6,11 +6,13 @@ import android.app.ProgressDialog | ||||
| import android.content.ClipData | ||||
| import android.content.Context | ||||
| import android.content.Intent | ||||
| import android.content.res.ColorStateList | ||||
| import android.graphics.Bitmap | ||||
| import android.graphics.Color | ||||
| import android.graphics.ColorMatrix | ||||
| import android.graphics.ColorMatrixColorFilter | ||||
| import android.graphics.Paint | ||||
| import android.graphics.drawable.ColorDrawable | ||||
| import android.os.Build | ||||
| import android.os.Bundle | ||||
| import android.view.KeyEvent | ||||
| @@ -23,12 +25,14 @@ import android.view.animation.Animation | ||||
| import android.view.animation.AnimationUtils | ||||
| import android.widget.SeekBar | ||||
| import android.widget.Toast | ||||
| import androidx.core.view.ViewCompat | ||||
| import androidx.core.view.WindowCompat | ||||
| import androidx.core.view.WindowInsetsCompat | ||||
| import androidx.core.view.WindowInsetsControllerCompat | ||||
| import androidx.core.view.isVisible | ||||
| import androidx.core.view.setPadding | ||||
| import androidx.lifecycle.lifecycleScope | ||||
| import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView | ||||
| import com.google.android.material.shape.MaterialShapeDrawable | ||||
| import dev.chrisbanes.insetter.applyInsetter | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| @@ -38,6 +42,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.main.MainActivity | ||||
| import eu.kanade.tachiyomi.ui.manga.MangaController | ||||
| import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst | ||||
| @@ -55,12 +60,8 @@ 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.toast | ||||
| import eu.kanade.tachiyomi.util.view.defaultBar | ||||
| import eu.kanade.tachiyomi.util.view.hideBar | ||||
| import eu.kanade.tachiyomi.util.view.isDefaultBar | ||||
| import eu.kanade.tachiyomi.util.view.popupMenu | ||||
| import eu.kanade.tachiyomi.util.view.setTooltip | ||||
| import eu.kanade.tachiyomi.util.view.showBar | ||||
| import eu.kanade.tachiyomi.widget.listener.SimpleAnimationListener | ||||
| import eu.kanade.tachiyomi.widget.listener.SimpleSeekBarListener | ||||
| import kotlinx.coroutines.flow.drop | ||||
| @@ -129,22 +130,20 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|  | ||||
|     private var readingModeToast: Toast? = null | ||||
|  | ||||
|     private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) } | ||||
|  | ||||
|     /** | ||||
|      * Called when the activity is created. Initializes the presenter and configuration. | ||||
|      */ | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         setTheme( | ||||
|             when (preferences.readerTheme().get()) { | ||||
|                 0 -> R.style.Theme_Reader_Light | ||||
|                 2 -> R.style.Theme_Reader_Dark_Grey | ||||
|                 else -> R.style.Theme_Reader_Dark | ||||
|             } | ||||
|         ) | ||||
|         setTheme(BaseThemedActivity.getThemeResourceId(preferences)) | ||||
|         super.onCreate(savedInstanceState) | ||||
|  | ||||
|         binding = ReaderActivityBinding.inflate(layoutInflater) | ||||
|         setContentView(binding.root) | ||||
|  | ||||
|         windowInsetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE | ||||
|  | ||||
|         if (presenter.needsInit()) { | ||||
|             val manga = intent.extras!!.getLong("manga", -1) | ||||
|             val chapter = intent.extras!!.getLong("chapter", -1) | ||||
| @@ -163,9 +162,10 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|         config = ReaderConfig() | ||||
|         initializeMenu() | ||||
|  | ||||
|         // Avoid status bar showing up on rotation | ||||
|         window.decorView.setOnSystemUiVisibilityChangeListener { | ||||
|             setMenuVisibility(menuVisible, animate = false) | ||||
|         binding.pageNumber.applyInsetter { | ||||
|             type(navigationBars = true) { | ||||
|                 margin() | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Finish when incognito mode is disabled | ||||
| @@ -299,17 +299,15 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|             onBackPressed() | ||||
|         } | ||||
|  | ||||
|         ViewCompat.setOnApplyWindowInsetsListener(binding.readerMenu) { _, insets -> | ||||
|             if (!window.isDefaultBar()) { | ||||
|                 val systemInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) | ||||
|                 binding.readerMenu.setPadding( | ||||
|                     systemInsets.left, | ||||
|                     systemInsets.top, | ||||
|                     systemInsets.right, | ||||
|                     systemInsets.bottom | ||||
|                 ) | ||||
|         binding.toolbar.applyInsetter { | ||||
|             type(navigationBars = true, statusBars = true) { | ||||
|                 margin(top = true, horizontal = true) | ||||
|             } | ||||
|         } | ||||
|         binding.readerMenuBottom.applyInsetter { | ||||
|             type(navigationBars = true) { | ||||
|                 margin(bottom = true, horizontal = true) | ||||
|             } | ||||
|             insets | ||||
|         } | ||||
|  | ||||
|         binding.toolbar.setOnClickListener { | ||||
| @@ -355,6 +353,21 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|  | ||||
|         initBottomShortcuts() | ||||
|  | ||||
|         val alpha = if (preferences.isDarkMode()) 230 else 242 // 90% dark 95% light | ||||
|         listOf( | ||||
|             binding.toolbarBottom, | ||||
|             binding.leftChapter, | ||||
|             binding.readerSeekbar, | ||||
|             binding.rightChapter | ||||
|         ).forEach { | ||||
|             it.background.alpha = alpha | ||||
|         } | ||||
|  | ||||
|         val systemBarsColor = (binding.toolbarBottom.background as ColorDrawable).color | ||||
|         window.statusBarColor = systemBarsColor | ||||
|         window.navigationBarColor = systemBarsColor | ||||
|         (binding.toolbar.background as MaterialShapeDrawable).fillColor = ColorStateList.valueOf(systemBarsColor) | ||||
|  | ||||
|         // Set initial visibility | ||||
|         setMenuVisibility(menuVisible) | ||||
|     } | ||||
| @@ -475,11 +488,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|     fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { | ||||
|         menuVisible = visible | ||||
|         if (visible) { | ||||
|             if (preferences.fullscreen().get()) { | ||||
|                 window.showBar() | ||||
|             } else { | ||||
|                 resetDefaultMenuAndBar() | ||||
|             } | ||||
|             windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) | ||||
|             binding.readerMenu.isVisible = true | ||||
|  | ||||
|             if (animate) { | ||||
| @@ -503,9 +512,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|             } | ||||
|         } else { | ||||
|             if (preferences.fullscreen().get()) { | ||||
|                 window.hideBar() | ||||
|             } else { | ||||
|                 resetDefaultMenuAndBar() | ||||
|                 windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) | ||||
|             } | ||||
|  | ||||
|             if (animate) { | ||||
| @@ -529,14 +536,6 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reset menu padding and system bar | ||||
|      */ | ||||
|     private fun resetDefaultMenuAndBar() { | ||||
|         binding.readerMenu.setPadding(0) | ||||
|         window.defaultBar() | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Called from the presenter when a manga is ready. Used to instantiate the appropriate viewer | ||||
|      * and the toolbar title. | ||||
| @@ -557,6 +556,7 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|             binding.viewerContainer.removeAllViews() | ||||
|         } | ||||
|         viewer = newViewer | ||||
|         updateViewerInset(preferences.fullscreen().get()) | ||||
|         binding.viewerContainer.addView(newViewer.getView()) | ||||
|  | ||||
|         if (preferences.showReadingMode()) { | ||||
| @@ -811,6 +811,19 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|         updateOrientationShortcut(presenter.getMangaOrientationType(resolveDefault = false)) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates viewer inset depending on fullscreen reader preferences. | ||||
|      */ | ||||
|     fun updateViewerInset(fullscreen: Boolean) { | ||||
|         viewer?.getView()?.applyInsetter { | ||||
|             if (!fullscreen) { | ||||
|                 type(navigationBars = true, statusBars = true) { | ||||
|                     padding() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Class that handles the user preferences of the reader. | ||||
|      */ | ||||
| @@ -831,8 +844,15 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|          */ | ||||
|         init { | ||||
|             preferences.readerTheme().asFlow() | ||||
|                 .drop(1) // We only care about updates | ||||
|                 .onEach { recreate() } | ||||
|                 .onEach { | ||||
|                     binding.readerContainer.setBackgroundResource( | ||||
|                         when (preferences.readerTheme().get()) { | ||||
|                             0 -> android.R.color.white | ||||
|                             2 -> R.color.background_dark | ||||
|                             else -> android.R.color.black | ||||
|                         } | ||||
|                     ) | ||||
|                 } | ||||
|                 .launchIn(lifecycleScope) | ||||
|  | ||||
|             preferences.showPageNumber().asFlow() | ||||
| @@ -868,6 +888,13 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>() | ||||
|             preferences.grayscale().asFlow() | ||||
|                 .onEach { setGrayscale(it) } | ||||
|                 .launchIn(lifecycleScope) | ||||
|  | ||||
|             preferences.fullscreen().asFlow() | ||||
|                 .onEach { | ||||
|                     WindowCompat.setDecorFitsSystemWindows(window, !it) | ||||
|                     updateViewerInset(it) | ||||
|                 } | ||||
|                 .launchIn(lifecycleScope) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -3,32 +3,11 @@ package eu.kanade.tachiyomi.util.view | ||||
| import android.content.Context | ||||
| import android.graphics.Color | ||||
| import android.os.Build | ||||
| import android.view.View | ||||
| import android.view.Window | ||||
| import android.view.WindowManager | ||||
| import eu.kanade.tachiyomi.util.system.InternalResourceHelper | ||||
| import eu.kanade.tachiyomi.util.system.getResourceColor | ||||
|  | ||||
| fun Window.showBar() { | ||||
|     decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or | ||||
|         View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or | ||||
|         View.SYSTEM_UI_FLAG_LAYOUT_STABLE | ||||
| } | ||||
|  | ||||
| fun Window.hideBar() { | ||||
|     decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or | ||||
|         View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or | ||||
|         View.SYSTEM_UI_FLAG_FULLSCREEN or | ||||
|         View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or | ||||
|         View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | ||||
| } | ||||
|  | ||||
| fun Window.defaultBar() { | ||||
|     decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE | ||||
| } | ||||
|  | ||||
| fun Window.isDefaultBar() = decorView.systemUiVisibility == View.SYSTEM_UI_FLAG_VISIBLE | ||||
|  | ||||
| /** | ||||
|  * Sets navigation bar color to transparent if system's config_navBarNeedsScrim is false, | ||||
|  * otherwise it will use the theme navigationBarColor with 70% opacity. | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package eu.kanade.tachiyomi.widget.sheet | ||||
|  | ||||
| import android.content.Context | ||||
| import android.content.res.Configuration | ||||
| import android.os.Build | ||||
| import android.os.Bundle | ||||
| import android.util.DisplayMetrics | ||||
| @@ -10,7 +9,6 @@ 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.PreferenceValues | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.util.system.displayCompat | ||||
| import eu.kanade.tachiyomi.util.view.setNavigationBarTransparentCompat | ||||
| @@ -45,16 +43,9 @@ abstract class BaseBottomSheetDialog(context: Context) : BottomSheetDialog(conte | ||||
|         @Suppress("DEPRECATION") | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             window?.setNavigationBarTransparentCompat(context) | ||||
|             val isDarkMode = when (Injekt.get<PreferencesHelper>().themeMode().get()) { | ||||
|                 PreferenceValues.ThemeMode.light -> false | ||||
|                 PreferenceValues.ThemeMode.dark -> true | ||||
|                 PreferenceValues.ThemeMode.system -> | ||||
|                     context.resources.configuration.uiMode and | ||||
|                         Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES | ||||
|             } | ||||
|             val bottomSheet = rootView.parent as ViewGroup | ||||
|             var flags = bottomSheet.systemUiVisibility | ||||
|             flags = if (isDarkMode) { | ||||
|             flags = if (Injekt.get<PreferencesHelper>().isDarkMode()) { | ||||
|                 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