diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 7dc07c3cc..1d85d4f6d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -138,6 +138,13 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { get() = prefs.getBoolean(KEY_READER_DOUBLE_PAGES, false) set(value) = prefs.edit { putBoolean(KEY_READER_DOUBLE_PAGES, value) } + val readerDoublePagesSensitivity: Float + get() = prefs.getFloat(KEY_READER_DOUBLE_PAGES_SENSITIVITY, 12f) / 10f + + fun setReaderDoublePagesSensitivity(value: Float) { + prefs.edit { putFloat(KEY_READER_DOUBLE_PAGES_SENSITIVITY, value) } + } + val readerScreenOrientation: Int get() = prefs.getString(KEY_READER_ORIENTATION, null)?.toIntOrNull() ?: ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED @@ -673,6 +680,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_REMOTE_SOURCES = "remote_sources" const val KEY_LOCAL_STORAGE = "local_storage" const val KEY_READER_DOUBLE_PAGES = "reader_double_pages" + const val KEY_READER_DOUBLE_PAGES_SENSITIVITY = "reader_double_pages_sensitivity" const val KEY_READER_ZOOM_BUTTONS = "reader_zoom_buttons" const val KEY_READER_CONTROL_LTR = "reader_taps_ltr" const val KEY_READER_NAVIGATION_INVERTED = "reader_navigation_inverted" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt index 577e9a9c7..60d89885f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/config/ReaderConfigSheet.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.CompoundButton +import android.widget.SeekBar import androidx.core.view.WindowInsetsCompat import androidx.core.view.isGone import androidx.core.view.isVisible @@ -89,6 +90,10 @@ class ReaderConfigSheet : binding.switchPullGesture.isChecked = settings.isWebtoonPullGestureEnabled binding.switchPullGesture.isEnabled = mode == ReaderMode.WEBTOON + binding.textSensitivity.isVisible = settings.isReaderDoubleOnLandscape + binding.seekbarSensitivity.isVisible = settings.isReaderDoubleOnLandscape + binding.seekbarSensitivity.progress = (settings.readerDoublePagesSensitivity * 100).toInt() + binding.checkableGroup.addOnButtonCheckedListener(this) binding.buttonSavePage.setOnClickListener(this) binding.buttonScreenRotate.setOnClickListener(this) @@ -100,6 +105,16 @@ class ReaderConfigSheet : binding.switchDoubleReader.setOnCheckedChangeListener(this) binding.switchPullGesture.setOnCheckedChangeListener(this) + binding.seekbarSensitivity.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { + settings.setReaderDoublePagesSensitivity(progress / 10f) + } + + override fun onStartTrackingTouch(seekBar: SeekBar?) {} + + override fun onStopTrackingTouch(seekBar: SeekBar?) {} + }) + viewModel.isBookmarkAdded.observe(viewLifecycleOwner) { binding.buttonBookmark.setText(if (it) R.string.bookmark_remove else R.string.bookmark_add) binding.buttonBookmark.setCompoundDrawablesRelativeWithIntrinsicBounds( @@ -173,6 +188,8 @@ class ReaderConfigSheet : R.id.switch_double_reader -> { settings.isReaderDoubleOnLandscape = isChecked + viewBinding?.textSensitivity?.isVisible = isChecked + viewBinding?.seekbarSensitivity?.isVisible = isChecked findParentCallback(Callback::class.java)?.onDoubleModeChanged(isChecked) } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoublePageSnapHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoublePageSnapHelper.kt index cf9b4106b..697ba5eef 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoublePageSnapHelper.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoublePageSnapHelper.kt @@ -11,11 +11,14 @@ import androidx.recyclerview.widget.OrientationHelper import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.SmoothScroller.ScrollVectorProvider import androidx.recyclerview.widget.SnapHelper +import org.koitharu.kotatsu.core.prefs.AppSettings import kotlin.math.abs +import kotlin.math.absoluteValue import kotlin.math.max import kotlin.math.roundToInt +import kotlin.math.sign -class DoublePageSnapHelper : SnapHelper() { +class DoublePageSnapHelper(private val settings: AppSettings) : SnapHelper() { private lateinit var recyclerView: RecyclerView @@ -248,28 +251,27 @@ class DoublePageSnapHelper : SnapHelper() { equal to zero. */ fun getPositionsToMove(llm: LinearLayoutManager, scroll: Int, itemSize: Int): Int { - var positionsToMove: Int - positionsToMove = roundUpToBlockSize(abs((scroll.toDouble()) / itemSize).roundToInt()) - if (positionsToMove < blockSize) { - // Must move at least one block - positionsToMove = blockSize - } else if (positionsToMove > maxPositionsToMove) { - // Clamp number of positions to move, so we don't get wild flinging. - positionsToMove = maxPositionsToMove + val sensitivity = settings.readerDoublePagesSensitivity + var positionsToMove = (scroll.toDouble() / (itemSize * (2.5 - sensitivity))).roundToInt() + + // Apply a maximum threshold + val maxPages = (4 * sensitivity).roundToInt().coerceAtLeast(1) + if (positionsToMove.absoluteValue > maxPages) { + positionsToMove = maxPages * positionsToMove.sign } - if (scroll < 0) { - positionsToMove *= -1 + + // Apply a minimum threshold + if (positionsToMove == 0 && scroll.absoluteValue > itemSize * 0.2) { + positionsToMove = 1 * scroll.sign } - if (isRTL) { - positionsToMove *= -1 - } - return if (layoutDirectionHelper.isDirectionToBottom(scroll < 0)) { - // Scrolling toward the bottom of data. - roundDownToBlockSize(llm.findFirstVisibleItemPosition()) + positionsToMove + + val currentPosition = if (layoutDirectionHelper.isDirectionToBottom(scroll < 0)) { + llm.findFirstVisibleItemPosition() } else { - roundDownToBlockSize(llm.findLastVisibleItemPosition()) + positionsToMove + llm.findLastVisibleItemPosition() } - // Scrolling toward the top of the data. + val targetPos = currentPosition + positionsToMove * 2 + return roundDownToBlockSize(targetPos) } fun isDirectionToBottom(velocityNegative: Boolean): Boolean { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoubleReaderFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoubleReaderFragment.kt index 035225161..71bf54c7d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoubleReaderFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/pager/doublepage/DoubleReaderFragment.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.yield import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.os.NetworkState +import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.ui.list.lifecycle.RecyclerViewLifecycleDispatcher import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition import org.koitharu.kotatsu.databinding.FragmentReaderDoubleBinding @@ -33,6 +34,9 @@ open class DoubleReaderFragment : BaseReaderFragment + + + + None Reset settings to default values? This action cannot be undone. Use two pages layout on landscape orientation (beta) + Two-Page Scroll Sensitivity Default webtoon zoom out Fullscreen mode Hide system status and navigation bars