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:
parent
3a790f3d66
commit
776610d0e6
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user