Reader control direction depends on mode #214

pull/216/head
Koitharu 4 years ago
parent b4f93fc0a5
commit 040d3e4433
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -14,9 +14,6 @@ import java.io.File
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.channels.trySendBlocking
import kotlinx.coroutines.flow.callbackFlow
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.ZoomMode import org.koitharu.kotatsu.core.model.ZoomMode
import org.koitharu.kotatsu.core.network.DoHProvider import org.koitharu.kotatsu.core.network.DoHProvider
@ -64,6 +61,9 @@ class AppSettings(context: Context) {
val readerPageSwitch: Set<String> val readerPageSwitch: Set<String>
get() = prefs.getStringSet(KEY_READER_SWITCHERS, null) ?: setOf(PAGE_SWITCH_TAPS) get() = prefs.getStringSet(KEY_READER_SWITCHERS, null) ?: setOf(PAGE_SWITCH_TAPS)
val isReaderTapsAdaptive: Boolean
get() = !prefs.getBoolean(KEY_READER_TAPS_LTR, false)
var isTrafficWarningEnabled: Boolean var isTrafficWarningEnabled: Boolean
get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true) get() = prefs.getBoolean(KEY_TRAFFIC_WARNING, true)
set(value) = prefs.edit { putBoolean(KEY_TRAFFIC_WARNING, value) } set(value) = prefs.edit { putBoolean(KEY_TRAFFIC_WARNING, value) }
@ -314,6 +314,7 @@ class AppSettings(context: Context) {
const val KEY_DOWNLOADS_SLOWDOWN = "downloads_slowdown" const val KEY_DOWNLOADS_SLOWDOWN = "downloads_slowdown"
const val KEY_ALL_FAVOURITES_VISIBLE = "all_favourites_visible" const val KEY_ALL_FAVOURITES_VISIBLE = "all_favourites_visible"
const val KEY_DOH = "doh" const val KEY_DOH = "doh"
const val KEY_READER_TAPS_LTR = "reader_taps_ltr"
// About // About
const val KEY_APP_UPDATE = "app_update" const val KEY_APP_UPDATE = "app_update"

@ -4,6 +4,7 @@ import android.app.Activity
import android.app.Application import android.app.Application
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import org.acra.dialog.CrashReportDialog
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
class AppProtectHelper(private val settings: AppSettings) : Application.ActivityLifecycleCallbacks { class AppProtectHelper(private val settings: AppSettings) : Application.ActivityLifecycleCallbacks {
@ -11,7 +12,7 @@ class AppProtectHelper(private val settings: AppSettings) : Application.Activity
private var isUnlocked = settings.appPassword.isNullOrEmpty() private var isUnlocked = settings.appPassword.isNullOrEmpty()
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
if (activity !is ProtectActivity && !isUnlocked) { if (!isUnlocked && activity !is ProtectActivity && activity !is CrashReportDialog) {
val sourceIntent = Intent(activity, activity.javaClass) val sourceIntent = Intent(activity, activity.javaClass)
activity.intent?.let { activity.intent?.let {
sourceIntent.putExtras(it) sourceIntent.putExtras(it)

@ -19,6 +19,7 @@ import androidx.transition.TransitionManager
import androidx.transition.TransitionSet import androidx.transition.TransitionSet
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -47,7 +48,6 @@ import org.koitharu.kotatsu.utils.GridTouchHelper
import org.koitharu.kotatsu.utils.ScreenOrientationHelper import org.koitharu.kotatsu.utils.ScreenOrientationHelper
import org.koitharu.kotatsu.utils.ShareHelper import org.koitharu.kotatsu.utils.ShareHelper
import org.koitharu.kotatsu.utils.ext.* import org.koitharu.kotatsu.utils.ext.*
import java.util.concurrent.TimeUnit
class ReaderActivity : class ReaderActivity :
BaseFullscreenActivity<ActivityReaderBinding>(), BaseFullscreenActivity<ActivityReaderBinding>(),
@ -67,6 +67,9 @@ class ReaderActivity :
) )
} }
override val readerMode: ReaderMode?
get() = readerManager.currentMode
private lateinit var touchHelper: GridTouchHelper private lateinit var touchHelper: GridTouchHelper
private lateinit var orientationHelper: ScreenOrientationHelper private lateinit var orientationHelper: ScreenOrientationHelper
private lateinit var controlDelegate: ReaderControlDelegate private lateinit var controlDelegate: ReaderControlDelegate
@ -82,7 +85,7 @@ class ReaderActivity :
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
touchHelper = GridTouchHelper(this, this) touchHelper = GridTouchHelper(this, this)
orientationHelper = ScreenOrientationHelper(this) orientationHelper = ScreenOrientationHelper(this)
controlDelegate = ReaderControlDelegate(lifecycleScope, get(), this) controlDelegate = ReaderControlDelegate(get(), this, this)
binding.toolbarBottom.inflateMenu(R.menu.opt_reader_bottom) binding.toolbarBottom.inflateMenu(R.menu.opt_reader_bottom)
binding.toolbarBottom.setOnMenuItemClickListener(::onOptionsItemSelected) binding.toolbarBottom.setOnMenuItemClickListener(::onOptionsItemSelected)
insetsDelegate.interceptingWindowInsetsListener = this insetsDelegate.interceptingWindowInsetsListener = this
@ -146,7 +149,7 @@ class ReaderActivity :
ChaptersBottomSheet.show( ChaptersBottomSheet.show(
supportFragmentManager, supportFragmentManager,
viewModel.manga?.chapters.orEmpty(), viewModel.manga?.chapters.orEmpty(),
viewModel.getCurrentState()?.chapterId ?: 0L viewModel.getCurrentState()?.chapterId ?: 0L,
) )
} }
R.id.action_screen_rotate -> { R.id.action_screen_rotate -> {
@ -317,12 +320,12 @@ class ReaderActivity :
binding.appbarTop.updatePadding( binding.appbarTop.updatePadding(
top = systemBars.top, top = systemBars.top,
right = systemBars.right, right = systemBars.right,
left = systemBars.left left = systemBars.left,
) )
binding.appbarBottom?.updatePadding( binding.appbarBottom?.updatePadding(
bottom = systemBars.bottom, bottom = systemBars.bottom,
right = systemBars.right, right = systemBars.right,
left = systemBars.left left = systemBars.left,
) )
return WindowInsetsCompat.Builder(insets) return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE) .setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)

@ -1,33 +1,39 @@
package org.koitharu.kotatsu.reader.ui package org.koitharu.kotatsu.reader.ui
import android.content.SharedPreferences
import android.view.KeyEvent import android.view.KeyEvent
import android.view.SoundEffectConstants import android.view.SoundEffectConstants
import android.view.View import android.view.View
import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.DefaultLifecycleObserver
import kotlinx.coroutines.Dispatchers import androidx.lifecycle.LifecycleOwner
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.observeAsFlow import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.utils.GridTouchHelper import org.koitharu.kotatsu.utils.GridTouchHelper
class ReaderControlDelegate( class ReaderControlDelegate(
scope: LifecycleCoroutineScope, private val settings: AppSettings,
settings: AppSettings, private val listener: OnInteractionListener,
private val listener: OnInteractionListener owner: LifecycleOwner,
) { ) : DefaultLifecycleObserver, SharedPreferences.OnSharedPreferenceChangeListener {
private var isTapSwitchEnabled: Boolean = true private var isTapSwitchEnabled: Boolean = true
private var isVolumeKeysSwitchEnabled: Boolean = false private var isVolumeKeysSwitchEnabled: Boolean = false
private var isReaderTapsAdaptive: Boolean = true
init { init {
settings.observeAsFlow(AppSettings.KEY_READER_SWITCHERS) { readerPageSwitch } owner.lifecycle.addObserver(this)
.flowOn(Dispatchers.Default) settings.subscribe(this)
.onEach { updateSettings()
isTapSwitchEnabled = AppSettings.PAGE_SWITCH_TAPS in it }
isVolumeKeysSwitchEnabled = AppSettings.PAGE_SWITCH_VOLUME_KEYS in it
}.launchIn(scope) override fun onDestroy(owner: LifecycleOwner) {
settings.unsubscribe(this)
owner.lifecycle.removeObserver(this)
super.onDestroy(owner)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
updateSettings()
} }
fun onGridTouch(area: Int, view: View) { fun onGridTouch(area: Int, view: View) {
@ -41,7 +47,7 @@ class ReaderControlDelegate(
view.playSoundEffect(SoundEffectConstants.NAVIGATION_UP) view.playSoundEffect(SoundEffectConstants.NAVIGATION_UP)
} }
GridTouchHelper.AREA_LEFT -> if (isTapSwitchEnabled) { GridTouchHelper.AREA_LEFT -> if (isTapSwitchEnabled) {
listener.switchPageBy(-1) listener.switchPageBy(if (isReaderTapsReversed()) 1 else -1)
view.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT) view.playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT)
} }
GridTouchHelper.AREA_BOTTOM -> if (isTapSwitchEnabled) { GridTouchHelper.AREA_BOTTOM -> if (isTapSwitchEnabled) {
@ -49,7 +55,7 @@ class ReaderControlDelegate(
view.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN) view.playSoundEffect(SoundEffectConstants.NAVIGATION_DOWN)
} }
GridTouchHelper.AREA_RIGHT -> if (isTapSwitchEnabled) { GridTouchHelper.AREA_RIGHT -> if (isTapSwitchEnabled) {
listener.switchPageBy(1) listener.switchPageBy(if (isReaderTapsReversed()) -1 else 1)
view.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT) view.playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT)
} }
} }
@ -72,17 +78,25 @@ class ReaderControlDelegate(
KeyEvent.KEYCODE_PAGE_DOWN, KeyEvent.KEYCODE_PAGE_DOWN,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN,
KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_RIGHT -> { -> {
listener.switchPageBy(1) listener.switchPageBy(1)
true true
} }
KeyEvent.KEYCODE_DPAD_RIGHT -> {
listener.switchPageBy(if (isReaderTapsReversed()) -1 else 1)
true
}
KeyEvent.KEYCODE_PAGE_UP, KeyEvent.KEYCODE_PAGE_UP,
KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP, KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP,
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_LEFT -> { -> {
listener.switchPageBy(-1) listener.switchPageBy(-1)
true true
} }
KeyEvent.KEYCODE_DPAD_LEFT -> {
listener.switchPageBy(if (isReaderTapsReversed()) 1 else -1)
true
}
KeyEvent.KEYCODE_DPAD_CENTER -> { KeyEvent.KEYCODE_DPAD_CENTER -> {
listener.toggleUiVisibility() listener.toggleUiVisibility()
true true
@ -97,8 +111,21 @@ class ReaderControlDelegate(
) )
} }
private fun updateSettings() {
val switch = settings.readerPageSwitch
isTapSwitchEnabled = AppSettings.PAGE_SWITCH_TAPS in switch
isVolumeKeysSwitchEnabled = AppSettings.PAGE_SWITCH_VOLUME_KEYS in switch
isReaderTapsAdaptive = settings.isReaderTapsAdaptive
}
private fun isReaderTapsReversed(): Boolean {
return isReaderTapsAdaptive && listener.readerMode == ReaderMode.REVERSED
}
interface OnInteractionListener { interface OnInteractionListener {
val readerMode: ReaderMode?
fun switchPageBy(delta: Int) fun switchPageBy(delta: Int)
fun toggleUiVisibility() fun toggleUiVisibility()

@ -325,4 +325,6 @@
<string name="not_found_404">Content not found or removed</string> <string name="not_found_404">Content not found or removed</string>
<string name="downloading_manga">Downloading manga</string> <string name="downloading_manga">Downloading manga</string>
<string name="download_summary_pattern" translatable="false">&lt;b>%1$s&lt;/b> %2$s</string> <string name="download_summary_pattern" translatable="false">&lt;b>%1$s&lt;/b> %2$s</string>
<string name="reader_control_ltr_summary">Tap on the right edge or pressing the right key always switches to the next page</string>
<string name="reader_control_ltr">Ergonomic reader control</string>
</resources> </resources>

@ -29,6 +29,12 @@
android:title="@string/switch_pages" android:title="@string/switch_pages"
app:allowDividerAbove="true" /> app:allowDividerAbove="true" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="reader_taps_ltr"
android:summary="@string/reader_control_ltr_summary"
android:title="@string/reader_control_ltr" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="false"
android:key="reader_animation" android:key="reader_animation"

Loading…
Cancel
Save