diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 7c82c921a8..684dc5c29c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -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" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 0b5bae2545..7e75acca6c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt index a8896a5bc9..2ee7533f24 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt index 25b417cebc..6614f9c6fb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 36e4fff0a9..633e7af31b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -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() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt index 6268f069d5..ca124c2f59 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt @@ -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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt index dca513d5c7..c0a6ea7194 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt @@ -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 diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt index 4716fa24ca..73fda3cc52 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/ImageUtil.kt @@ -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) diff --git a/app/src/main/res/layout/reader_settings_sheet.xml b/app/src/main/res/layout/reader_settings_sheet.xml index d28d64fc84..95624aafba 100644 --- a/app/src/main/res/layout/reader_settings_sheet.xml +++ b/app/src/main/res/layout/reader_settings_sheet.xml @@ -159,6 +159,16 @@ android:textColor="?android:attr/textColorSecondary" app:layout_constraintTop_toBottomOf="@id/fullscreen" /> + + Fullscreen Dual page split (ALPHA) + Invert dual page split placement + If the placement of the dual page split doesn\'t match reading direction Show content in cutout area Lock orientation Animate page transitions