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
This commit is contained in:
arkon 2020-06-25 18:12:12 -04:00 committed by GitHub
commit 04d83e9a6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 157 additions and 8 deletions

View File

@ -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"

View File

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

View File

@ -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)

View File

@ -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>

View File

@ -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 })

View File

@ -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()
}
}

View File

@ -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()
}
}

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>