mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Viewer navigation (#3869)
* Viewer navigation Co-authored-by: Harsh Parekh <h.x.dev@outlook.com> * Match current reader behavior and add ability to invert it * A bit of clean up * Clean up inversion * Only create navigator when changed and change tap zone when invertTapping is changed * Clean up PagerConfig * Change how Viewer navigation works * Add Edge Navigation Co-authored-by: Harsh Parekh <h.x.dev@outlook.com>
This commit is contained in:
		@@ -65,6 +65,10 @@ object PreferenceKeys {
 | 
			
		||||
 | 
			
		||||
    const val readWithVolumeKeysInverted = "reader_volume_keys_inverted"
 | 
			
		||||
 | 
			
		||||
    const val navigationModePager = "reader_navigation_mode_pager"
 | 
			
		||||
 | 
			
		||||
    const val navigationModeWebtoon = "reader_navigation_mode_webtoon"
 | 
			
		||||
 | 
			
		||||
    const val webtoonSidePadding = "webtoon_side_padding"
 | 
			
		||||
 | 
			
		||||
    const val portraitColumns = "pref_library_columns_portrait_key"
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,10 @@ object PreferenceValues {
 | 
			
		||||
        LIST,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enum class TappingInvertMode {
 | 
			
		||||
    enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false) {
 | 
			
		||||
        NONE,
 | 
			
		||||
        HORIZONTAL,
 | 
			
		||||
        VERTICAL,
 | 
			
		||||
        BOTH
 | 
			
		||||
        HORIZONTAL(shouldInvertHorizontal = true),
 | 
			
		||||
        VERTICAL(shouldInvertVertical = true),
 | 
			
		||||
        BOTH(shouldInvertHorizontal = true, shouldInvertVertical = true)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -138,6 +138,10 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun readWithVolumeKeysInverted() = flowPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false)
 | 
			
		||||
 | 
			
		||||
    fun navigationModePager() = flowPrefs.getInt(Keys.navigationModePager, 0)
 | 
			
		||||
 | 
			
		||||
    fun navigationModeWebtoon() = flowPrefs.getInt(Keys.navigationModeWebtoon, 0)
 | 
			
		||||
 | 
			
		||||
    fun portraitColumns() = flowPrefs.getInt(Keys.portraitColumns, 0)
 | 
			
		||||
 | 
			
		||||
    fun landscapeColumns() = flowPrefs.getInt(Keys.landscapeColumns, 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -86,6 +86,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
 | 
			
		||||
        binding.webtoonPrefsGroup.isInvisible = true
 | 
			
		||||
        binding.pagerPrefsGroup.isVisible = true
 | 
			
		||||
 | 
			
		||||
        binding.pagerNav.bindToPreference(preferences.navigationModePager())
 | 
			
		||||
        binding.scaleType.bindToPreference(preferences.imageScaleType(), 1)
 | 
			
		||||
        binding.zoomStart.bindToPreference(preferences.zoomStart(), 1)
 | 
			
		||||
        binding.cropBorders.bindToPreference(preferences.cropBorders())
 | 
			
		||||
@@ -98,6 +99,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
 | 
			
		||||
        binding.pagerPrefsGroup.isInvisible = true
 | 
			
		||||
        binding.webtoonPrefsGroup.isVisible = true
 | 
			
		||||
 | 
			
		||||
        binding.webtoonNav.bindToPreference(preferences.navigationModeWebtoon())
 | 
			
		||||
        binding.cropBordersWebtoon.bindToPreference(preferences.cropBordersWebtoon())
 | 
			
		||||
        binding.webtoonSidePadding.bindToIntPreference(preferences.webtoonSidePadding(), R.array.webtoon_side_padding_values)
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,13 +28,18 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
 | 
			
		||||
    var volumeKeysInverted = false
 | 
			
		||||
    var trueColor = false
 | 
			
		||||
    var alwaysShowChapterTransition = true
 | 
			
		||||
    var navigationMode = 0
 | 
			
		||||
        protected set
 | 
			
		||||
 | 
			
		||||
    abstract var navigator: ViewerNavigation
 | 
			
		||||
        protected set
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        preferences.readWithTapping()
 | 
			
		||||
            .register({ tappingEnabled = it })
 | 
			
		||||
 | 
			
		||||
        preferences.readWithTappingInverted()
 | 
			
		||||
            .register({ tappingInverted = it })
 | 
			
		||||
            .register({ tappingInverted = it }, { navigator.invertMode = it })
 | 
			
		||||
 | 
			
		||||
        preferences.readWithLongTap()
 | 
			
		||||
            .register({ longTapEnabled = it })
 | 
			
		||||
@@ -58,6 +63,10 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
 | 
			
		||||
            .register({ alwaysShowChapterTransition = it })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract fun defaultNavigation(): ViewerNavigation
 | 
			
		||||
 | 
			
		||||
    abstract fun updateNavigation(navigationMode: Int)
 | 
			
		||||
 | 
			
		||||
    fun <T> Preference<T>.register(
 | 
			
		||||
        valueAssignment: (T) -> Unit,
 | 
			
		||||
        onChanged: (T) -> Unit = {}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,43 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer
 | 
			
		||||
 | 
			
		||||
import android.graphics.PointF
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.invert
 | 
			
		||||
 | 
			
		||||
abstract class ViewerNavigation {
 | 
			
		||||
 | 
			
		||||
    enum class NavigationRegion {
 | 
			
		||||
        NEXT, PREV, MENU
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    data class Region(
 | 
			
		||||
        val rectF: RectF,
 | 
			
		||||
        val type: NavigationRegion
 | 
			
		||||
    ) {
 | 
			
		||||
        fun invert(invertMode: PreferenceValues.TappingInvertMode): Region {
 | 
			
		||||
            if (invertMode == PreferenceValues.TappingInvertMode.NONE) return this
 | 
			
		||||
            return this.copy(
 | 
			
		||||
                rectF = this.rectF.invert(invertMode)
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private var constantMenuRegion: RectF = RectF(0f, 0f, 1f, 0.05f)
 | 
			
		||||
 | 
			
		||||
    abstract var regions: List<Region>
 | 
			
		||||
 | 
			
		||||
    var invertMode: PreferenceValues.TappingInvertMode = PreferenceValues.TappingInvertMode.NONE
 | 
			
		||||
 | 
			
		||||
    fun getAction(pos: PointF): NavigationRegion {
 | 
			
		||||
        val x = pos.x
 | 
			
		||||
        val y = pos.y
 | 
			
		||||
        val region = regions.map { it.invert(invertMode) }
 | 
			
		||||
            .find { it.rectF.contains(x, y) }
 | 
			
		||||
        return when {
 | 
			
		||||
            region != null -> region.type
 | 
			
		||||
            constantMenuRegion.contains(x, y) -> NavigationRegion.MENU
 | 
			
		||||
            else -> NavigationRegion.MENU
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.navigation
 | 
			
		||||
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Visualization of default state without any inversion
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | N | N |   P: Previous
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | M | N |   M: Menu
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | P | N |   N: Next
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
*/
 | 
			
		||||
class EdgeNavigation : ViewerNavigation() {
 | 
			
		||||
 | 
			
		||||
    override var regions: List<Region> = listOf(
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0f, 0.33f, 1f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0.33f, 0.66f, 0.66f, 1f),
 | 
			
		||||
            type = NavigationRegion.PREV
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0.66f, 0f, 1f, 1f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.navigation
 | 
			
		||||
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Visualization of default state without any inversion
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | M | M | M |   P: Previous
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | P | N | N |   M: Menu
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | P | N | N |   N: Next
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
*/
 | 
			
		||||
class KindlishNavigation : ViewerNavigation() {
 | 
			
		||||
 | 
			
		||||
    override var regions: List<Region> = listOf(
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0.33f, 0.33f, 1f, 1f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0.33f, 0.33f, 1f),
 | 
			
		||||
            type = NavigationRegion.PREV
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,36 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.navigation
 | 
			
		||||
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Visualization of default state without any inversion
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | N | N |   P: Previous
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | M | P |   M: Menu
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | P | P | P |   N: Next
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 */
 | 
			
		||||
open class LNavigation : ViewerNavigation() {
 | 
			
		||||
 | 
			
		||||
    override var regions: List<Region> = listOf(
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0.33f, 0.33f, 0.66f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0f, 1f, 0.33f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0.66f, 0.33f, 1f, 0.66f),
 | 
			
		||||
            type = NavigationRegion.PREV
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0.66f, 1f, 1f),
 | 
			
		||||
            type = NavigationRegion.PREV
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@@ -2,6 +2,10 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
@@ -29,6 +33,9 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
 | 
			
		||||
 | 
			
		||||
        preferences.cropBorders()
 | 
			
		||||
            .register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() })
 | 
			
		||||
 | 
			
		||||
        preferences.navigationModePager()
 | 
			
		||||
            .register({ navigationMode = it }, { updateNavigation(navigationMode) })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun zoomTypeFromPreference(value: Int) {
 | 
			
		||||
@@ -48,6 +55,28 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override var navigator: ViewerNavigation = defaultNavigation()
 | 
			
		||||
        set(value) {
 | 
			
		||||
            field = value.also { it.invertMode = this.tappingInverted }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun defaultNavigation(): ViewerNavigation {
 | 
			
		||||
        return when (viewer) {
 | 
			
		||||
            is VerticalPagerViewer -> VerticalPagerDefaultNavigation()
 | 
			
		||||
            else -> PagerDefaultNavigation()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun updateNavigation(navigationMode: Int) {
 | 
			
		||||
        navigator = when (navigationMode) {
 | 
			
		||||
            0 -> defaultNavigation()
 | 
			
		||||
            1 -> LNavigation()
 | 
			
		||||
            2 -> KindlishNavigation()
 | 
			
		||||
            3 -> EdgeNavigation()
 | 
			
		||||
            else -> defaultNavigation()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enum class ZoomType {
 | 
			
		||||
        Left, Center, Right
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.pager
 | 
			
		||||
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Visualization of default state without any inversion
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | M | P |   P: Previous
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | M | P |   M: Menu
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 * | N | M | P |   N: Next
 | 
			
		||||
 * +---+---+---+
 | 
			
		||||
 */
 | 
			
		||||
class PagerDefaultNavigation : ViewerNavigation() {
 | 
			
		||||
 | 
			
		||||
    override var regions: List<Region> = listOf(
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0f, 0f, 0.33f, 1f),
 | 
			
		||||
            type = NavigationRegion.NEXT
 | 
			
		||||
        ),
 | 
			
		||||
        Region(
 | 
			
		||||
            rectF = RectF(0.66f, 0f, 1f, 1f),
 | 
			
		||||
            type = NavigationRegion.PREV
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class VerticalPagerDefaultNavigation : LNavigation()
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.pager
 | 
			
		||||
 | 
			
		||||
import android.graphics.PointF
 | 
			
		||||
import android.view.InputDevice
 | 
			
		||||
import android.view.KeyEvent
 | 
			
		||||
import android.view.MotionEvent
 | 
			
		||||
@@ -9,12 +10,12 @@ import androidx.core.view.isGone
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import androidx.viewpager.widget.ViewPager
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import kotlin.math.min
 | 
			
		||||
 | 
			
		||||
@@ -89,34 +90,12 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
 | 
			
		||||
                return@f
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val positionX = event.x
 | 
			
		||||
            val positionY = event.y
 | 
			
		||||
            val topSideTap = positionY < pager.height * 0.25f
 | 
			
		||||
            val bottomSideTap = positionY > pager.height * 0.75f
 | 
			
		||||
            val leftSideTap = positionX < pager.width * 0.33f
 | 
			
		||||
            val rightSideTap = positionX > pager.width * 0.66f
 | 
			
		||||
 | 
			
		||||
            val invertMode = config.tappingInverted
 | 
			
		||||
            val invertVertical = invertMode == TappingInvertMode.VERTICAL || invertMode == TappingInvertMode.BOTH
 | 
			
		||||
            val invertHorizontal = invertMode == TappingInvertMode.HORIZONTAL || invertMode == TappingInvertMode.BOTH
 | 
			
		||||
 | 
			
		||||
            if (this is VerticalPagerViewer) {
 | 
			
		||||
                when {
 | 
			
		||||
                    topSideTap && !invertVertical || bottomSideTap && invertVertical -> moveLeft()
 | 
			
		||||
                    bottomSideTap && !invertVertical || topSideTap && invertVertical -> moveRight()
 | 
			
		||||
 | 
			
		||||
                    leftSideTap && !invertHorizontal || rightSideTap && invertHorizontal -> moveLeft()
 | 
			
		||||
                    rightSideTap && !invertHorizontal || leftSideTap && invertHorizontal -> moveRight()
 | 
			
		||||
 | 
			
		||||
                    else -> activity.toggleMenu()
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                when {
 | 
			
		||||
                    leftSideTap && !invertHorizontal || rightSideTap && invertHorizontal -> moveLeft()
 | 
			
		||||
                    rightSideTap && !invertHorizontal || leftSideTap && invertHorizontal -> moveRight()
 | 
			
		||||
 | 
			
		||||
                    else -> activity.toggleMenu()
 | 
			
		||||
                }
 | 
			
		||||
            val pos = PointF(event.rawX / pager.width, event.rawY / pager.height)
 | 
			
		||||
            val navigator = config.navigator
 | 
			
		||||
            when (navigator.getAction(pos)) {
 | 
			
		||||
                ViewerNavigation.NavigationRegion.MENU -> activity.toggleMenu()
 | 
			
		||||
                ViewerNavigation.NavigationRegion.NEXT -> moveToNext()
 | 
			
		||||
                ViewerNavigation.NavigationRegion.PREV -> moveToPrevious()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        pager.longTapListener = f@{
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,10 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.EdgeNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.KindlishNavigation
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
@@ -22,5 +26,27 @@ class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfi
 | 
			
		||||
 | 
			
		||||
        preferences.webtoonSidePadding()
 | 
			
		||||
            .register({ sidePadding = it }, { imagePropertyChangedListener?.invoke() })
 | 
			
		||||
 | 
			
		||||
        preferences.navigationModeWebtoon()
 | 
			
		||||
            .register({ navigationMode = it }, { updateNavigation(it) })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override var navigator: ViewerNavigation = defaultNavigation()
 | 
			
		||||
        set(value) {
 | 
			
		||||
            field = value.also { it.invertMode = tappingInverted }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    override fun defaultNavigation(): ViewerNavigation {
 | 
			
		||||
        return WebtoonDefaultNavigation()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun updateNavigation(navigationMode: Int) {
 | 
			
		||||
        this.navigator = when (navigationMode) {
 | 
			
		||||
            0 -> defaultNavigation()
 | 
			
		||||
            1 -> LNavigation()
 | 
			
		||||
            2 -> KindlishNavigation()
 | 
			
		||||
            3 -> EdgeNavigation()
 | 
			
		||||
            else -> defaultNavigation()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.navigation.LNavigation
 | 
			
		||||
 | 
			
		||||
class WebtoonDefaultNavigation : LNavigation()
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon
 | 
			
		||||
 | 
			
		||||
import android.graphics.PointF
 | 
			
		||||
import android.view.KeyEvent
 | 
			
		||||
import android.view.MotionEvent
 | 
			
		||||
import android.view.View
 | 
			
		||||
@@ -9,12 +10,12 @@ import androidx.core.view.isGone
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import androidx.recyclerview.widget.WebtoonLayoutManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
 | 
			
		||||
import rx.subscriptions.CompositeSubscription
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import kotlin.math.max
 | 
			
		||||
@@ -101,25 +102,15 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
 | 
			
		||||
                return@f
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val positionX = event.rawX
 | 
			
		||||
            val positionY = event.rawY
 | 
			
		||||
            val topSideTap = positionY < recycler.height * 0.25f
 | 
			
		||||
            val bottomSideTap = positionY > recycler.height * 0.75f
 | 
			
		||||
            val leftSideTap = positionX < recycler.width * 0.33f
 | 
			
		||||
            val rightSideTap = positionX > recycler.width * 0.66f
 | 
			
		||||
 | 
			
		||||
            val invertMode = config.tappingInverted
 | 
			
		||||
            val invertVertical = invertMode == TappingInvertMode.VERTICAL || invertMode == TappingInvertMode.BOTH
 | 
			
		||||
            val invertHorizontal = invertMode == TappingInvertMode.HORIZONTAL || invertMode == TappingInvertMode.BOTH
 | 
			
		||||
 | 
			
		||||
            when {
 | 
			
		||||
                topSideTap && !invertVertical || bottomSideTap && invertVertical -> scrollUp()
 | 
			
		||||
                bottomSideTap && !invertVertical || topSideTap && invertVertical -> scrollDown()
 | 
			
		||||
 | 
			
		||||
                leftSideTap && !invertHorizontal || rightSideTap && invertHorizontal -> scrollUp()
 | 
			
		||||
                rightSideTap && !invertHorizontal || leftSideTap && invertHorizontal -> scrollDown()
 | 
			
		||||
 | 
			
		||||
                else -> activity.toggleMenu()
 | 
			
		||||
            val pos = PointF(event.rawX / recycler.width, event.rawY / recycler.height)
 | 
			
		||||
            if (!config.tappingEnabled) activity.toggleMenu()
 | 
			
		||||
            else {
 | 
			
		||||
                val navigator = config.navigator
 | 
			
		||||
                when (navigator.getAction(pos)) {
 | 
			
		||||
                    ViewerNavigation.NavigationRegion.MENU -> activity.toggleMenu()
 | 
			
		||||
                    ViewerNavigation.NavigationRegion.NEXT -> scrollDown()
 | 
			
		||||
                    ViewerNavigation.NavigationRegion.PREV -> scrollUp()
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        recycler.longTapListener = f@{ event ->
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,15 @@
 | 
			
		||||
package eu.kanade.tachiyomi.util.lang
 | 
			
		||||
 | 
			
		||||
import android.graphics.RectF
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
 | 
			
		||||
 | 
			
		||||
fun RectF.invert(invertMode: PreferenceValues.TappingInvertMode): RectF {
 | 
			
		||||
    val horizontal = invertMode.shouldInvertHorizontal
 | 
			
		||||
    val vertical = invertMode.shouldInvertVertical
 | 
			
		||||
    return when {
 | 
			
		||||
        horizontal && vertical -> RectF(1f - this.right, 1f - this.bottom, 1f - this.left, 1f - this.top)
 | 
			
		||||
        vertical -> RectF(this.left, 1f - this.bottom, this.right, 1f - this.top)
 | 
			
		||||
        horizontal -> RectF(1f - this.right, this.top, 1f - this.left, this.bottom)
 | 
			
		||||
        else -> this
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -203,6 +203,25 @@
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/end_navigation_preferences" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/pager_nav_text"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="@string/pref_viewer_nav"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toStartOf="@id/verticalcenter"
 | 
			
		||||
        app:layout_constraintBaseline_toBaselineOf="@id/pager_nav"/>
 | 
			
		||||
 | 
			
		||||
    <androidx.appcompat.widget.AppCompatSpinner
 | 
			
		||||
        android:id="@+id/pager_nav"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:entries="@array/pager_nav"
 | 
			
		||||
        android:layout_marginTop="16dp"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/pager_prefs"
 | 
			
		||||
        app:layout_constraintStart_toEndOf="@id/verticalcenter"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="@id/spinner_end" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/scale_type_text"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
@@ -220,7 +239,7 @@
 | 
			
		||||
        android:entries="@array/image_scale_type"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="@id/spinner_end"
 | 
			
		||||
        app:layout_constraintStart_toEndOf="@id/verticalcenter"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/pager_prefs" />
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@+id/pager_nav" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/zoom_start_text"
 | 
			
		||||
@@ -326,6 +345,26 @@
 | 
			
		||||
        app:layout_constraintRight_toRightOf="@id/spinner_end"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/webtoon_prefs" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:id="@+id/webtoon_nav_text"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:text="@string/pref_viewer_nav"
 | 
			
		||||
        app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
        app:layout_constraintEnd_toStartOf="@id/verticalcenter"
 | 
			
		||||
        app:layout_constraintBaseline_toBaselineOf="@id/webtoon_nav"/>
 | 
			
		||||
 | 
			
		||||
    <androidx.appcompat.widget.AppCompatSpinner
 | 
			
		||||
        android:id="@+id/webtoon_nav"
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_marginTop="20dp"
 | 
			
		||||
        android:entries="@array/webtoon_nav"
 | 
			
		||||
        app:layout_constraintEnd_toEndOf="@id/spinner_end"
 | 
			
		||||
        app:layout_constraintHorizontal_bias="0.0"
 | 
			
		||||
        app:layout_constraintStart_toEndOf="@id/verticalcenter"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@+id/webtoon_side_padding" />
 | 
			
		||||
 | 
			
		||||
    <com.google.android.material.switchmaterial.SwitchMaterial
 | 
			
		||||
        android:id="@+id/crop_borders_webtoon"
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
@@ -333,7 +372,7 @@
 | 
			
		||||
        android:layout_marginTop="10dp"
 | 
			
		||||
        android:text="@string/pref_crop_borders"
 | 
			
		||||
        android:textColor="?android:attr/textColorSecondary"
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@id/webtoon_side_padding" />
 | 
			
		||||
        app:layout_constraintTop_toBottomOf="@+id/webtoon_nav" />
 | 
			
		||||
 | 
			
		||||
    <!-- Groups of preferences -->
 | 
			
		||||
 | 
			
		||||
@@ -342,7 +381,7 @@
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:constraint_referenced_ids="pager_prefs,scale_type_text,scale_type,zoom_start_text,zoom_start,crop_borders"
 | 
			
		||||
        app:constraint_referenced_ids="pager_prefs,pager_nav_text,pager_nav,scale_type_text,scale_type,zoom_start_text,zoom_start,crop_borders"
 | 
			
		||||
        tools:visibility="visible" />
 | 
			
		||||
 | 
			
		||||
    <androidx.constraintlayout.widget.Group
 | 
			
		||||
@@ -350,7 +389,7 @@
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:visibility="gone"
 | 
			
		||||
        app:constraint_referenced_ids="webtoon_prefs,crop_borders_webtoon,webtoon_side_padding_text,webtoon_side_padding" />
 | 
			
		||||
        app:constraint_referenced_ids="webtoon_prefs,webtoon_nav_text,webtoon_nav,crop_borders_webtoon,webtoon_side_padding_text,webtoon_side_padding" />
 | 
			
		||||
 | 
			
		||||
    <androidx.constraintlayout.widget.Guideline
 | 
			
		||||
        android:id="@+id/verticalcenter"
 | 
			
		||||
 
 | 
			
		||||
@@ -91,4 +91,18 @@
 | 
			
		||||
        <item>@string/manga_from_library</item>
 | 
			
		||||
        <item>@string/downloaded_chapters</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
    <string-array name="pager_nav">
 | 
			
		||||
        <item>@string/default_nav</item>
 | 
			
		||||
        <item>@string/l_nav</item>
 | 
			
		||||
        <item>@string/kindlish_nav</item>
 | 
			
		||||
        <item>@string/edge_nav</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
    <string-array name="webtoon_nav">
 | 
			
		||||
        <item>@string/default_nav</item>
 | 
			
		||||
        <item>@string/l_nav</item>
 | 
			
		||||
        <item>@string/kindlish_nav</item>
 | 
			
		||||
        <item>@string/edge_nav</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -277,12 +277,17 @@
 | 
			
		||||
    <string name="black_background">Black</string>
 | 
			
		||||
    <string name="pref_viewer_type">Default reading mode</string>
 | 
			
		||||
    <string name="default_viewer">Default</string>
 | 
			
		||||
    <string name="default_nav">Default</string>
 | 
			
		||||
    <string name="l_nav">L shaped</string>
 | 
			
		||||
    <string name="kindlish_nav">Kindle-ish</string>
 | 
			
		||||
    <string name="edge_nav">Edge</string>
 | 
			
		||||
    <string name="left_to_right_viewer">Left to right</string>
 | 
			
		||||
    <string name="right_to_left_viewer">Right to left</string>
 | 
			
		||||
    <string name="vertical_viewer">Vertical</string>
 | 
			
		||||
    <string name="webtoon_viewer">Webtoon</string>
 | 
			
		||||
    <string name="vertical_plus_viewer">Continuous vertical</string>
 | 
			
		||||
    <string name="pager_viewer">Paged</string>
 | 
			
		||||
    <string name="pref_viewer_nav">Navigation layout</string>
 | 
			
		||||
    <string name="pref_image_decoder">Image decoder</string>
 | 
			
		||||
    <string name="pref_image_scale_type">Scale type</string>
 | 
			
		||||
    <string name="scale_type_fit_screen">Fit screen</string>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user