mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Let users invert dual page split (#4470)
* Let users invert dual page split * Use Activity lifecycleScope and cleanup invert logic
This commit is contained in:
		@@ -25,6 +25,8 @@ object PreferenceKeys {
 | 
			
		||||
 | 
			
		||||
    const val dualPageSplit = "pref_dual_page_split"
 | 
			
		||||
 | 
			
		||||
    const val dualPageInvert = "pref_dual_page_invert"
 | 
			
		||||
 | 
			
		||||
    const val showReadingMode = "pref_show_reading_mode"
 | 
			
		||||
 | 
			
		||||
    const val trueColor = "pref_true_color_key"
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,8 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun dualPageSplit() = flowPrefs.getBoolean(Keys.dualPageSplit, false)
 | 
			
		||||
 | 
			
		||||
    fun dualPageInvert() = flowPrefs.getBoolean(Keys.dualPageInvert, false)
 | 
			
		||||
 | 
			
		||||
    fun showReadingMode() = prefs.getBoolean(Keys.showReadingMode, true)
 | 
			
		||||
 | 
			
		||||
    fun trueColor() = flowPrefs.getBoolean(Keys.trueColor, false)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,14 +6,17 @@ import android.widget.Spinner
 | 
			
		||||
import androidx.annotation.ArrayRes
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import androidx.core.widget.NestedScrollView
 | 
			
		||||
import androidx.lifecycle.lifecycleScope
 | 
			
		||||
import com.tfcporciuncula.flow.Preference
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.ReaderSettingsSheetBinding
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
 | 
			
		||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
 | 
			
		||||
import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog
 | 
			
		||||
import kotlinx.coroutines.flow.launchIn
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -71,6 +74,12 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BaseBottomShee
 | 
			
		||||
        binding.alwaysShowChapterTransition.bindToPreference(preferences.alwaysShowChapterTransition())
 | 
			
		||||
        binding.pageTransitions.bindToPreference(preferences.pageTransitions())
 | 
			
		||||
 | 
			
		||||
        // Makes so that dual page invert gets hidden away when turning of dual page split
 | 
			
		||||
        preferences.dualPageSplit()
 | 
			
		||||
            .asImmediateFlow { binding.dualPageInvert.isVisible = it }
 | 
			
		||||
            .launchIn(activity.lifecycleScope)
 | 
			
		||||
        binding.dualPageInvert.bindToPreference(preferences.dualPageInvert())
 | 
			
		||||
 | 
			
		||||
        // If the preference is explicitly disabled, that means the setting was configured since there is a cutout
 | 
			
		||||
        if (activity.hasCutout || !preferences.cutoutShort().get()) {
 | 
			
		||||
            binding.cutoutShort.isVisible = true
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
 | 
			
		||||
    var trueColor = false
 | 
			
		||||
    var alwaysShowChapterTransition = true
 | 
			
		||||
    var dualPageSplit = false
 | 
			
		||||
    var dualPageInvert = false
 | 
			
		||||
    var navigationMode = 0
 | 
			
		||||
        protected set
 | 
			
		||||
 | 
			
		||||
@@ -58,6 +59,9 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
 | 
			
		||||
 | 
			
		||||
        preferences.dualPageSplit()
 | 
			
		||||
            .register({ dualPageSplit = it }, { imagePropertyChangedListener?.invoke() })
 | 
			
		||||
 | 
			
		||||
        preferences.dualPageInvert()
 | 
			
		||||
            .register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract fun defaultNavigation(): ViewerNavigation
 | 
			
		||||
 
 | 
			
		||||
@@ -264,24 +264,29 @@ class PagerPageHolder(
 | 
			
		||||
            else -> ImageUtil.isDoublePage(inputStream)
 | 
			
		||||
        }
 | 
			
		||||
        inputStream = stream
 | 
			
		||||
        if (isDoublePage) {
 | 
			
		||||
            val side = when {
 | 
			
		||||
                viewer is L2RPagerViewer && page is InsertPage -> ImageUtil.Side.RIGHT
 | 
			
		||||
                viewer is R2LPagerViewer && page is InsertPage -> ImageUtil.Side.LEFT
 | 
			
		||||
                viewer is L2RPagerViewer && page !is InsertPage -> ImageUtil.Side.LEFT
 | 
			
		||||
                viewer is R2LPagerViewer && page !is InsertPage -> ImageUtil.Side.RIGHT
 | 
			
		||||
                viewer is VerticalPagerViewer && page !is InsertPage -> ImageUtil.Side.RIGHT
 | 
			
		||||
                viewer is VerticalPagerViewer && page is InsertPage -> ImageUtil.Side.LEFT
 | 
			
		||||
                else -> error("We should choose a side!")
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (page !is InsertPage) {
 | 
			
		||||
                onPageSplit()
 | 
			
		||||
            }
 | 
			
		||||
        if (!isDoublePage) return inputStream
 | 
			
		||||
 | 
			
		||||
            inputStream = ImageUtil.splitInHalf(inputStream, side)
 | 
			
		||||
        var side = when {
 | 
			
		||||
            viewer is L2RPagerViewer && page is InsertPage -> ImageUtil.Side.RIGHT
 | 
			
		||||
            (viewer is R2LPagerViewer || viewer is VerticalPagerViewer) && page is InsertPage -> ImageUtil.Side.LEFT
 | 
			
		||||
            viewer is L2RPagerViewer && page !is InsertPage -> ImageUtil.Side.LEFT
 | 
			
		||||
            (viewer is R2LPagerViewer || viewer is VerticalPagerViewer) && page !is InsertPage -> ImageUtil.Side.RIGHT
 | 
			
		||||
            else -> error("We should choose a side!")
 | 
			
		||||
        }
 | 
			
		||||
        return inputStream
 | 
			
		||||
 | 
			
		||||
        if (viewer.config.dualPageInvert) {
 | 
			
		||||
            side = when (side) {
 | 
			
		||||
                ImageUtil.Side.RIGHT -> ImageUtil.Side.LEFT
 | 
			
		||||
                ImageUtil.Side.LEFT -> ImageUtil.Side.RIGHT
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (page !is InsertPage) {
 | 
			
		||||
            onPageSplit()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ImageUtil.splitInHalf(inputStream, side)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun onPageSplit() {
 | 
			
		||||
 
 | 
			
		||||
@@ -292,7 +292,8 @@ class WebtoonPageHolder(
 | 
			
		||||
                    openStream = if (!isDoublePage) {
 | 
			
		||||
                        stream
 | 
			
		||||
                    } else {
 | 
			
		||||
                        ImageUtil.splitAndMerge(stream)
 | 
			
		||||
                        val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
 | 
			
		||||
                        ImageUtil.splitAndMerge(stream, upperSide)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (!isAnimated) {
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,13 @@ class SettingsReaderController : SettingsController() {
 | 
			
		||||
            titleRes = R.string.pref_dual_page_split
 | 
			
		||||
            defaultValue = false
 | 
			
		||||
        }
 | 
			
		||||
        switchPreference {
 | 
			
		||||
            key = Keys.dualPageInvert
 | 
			
		||||
            titleRes = R.string.pref_dual_page_invert
 | 
			
		||||
            summaryRes = R.string.pref_dual_page_invert_summary
 | 
			
		||||
            defaultValue = false
 | 
			
		||||
            preferences.dualPageSplit().asImmediateFlow { isVisible = it }.launchIn(viewScope)
 | 
			
		||||
        }
 | 
			
		||||
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 | 
			
		||||
            switchPreference {
 | 
			
		||||
                key = Keys.trueColor
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ object ImageUtil {
 | 
			
		||||
    /**
 | 
			
		||||
     * Split the image into left and right parts, then merge them into a new image.
 | 
			
		||||
     */
 | 
			
		||||
    fun splitAndMerge(imageStream: InputStream): InputStream {
 | 
			
		||||
    fun splitAndMerge(imageStream: InputStream, upperSide: Side): InputStream {
 | 
			
		||||
        val imageBytes = imageStream.readBytes()
 | 
			
		||||
 | 
			
		||||
        val imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
 | 
			
		||||
@@ -125,11 +125,17 @@ object ImageUtil {
 | 
			
		||||
        val result = Bitmap.createBitmap(width / 2, height * 2, Bitmap.Config.ARGB_8888)
 | 
			
		||||
        val canvas = Canvas(result)
 | 
			
		||||
        // right -> upper
 | 
			
		||||
        val rightPart = Rect(width - width / 2, 0, width, height)
 | 
			
		||||
        val rightPart = when (upperSide) {
 | 
			
		||||
            Side.RIGHT -> Rect(width - width / 2, 0, width, height)
 | 
			
		||||
            Side.LEFT -> Rect(0, 0, width / 2, height)
 | 
			
		||||
        }
 | 
			
		||||
        val upperPart = Rect(0, 0, width / 2, height)
 | 
			
		||||
        canvas.drawBitmap(imageBitmap, rightPart, upperPart, null)
 | 
			
		||||
        // left -> bottom
 | 
			
		||||
        val leftPart = Rect(0, 0, width / 2, height)
 | 
			
		||||
        val leftPart = when (upperSide) {
 | 
			
		||||
            Side.LEFT -> Rect(width - width / 2, 0, width, height)
 | 
			
		||||
            Side.RIGHT -> Rect(0, 0, width / 2, height)
 | 
			
		||||
        }
 | 
			
		||||
        val bottomPart = Rect(0, height, width / 2, height * 2)
 | 
			
		||||
        canvas.drawBitmap(imageBitmap, leftPart, bottomPart, null)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -159,6 +159,16 @@
 | 
			
		||||
        android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/fullscreen" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.switchmaterial.SwitchMaterial
 | 
			
		||||
        android:id="@+id/dual_page_invert"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="@string/pref_dual_page_invert"
 | 
			
		||||
        android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/dual_page_split"
 | 
			
		||||
        tools:visibility="visible" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.switchmaterial.SwitchMaterial
 | 
			
		||||
        android:id="@+id/cutout_short"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
@@ -166,7 +176,7 @@
 | 
			
		||||
        android:text="@string/pref_cutout_short"
 | 
			
		||||
        android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/dual_page_split"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/dual_page_invert"
 | 
			
		||||
        tools:visibility="visible" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.switchmaterial.SwitchMaterial
 | 
			
		||||
 
 | 
			
		||||
@@ -251,6 +251,8 @@
 | 
			
		||||
      <!-- Reader section -->
 | 
			
		||||
    <string name="pref_fullscreen">Fullscreen</string>
 | 
			
		||||
    <string name="pref_dual_page_split">Dual page split (ALPHA)</string>
 | 
			
		||||
    <string name="pref_dual_page_invert">Invert dual page split placement</string>
 | 
			
		||||
    <string name="pref_dual_page_invert_summary">If the placement of the dual page split doesn\'t match reading direction</string>
 | 
			
		||||
    <string name="pref_cutout_short">Show content in cutout area</string>
 | 
			
		||||
    <string name="pref_lock_orientation">Lock orientation</string>
 | 
			
		||||
    <string name="pref_page_transitions">Animate page transitions</string>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user