Selaa lähdekoodia

Add option to reverse tapping (#3360)

* Add option to reverse tapping

* Fix string for preference key

* Invert tapping for Webtoon and Vertical

* Use enum instead of boolean

* Add option to reader sheet

* Hide from reader sheet if tapping disabled and remove hard coded string

* Hide option if tapping disabled
arkon 4 vuotta sitten
vanhempi
commit
04d83e9a6a

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -55,6 +55,8 @@ object PreferenceKeys {
 
     const val readWithTapping = "reader_tap"
 
+    const val readWithTappingInverted = "reader_tapping_inverted"
+
     const val readWithLongTap = "reader_long_tap"
 
     const val readWithVolumeKeys = "reader_volume_keys"

+ 7 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt

@@ -30,4 +30,11 @@ object PreferenceValues {
         COMFORTABLE_GRID,
         LIST,
     }
+
+    enum class TappingInvertMode {
+        NONE,
+        HORIZONTAL,
+        VERTICAL,
+        BOTH
+    }
 }

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -121,6 +121,8 @@ class PreferencesHelper(val context: Context) {
 
     fun readWithTapping() = flowPrefs.getBoolean(Keys.readWithTapping, true)
 
+    fun readWithTappingInverted() = flowPrefs.getEnum(Keys.readWithTappingInverted, Values.TappingInvertMode.NONE)
+
     fun readWithLongTap() = flowPrefs.getBoolean(Keys.readWithLongTap, true)
 
     fun readWithVolumeKeys() = flowPrefs.getBoolean(Keys.readWithVolumeKeys, false)

+ 28 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt

@@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
 import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
+import eu.kanade.tachiyomi.util.view.gone
 import eu.kanade.tachiyomi.util.view.invisible
 import eu.kanade.tachiyomi.util.view.visible
 import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
@@ -23,11 +24,13 @@ import kotlinx.android.synthetic.main.reader_settings_sheet.cutout_short
 import kotlinx.android.synthetic.main.reader_settings_sheet.fullscreen
 import kotlinx.android.synthetic.main.reader_settings_sheet.keepscreen
 import kotlinx.android.synthetic.main.reader_settings_sheet.long_tap
+import kotlinx.android.synthetic.main.reader_settings_sheet.navigation_prefs_group
 import kotlinx.android.synthetic.main.reader_settings_sheet.page_transitions
 import kotlinx.android.synthetic.main.reader_settings_sheet.pager_prefs_group
 import kotlinx.android.synthetic.main.reader_settings_sheet.rotation_mode
 import kotlinx.android.synthetic.main.reader_settings_sheet.scale_type
 import kotlinx.android.synthetic.main.reader_settings_sheet.show_page_number
+import kotlinx.android.synthetic.main.reader_settings_sheet.tapping_inverted
 import kotlinx.android.synthetic.main.reader_settings_sheet.true_color
 import kotlinx.android.synthetic.main.reader_settings_sheet.viewer
 import kotlinx.android.synthetic.main.reader_settings_sheet.webtoon_prefs_group
@@ -57,6 +60,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
         super.onCreate(savedInstanceState)
 
         initGeneralPreferences()
+        initNavigationPreferences()
 
         when (activity.viewer) {
             is PagerViewer -> initPagerPreferences()
@@ -119,6 +123,17 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
         webtoon_side_padding.bindToIntPreference(preferences.webtoonSidePadding(), R.array.webtoon_side_padding_values)
     }
 
+    /**
+     * Init the preferences for navigation.
+     */
+    private fun initNavigationPreferences() {
+        if (!preferences.readWithTapping().get()) {
+            navigation_prefs_group.gone()
+        }
+
+        tapping_inverted.bindToPreference(preferences.readWithTappingInverted())
+    }
+
     /**
      * Binds a checkbox or switch view with a boolean preference.
      */
@@ -137,6 +152,19 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : BottomSheetDia
         setSelection(pref.get() - offset, false)
     }
 
+    /**
+     * Binds a spinner to an enum preference.
+     */
+    private inline fun <reified T : Enum<T>> Spinner.bindToPreference(pref: Preference<T>) {
+        val enumConstants = T::class.java.enumConstants
+
+        onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
+            enumConstants?.get(position)?.let { pref.set(it) }
+        }
+
+        enumConstants?.indexOf(pref.get())?.let { setSelection(it, false) }
+    }
+
     /**
      * Binds a spinner to an int preference. The position of the spinner item must
      * correlate with the [intValues] resource item (in arrays.xml), which is a <string-array>

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt

@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.ui.reader.viewer
 
 import com.tfcporciuncula.flow.Preference
+import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -20,6 +21,7 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
 
     var tappingEnabled = true
     var longTapEnabled = true
+    var tappingInverted = TappingInvertMode.NONE
     var doubleTapAnimDuration = 500
     var volumeKeysEnabled = false
     var volumeKeysInverted = false
@@ -30,6 +32,9 @@ abstract class ViewerConfig(preferences: PreferencesHelper) {
         preferences.readWithTapping()
             .register({ tappingEnabled = it })
 
+        preferences.readWithTappingInverted()
+            .register({ tappingInverted = it })
+
         preferences.readWithLongTap()
             .register({ longTapEnabled = it })
 

+ 15 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt

@@ -7,6 +7,7 @@ import android.view.View
 import android.view.ViewGroup.LayoutParams
 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
@@ -80,18 +81,28 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
             }
         })
         pager.tapListener = { event ->
+            val invertMode = config.tappingInverted
+
             if (this is VerticalPagerViewer) {
                 val positionY = event.y
+                val tappingInverted = invertMode == TappingInvertMode.VERTICAL || invertMode == TappingInvertMode.BOTH
+                val topSideTap = positionY < pager.height * 0.33f && config.tappingEnabled
+                val bottomSideTap = positionY > pager.height * 0.66f && config.tappingEnabled
+
                 when {
-                    positionY < pager.height * 0.33f && config.tappingEnabled -> moveLeft()
-                    positionY > pager.height * 0.66f && config.tappingEnabled -> moveRight()
+                    topSideTap && !tappingInverted || bottomSideTap && tappingInverted -> moveLeft()
+                    bottomSideTap && !tappingInverted || topSideTap && tappingInverted -> moveRight()
                     else -> activity.toggleMenu()
                 }
             } else {
                 val positionX = event.x
+                val tappingInverted = invertMode == TappingInvertMode.HORIZONTAL || invertMode == TappingInvertMode.BOTH
+                val leftSideTap = positionX < pager.width * 0.33f && config.tappingEnabled
+                val rightSideTap = positionX > pager.width * 0.66f && config.tappingEnabled
+
                 when {
-                    positionX < pager.width * 0.33f && config.tappingEnabled -> moveLeft()
-                    positionX > pager.width * 0.66f && config.tappingEnabled -> moveRight()
+                    leftSideTap && !tappingInverted || rightSideTap && tappingInverted -> moveLeft()
+                    rightSideTap && !tappingInverted || leftSideTap && tappingInverted -> moveRight()
                     else -> activity.toggleMenu()
                 }
             }

+ 9 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt

@@ -7,6 +7,7 @@ import android.view.ViewGroup
 import android.view.ViewGroup.LayoutParams.MATCH_PARENT
 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
@@ -94,9 +95,15 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
         })
         recycler.tapListener = { event ->
             val positionY = event.rawY
+            val invertMode = config.tappingInverted
+            val topSideTap = positionY < recycler.height * 0.33f && config.tappingEnabled
+            val bottomSideTap = positionY > recycler.height * 0.66f && config.tappingEnabled
+
+            val tappingInverted = invertMode == TappingInvertMode.VERTICAL || invertMode == TappingInvertMode.BOTH
+
             when {
-                positionY < recycler.height * 0.33f && config.tappingEnabled -> scrollUp()
-                positionY > recycler.height * 0.66f && config.tappingEnabled -> scrollDown()
+                topSideTap && !tappingInverted || bottomSideTap && tappingInverted -> scrollUp()
+                bottomSideTap && !tappingInverted || topSideTap && tappingInverted -> scrollDown()
                 else -> activity.toggleMenu()
             }
         }

+ 24 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt

@@ -4,14 +4,18 @@ import android.os.Build
 import androidx.preference.PreferenceScreen
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
+import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode
+import eu.kanade.tachiyomi.data.preference.asImmediateFlow
 import eu.kanade.tachiyomi.util.preference.defaultValue
 import eu.kanade.tachiyomi.util.preference.entriesRes
 import eu.kanade.tachiyomi.util.preference.intListPreference
+import eu.kanade.tachiyomi.util.preference.listPreference
 import eu.kanade.tachiyomi.util.preference.preferenceCategory
 import eu.kanade.tachiyomi.util.preference.summaryRes
 import eu.kanade.tachiyomi.util.preference.switchPreference
 import eu.kanade.tachiyomi.util.preference.titleRes
 import eu.kanade.tachiyomi.util.system.hasDisplayCutout
+import kotlinx.coroutines.flow.launchIn
 
 class SettingsReaderController : SettingsController() {
 
@@ -190,6 +194,26 @@ class SettingsReaderController : SettingsController() {
                 titleRes = R.string.pref_read_with_tapping
                 defaultValue = true
             }
+            listPreference {
+                key = Keys.readWithTappingInverted
+                titleRes = R.string.pref_read_with_tapping_inverted
+                entriesRes = arrayOf(
+                    R.string.tapping_inverted_none,
+                    R.string.tapping_inverted_horizontal,
+                    R.string.tapping_inverted_vertical,
+                    R.string.tapping_inverted_both
+                )
+                entryValues = arrayOf(
+                    TappingInvertMode.NONE.name,
+                    TappingInvertMode.HORIZONTAL.name,
+                    TappingInvertMode.VERTICAL.name,
+                    TappingInvertMode.BOTH.name
+                )
+                defaultValue = TappingInvertMode.NONE.name
+                summary = "%s"
+
+                preferences.readWithTapping().asImmediateFlow { isVisible = it }.launchIn(scope)
+            }
             switchPreference {
                 key = Keys.readWithLongTap
                 titleRes = R.string.pref_read_with_long_tap

+ 53 - 2
app/src/main/res/layout/reader_settings_sheet.xml

@@ -188,7 +188,7 @@
         android:textColor="?attr/colorAccent"
         android:textStyle="bold"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/end_general_preferences" />
+        app:layout_constraintTop_toBottomOf="@id/end_navigation_preferences" />
 
     <TextView
         android:id="@+id/scale_type_text"
@@ -245,6 +245,50 @@
         android:textColor="?android:attr/textColorSecondary"
         app:layout_constraintTop_toBottomOf="@id/crop_borders" />
 
+    <android.widget.Space
+        android:id="@+id/end_paged_preferences"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="@+id/page_transitions"
+        tools:layout_editor_absoluteX="24dp" />
+
+    <TextView
+        android:id="@+id/navigation_prefs"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="24dp"
+        android:text="@string/pref_reader_navigation"
+        android:textColor="?attr/colorAccent"
+        android:textStyle="bold"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/end_general_preferences" />
+
+    <TextView
+        android:id="@+id/tapping_inverted_text"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/pref_read_with_tapping_inverted"
+        app:layout_constraintBaseline_toBaselineOf="@id/tapping_inverted"
+        app:layout_constraintEnd_toStartOf="@id/verticalcenter"
+        app:layout_constraintStart_toStartOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatSpinner
+        android:id="@+id/tapping_inverted"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dp"
+        android:entries="@array/invert_tapping_mode"
+        app:layout_constraintEnd_toEndOf="@id/spinner_end"
+        app:layout_constraintStart_toEndOf="@id/verticalcenter"
+        app:layout_constraintTop_toBottomOf="@+id/navigation_prefs" />
+
+    <android.widget.Space
+        android:id="@+id/end_navigation_preferences"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="@+id/tapping_inverted"
+        tools:layout_editor_absoluteX="24dp" />
+
     <!-- Webtoon preferences -->
 
     <TextView
@@ -256,7 +300,7 @@
         android:textColor="?attr/colorAccent"
         android:textStyle="bold"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/end_general_preferences" />
+        app:layout_constraintTop_toBottomOf="@id/end_navigation_preferences" />
 
     <com.google.android.material.switchmaterial.SwitchMaterial
         android:id="@+id/crop_borders_webtoon"
@@ -310,4 +354,11 @@
         android:orientation="vertical"
         app:layout_constraintGuide_percent="0.5" />
 
+    <androidx.constraintlayout.widget.Group
+        android:id="@+id/navigation_prefs_group"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:constraint_referenced_ids="navigation_prefs,tapping_inverted_text,end_navigation_preferences,tapping_inverted"
+        tools:layout_editor_absoluteX="24dp" />
+
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 7 - 0
app/src/main/res/values/arrays.xml

@@ -79,4 +79,11 @@
         <item>@string/filter_mode_multiply</item>
         <item>@string/filter_mode_screen</item>
     </string-array>
+
+    <string-array name="invert_tapping_mode">
+        <item>@string/tapping_inverted_none</item>
+        <item>@string/tapping_inverted_horizontal</item>
+        <item>@string/tapping_inverted_vertical</item>
+        <item>@string/tapping_inverted_both</item>
+    </string-array>
 </resources>

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -668,5 +668,10 @@
     <string name="channel_backup_restore">Backup and restore</string>
     <string name="channel_backup_restore_progress">Progress</string>
     <string name="channel_backup_restore_complete">Complete</string>
+    <string name="pref_read_with_tapping_inverted">Invert tapping</string>
+    <string name="tapping_inverted_none">None</string>
+    <string name="tapping_inverted_horizontal">Horizontal</string>
+    <string name="tapping_inverted_vertical">Vertical</string>
+    <string name="tapping_inverted_both">Both</string>
 
 </resources>