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:
Andreas 2021-02-20 15:26:57 +01:00 committed by GitHub
parent 3a790f3d66
commit 776610d0e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 68 additions and 20 deletions

View File

@ -25,6 +25,8 @@ object PreferenceKeys {
const val dualPageSplit = "pref_dual_page_split" const val dualPageSplit = "pref_dual_page_split"
const val dualPageInvert = "pref_dual_page_invert"
const val showReadingMode = "pref_show_reading_mode" const val showReadingMode = "pref_show_reading_mode"
const val trueColor = "pref_true_color_key" const val trueColor = "pref_true_color_key"

View File

@ -91,6 +91,8 @@ class PreferencesHelper(val context: Context) {
fun dualPageSplit() = flowPrefs.getBoolean(Keys.dualPageSplit, false) fun dualPageSplit() = flowPrefs.getBoolean(Keys.dualPageSplit, false)
fun dualPageInvert() = flowPrefs.getBoolean(Keys.dualPageInvert, false)
fun showReadingMode() = prefs.getBoolean(Keys.showReadingMode, true) fun showReadingMode() = prefs.getBoolean(Keys.showReadingMode, true)
fun trueColor() = flowPrefs.getBoolean(Keys.trueColor, false) fun trueColor() = flowPrefs.getBoolean(Keys.trueColor, false)

View File

@ -6,14 +6,17 @@ import android.widget.Spinner
import androidx.annotation.ArrayRes import androidx.annotation.ArrayRes
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.NestedScrollView import androidx.core.widget.NestedScrollView
import androidx.lifecycle.lifecycleScope
import com.tfcporciuncula.flow.Preference import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.databinding.ReaderSettingsSheetBinding import eu.kanade.tachiyomi.databinding.ReaderSettingsSheetBinding
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog
import kotlinx.coroutines.flow.launchIn
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
/** /**
@ -71,6 +74,12 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BaseBottomShee
binding.alwaysShowChapterTransition.bindToPreference(preferences.alwaysShowChapterTransition()) binding.alwaysShowChapterTransition.bindToPreference(preferences.alwaysShowChapterTransition())
binding.pageTransitions.bindToPreference(preferences.pageTransitions()) 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 the preference is explicitly disabled, that means the setting was configured since there is a cutout
if (activity.hasCutout || !preferences.cutoutShort().get()) { if (activity.hasCutout || !preferences.cutoutShort().get()) {
binding.cutoutShort.isVisible = true binding.cutoutShort.isVisible = true

View File

@ -25,6 +25,7 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
var trueColor = false var trueColor = false
var alwaysShowChapterTransition = true var alwaysShowChapterTransition = true
var dualPageSplit = false var dualPageSplit = false
var dualPageInvert = false
var navigationMode = 0 var navigationMode = 0
protected set protected set
@ -58,6 +59,9 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C
preferences.dualPageSplit() preferences.dualPageSplit()
.register({ dualPageSplit = it }, { imagePropertyChangedListener?.invoke() }) .register({ dualPageSplit = it }, { imagePropertyChangedListener?.invoke() })
preferences.dualPageInvert()
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
} }
protected abstract fun defaultNavigation(): ViewerNavigation protected abstract fun defaultNavigation(): ViewerNavigation

View File

@ -264,24 +264,29 @@ class PagerPageHolder(
else -> ImageUtil.isDoublePage(inputStream) else -> ImageUtil.isDoublePage(inputStream)
} }
inputStream = stream 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) { if (!isDoublePage) return inputStream
onPageSplit()
}
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() { private fun onPageSplit() {

View File

@ -292,7 +292,8 @@ class WebtoonPageHolder(
openStream = if (!isDoublePage) { openStream = if (!isDoublePage) {
stream stream
} else { } else {
ImageUtil.splitAndMerge(stream) val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
ImageUtil.splitAndMerge(stream, upperSide)
} }
} }
if (!isAnimated) { if (!isAnimated) {

View File

@ -55,6 +55,13 @@ class SettingsReaderController : SettingsController() {
titleRes = R.string.pref_dual_page_split titleRes = R.string.pref_dual_page_split
defaultValue = false 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) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
switchPreference { switchPreference {
key = Keys.trueColor key = Keys.trueColor

View File

@ -115,7 +115,7 @@ object ImageUtil {
/** /**
* Split the image into left and right parts, then merge them into a new image. * 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 imageBytes = imageStream.readBytes()
val imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) 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 result = Bitmap.createBitmap(width / 2, height * 2, Bitmap.Config.ARGB_8888)
val canvas = Canvas(result) val canvas = Canvas(result)
// right -> upper // 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) val upperPart = Rect(0, 0, width / 2, height)
canvas.drawBitmap(imageBitmap, rightPart, upperPart, null) canvas.drawBitmap(imageBitmap, rightPart, upperPart, null)
// left -> bottom // 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) val bottomPart = Rect(0, height, width / 2, height * 2)
canvas.drawBitmap(imageBitmap, leftPart, bottomPart, null) canvas.drawBitmap(imageBitmap, leftPart, bottomPart, null)

View File

@ -159,6 +159,16 @@
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
app:layout_constraintTop_toBottomOf="@id/fullscreen" /> 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 <com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/cutout_short" android:id="@+id/cutout_short"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -166,7 +176,7 @@
android:text="@string/pref_cutout_short" android:text="@string/pref_cutout_short"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:visibility="gone" android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/dual_page_split" app:layout_constraintTop_toBottomOf="@id/dual_page_invert"
tools:visibility="visible" /> tools:visibility="visible" />
<com.google.android.material.switchmaterial.SwitchMaterial <com.google.android.material.switchmaterial.SwitchMaterial

View File

@ -251,6 +251,8 @@
<!-- Reader section --> <!-- Reader section -->
<string name="pref_fullscreen">Fullscreen</string> <string name="pref_fullscreen">Fullscreen</string>
<string name="pref_dual_page_split">Dual page split (ALPHA)</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_cutout_short">Show content in cutout area</string>
<string name="pref_lock_orientation">Lock orientation</string> <string name="pref_lock_orientation">Lock orientation</string>
<string name="pref_page_transitions">Animate page transitions</string> <string name="pref_page_transitions">Animate page transitions</string>