fix: stabilize reader navigation and release 2.33
This commit is contained in:
@@ -11,8 +11,8 @@ android {
|
||||
applicationId = "com.aletheia.app"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 42
|
||||
versionName = "2.31"
|
||||
versionCode = 44
|
||||
versionName = "2.33"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".ui.reader.ReaderActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.Aletheia"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
this.preparedDocuments = new WeakSet();
|
||||
this.resizeTimer = null;
|
||||
this.resizeObserver = null;
|
||||
this.pendingResizeTarget = undefined;
|
||||
}
|
||||
|
||||
async load(arrayBuffer, payload) {
|
||||
@@ -139,7 +140,8 @@
|
||||
getPreferences: this.host.getPreferences,
|
||||
next: this.host.next,
|
||||
previous: this.host.previous,
|
||||
toggleControls: this.host.toggleControls
|
||||
toggleControls: this.host.toggleControls,
|
||||
nativeTapZones: true
|
||||
});
|
||||
if (!this.preparedDocuments.has(contents.document)) {
|
||||
this.preparedDocuments.add(contents.document);
|
||||
@@ -253,10 +255,14 @@
|
||||
if (!global.ResizeObserver || this.resizeObserver) return;
|
||||
const self = this;
|
||||
this.resizeObserver = new ResizeObserver(function () {
|
||||
if (self.pendingResizeTarget === undefined) {
|
||||
self.pendingResizeTarget = self.currentCfi || null;
|
||||
}
|
||||
clearTimeout(self.resizeTimer);
|
||||
self.resizeTimer = setTimeout(async function () {
|
||||
if (!self.rendition || self.destroyed) return;
|
||||
const target = self.currentCfi;
|
||||
const target = self.pendingResizeTarget;
|
||||
self.pendingResizeTarget = undefined;
|
||||
try {
|
||||
self.rendition.resize();
|
||||
if (target) await self.rendition.display(target);
|
||||
@@ -594,6 +600,7 @@
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
clearTimeout(this.resizeTimer);
|
||||
this.pendingResizeTarget = undefined;
|
||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
this.clearSearch(false);
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
this.searchMarks = [];
|
||||
this.resizeObserver = null;
|
||||
this.resizeTimer = null;
|
||||
this.pendingResizeLocator = undefined;
|
||||
this.scrollFrame = 0;
|
||||
this.selectionTimer = null;
|
||||
this.detachGestures = null;
|
||||
@@ -169,7 +170,8 @@
|
||||
getPreferences: this.host.getPreferences,
|
||||
next: this.host.next,
|
||||
previous: this.host.previous,
|
||||
toggleControls: this.host.toggleControls
|
||||
toggleControls: this.host.toggleControls,
|
||||
nativeTapZones: true
|
||||
});
|
||||
await Internal.waitForPreferredFont(document, this.host.getPreferences());
|
||||
await this._layout(false);
|
||||
@@ -487,9 +489,9 @@
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
async _layout(preserve) {
|
||||
async _layout(preserve, preservedLocator) {
|
||||
const preferences = this.host.getPreferences();
|
||||
const locator = preserve ? this.currentLocator() : null;
|
||||
const locator = preserve ? (preservedLocator || this.currentLocator()) : null;
|
||||
const progress = this.currentProgress;
|
||||
const width = Math.max(1, this.mount.clientWidth);
|
||||
const height = Math.max(1, this.mount.clientHeight);
|
||||
@@ -534,9 +536,14 @@
|
||||
if (!global.ResizeObserver || this.resizeObserver) return;
|
||||
const self = this;
|
||||
this.resizeObserver = new ResizeObserver(function () {
|
||||
if (self.pendingResizeLocator === undefined) {
|
||||
self.pendingResizeLocator = self.currentLocator();
|
||||
}
|
||||
clearTimeout(self.resizeTimer);
|
||||
self.resizeTimer = setTimeout(function () {
|
||||
if (!self.destroyed) self._layout(true).catch(function (error) {
|
||||
const locator = self.pendingResizeLocator;
|
||||
self.pendingResizeLocator = undefined;
|
||||
if (!self.destroyed) self._layout(true, locator).catch(function (error) {
|
||||
Internal.reportError(error, 'fb2.resize', true);
|
||||
});
|
||||
}, 120);
|
||||
@@ -1051,6 +1058,7 @@
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
clearTimeout(this.resizeTimer);
|
||||
this.pendingResizeLocator = undefined;
|
||||
clearTimeout(this.selectionTimer);
|
||||
if (this.scrollFrame) cancelAnimationFrame(this.scrollFrame);
|
||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
|
||||
const Internal = global.ReaderV2Internal = global.ReaderV2Internal || {};
|
||||
const attachedDocuments = new WeakMap();
|
||||
const LEFT_ZONE_END = 1 / 3;
|
||||
const RIGHT_ZONE_START = 2 / 3;
|
||||
let lastHandledTouchAt = 0;
|
||||
|
||||
function viewportWidth(doc) {
|
||||
const viewWidth = Number(doc && doc.defaultView && doc.defaultView.innerWidth);
|
||||
if (Number.isFinite(viewWidth) && viewWidth > 0) return viewWidth;
|
||||
const documentWidth = Number(doc && doc.documentElement && doc.documentElement.clientWidth);
|
||||
if (Number.isFinite(documentWidth) && documentWidth > 0) return documentWidth;
|
||||
return Math.max(1, Number(global.innerWidth) || 1);
|
||||
}
|
||||
|
||||
function selectionText(doc) {
|
||||
try {
|
||||
@@ -39,7 +50,7 @@
|
||||
startAt = Date.now();
|
||||
startTarget = event.target;
|
||||
moved = false;
|
||||
const width = doc.documentElement.clientWidth || global.innerWidth;
|
||||
const width = viewportWidth(doc);
|
||||
brightnessCandidate = Boolean(preferences().brightnessGesture && startX <= width * .18);
|
||||
}
|
||||
|
||||
@@ -55,16 +66,18 @@
|
||||
}
|
||||
|
||||
function doTap(x, width) {
|
||||
if (options.nativeTapZones) return false;
|
||||
const current = preferences();
|
||||
const mode = current.pageTurnMode || 'tapSwipe';
|
||||
const normalized = x / Math.max(1, width);
|
||||
if (normalized >= .28 && normalized <= .72) {
|
||||
if (normalized >= LEFT_ZONE_END && normalized <= RIGHT_ZONE_START) {
|
||||
options.toggleControls();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (mode !== 'tapSwipe' && mode !== 'tap') return;
|
||||
if (normalized < .28) current.invertZones ? options.next() : options.previous();
|
||||
if (mode !== 'tapSwipe' && mode !== 'tap') return false;
|
||||
if (normalized < LEFT_ZONE_END) current.invertZones ? options.next() : options.previous();
|
||||
else current.invertZones ? options.previous() : options.next();
|
||||
return true;
|
||||
}
|
||||
|
||||
function onTouchEnd(event) {
|
||||
@@ -76,14 +89,14 @@
|
||||
const horizontal = Math.abs(dx) > Math.abs(dy) * 1.25;
|
||||
const current = preferences();
|
||||
const mode = current.pageTurnMode || 'tapSwipe';
|
||||
const viewportWidth = doc.documentElement.clientWidth || global.innerWidth;
|
||||
const width = viewportWidth(doc);
|
||||
const viewportHeight = doc.documentElement.clientHeight || global.innerHeight;
|
||||
|
||||
if (interactiveTarget(startTarget) || selectionText(doc)) return;
|
||||
|
||||
if (
|
||||
current.brightnessGesture &&
|
||||
startX <= viewportWidth * .18 &&
|
||||
startX <= width * .18 &&
|
||||
elapsed < 1200 &&
|
||||
Math.abs(dy) >= 28 &&
|
||||
Math.abs(dy) > Math.abs(dx) * 1.35
|
||||
@@ -92,24 +105,37 @@
|
||||
delta: Internal.clamp((-dy / Math.max(1, viewportHeight)) * 100, -100, 100)
|
||||
});
|
||||
consumedAt = Date.now();
|
||||
lastHandledTouchAt = consumedAt;
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (elapsed < 650 && horizontal && Math.abs(dx) >= 48 && (mode === 'tapSwipe' || mode === 'swipe')) {
|
||||
dx < 0 ? options.next() : options.previous();
|
||||
consumedAt = Date.now();
|
||||
lastHandledTouchAt = consumedAt;
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (elapsed < 300 && !moved && Math.abs(dx) < 12 && Math.abs(dy) < 12) {
|
||||
doTap(touch.clientX, doc.documentElement.clientWidth || global.innerWidth);
|
||||
consumedAt = Date.now();
|
||||
if (doTap(touch.clientX, width)) {
|
||||
consumedAt = Date.now();
|
||||
lastHandledTouchAt = consumedAt;
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClick(event) {
|
||||
if (Date.now() - consumedAt < 500 || interactiveTarget(event.target) || selectionText(doc)) return;
|
||||
doTap(event.clientX, doc.documentElement.clientWidth || global.innerWidth);
|
||||
const now = Date.now();
|
||||
if (
|
||||
now - consumedAt < 700 ||
|
||||
now - lastHandledTouchAt < 700 ||
|
||||
interactiveTarget(event.target) ||
|
||||
selectionText(doc)
|
||||
) return;
|
||||
doTap(event.clientX, viewportWidth(doc));
|
||||
}
|
||||
|
||||
function onKeyDown(event) {
|
||||
@@ -127,7 +153,7 @@
|
||||
|
||||
doc.addEventListener('touchstart', onTouchStart, { passive: true });
|
||||
doc.addEventListener('touchmove', onTouchMove, { passive: false });
|
||||
doc.addEventListener('touchend', onTouchEnd, { passive: true });
|
||||
doc.addEventListener('touchend', onTouchEnd, { passive: false });
|
||||
doc.addEventListener('click', onClick, false);
|
||||
doc.addEventListener('keydown', onKeyDown, false);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
@@ -24,9 +25,9 @@ import com.aletheia.app.ui.books.BookshelfFragment
|
||||
import com.aletheia.app.ui.home.HomeFragment
|
||||
import com.aletheia.app.ui.qbooks.QBooksLibraryFragment
|
||||
import com.aletheia.app.ui.reader.ReaderActivity
|
||||
import com.aletheia.app.ui.reader.ReaderHubFragment
|
||||
import com.aletheia.app.ui.settings.SettingsFragment
|
||||
import com.aletheia.app.util.setBookCover
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -57,7 +58,10 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
selectOrOpenTab(resolveInitialTab(intent?.getStringExtra(EXTRA_OPEN_TAB)))
|
||||
} else if (supportFragmentManager.fragments.none { !it.isHidden }) {
|
||||
} else if (
|
||||
supportFragmentManager.fragments.none { !it.isHidden } ||
|
||||
supportFragmentManager.findFragmentByTag(LEGACY_TAG_READER)?.isHidden == false
|
||||
) {
|
||||
selectOrOpenTab(R.id.nav_home)
|
||||
}
|
||||
}
|
||||
@@ -86,7 +90,10 @@ class MainActivity : AppCompatActivity() {
|
||||
private fun openTab(itemId: Int): Boolean = when (itemId) {
|
||||
R.id.nav_home -> showTab(TAG_HOME) { HomeFragment.newInstance() }
|
||||
R.id.nav_search -> showTab(TAG_SEARCH) { QBooksLibraryFragment.newInstance() }
|
||||
R.id.nav_reader -> showTab(TAG_READER) { ReaderHubFragment.newInstance() }
|
||||
R.id.nav_reader -> {
|
||||
openLastReadBook()
|
||||
false
|
||||
}
|
||||
R.id.nav_my_books -> showTab(TAG_MY_BOOKS) { BookshelfFragment.newInstance() }
|
||||
R.id.nav_profile -> showTab(TAG_PROFILE) { SettingsFragment.newInstance() }
|
||||
else -> false
|
||||
@@ -130,9 +137,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
private fun refreshMiniReader() {
|
||||
lifecycleScope.launch {
|
||||
val book = withContext(Dispatchers.IO) {
|
||||
app.bookRepository.getAllBooks().maxByOrNull { item -> item.lastRead }
|
||||
}
|
||||
val book = findLastReadableBook()
|
||||
miniReaderBook = book
|
||||
val visibility = if (book == null) View.GONE else View.VISIBLE
|
||||
binding.miniReaderPanel.visibility = visibility
|
||||
@@ -150,6 +155,36 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
private fun openMiniReader() {
|
||||
val book = miniReaderBook ?: return
|
||||
openReader(book)
|
||||
}
|
||||
|
||||
private fun openLastReadBook() {
|
||||
if (supportFragmentManager.fragments.none { fragment -> !fragment.isHidden }) {
|
||||
showTab(TAG_HOME) { HomeFragment.newInstance() }
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
val book = findLastReadableBook()
|
||||
if (book == null) {
|
||||
Toast.makeText(
|
||||
this@MainActivity,
|
||||
R.string.reader_no_book_selected,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
return@launch
|
||||
}
|
||||
miniReaderBook = book
|
||||
openReader(book)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun findLastReadableBook(): Book? = withContext(Dispatchers.IO) {
|
||||
app.bookRepository.getAllBooks()
|
||||
.asSequence()
|
||||
.filter { book -> File(book.filePath).isFile }
|
||||
.maxByOrNull { book -> book.lastRead }
|
||||
}
|
||||
|
||||
private fun openReader(book: Book) {
|
||||
startActivity(
|
||||
Intent(this, ReaderActivity::class.java)
|
||||
.putExtra(ReaderActivity.EXTRA_BOOK_ID, book.id)
|
||||
@@ -203,7 +238,7 @@ class MainActivity : AppCompatActivity() {
|
||||
const val EXTRA_OPEN_TAB = "open_tab"
|
||||
private const val TAG_HOME = "home"
|
||||
private const val TAG_SEARCH = "search"
|
||||
private const val TAG_READER = "reader"
|
||||
private const val LEGACY_TAG_READER = "reader"
|
||||
private const val TAG_MY_BOOKS = "my-books"
|
||||
private const val TAG_PROFILE = "profile"
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
@@ -14,7 +15,6 @@ import android.graphics.drawable.StateListDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.Gravity
|
||||
@@ -23,6 +23,7 @@ import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.webkit.WebView
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
@@ -99,11 +100,9 @@ class ReaderActivity : AppCompatActivity() {
|
||||
private var readerTouchDownX = 0f
|
||||
private var readerTouchDownY = 0f
|
||||
private var readerTouchDownAt = 0L
|
||||
private var lastNativeControlsToggleAt = 0L
|
||||
private val readerTapSlop by lazy(LazyThreadSafetyMode.NONE) {
|
||||
ViewConfiguration.get(this).scaledTouchSlop.toFloat()
|
||||
}
|
||||
|
||||
private var pageHeaderBasePadding = Insets()
|
||||
private var controlsBasePadding = Insets()
|
||||
private var settingsBasePadding = Insets()
|
||||
@@ -159,6 +158,12 @@ class ReaderActivity : AppCompatActivity() {
|
||||
applySystemUi()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
ViewCompat.requestApplyInsets(binding.root)
|
||||
applySystemUi()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putBoolean(STATE_FINISHING, finishingReader)
|
||||
outState.putString(STATE_PREFERENCES, preferences.toStateJson())
|
||||
@@ -196,11 +201,11 @@ class ReaderActivity : AppCompatActivity() {
|
||||
if (bookReady && preferences.volumeButtons && !preferences.verticalScroll) {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
||||
webController.next()
|
||||
webController.previous()
|
||||
return true
|
||||
}
|
||||
KeyEvent.KEYCODE_VOLUME_UP -> {
|
||||
webController.previous()
|
||||
webController.next()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -546,8 +551,8 @@ class ReaderActivity : AppCompatActivity() {
|
||||
currentPage = book.currentPage.coerceAtLeast(1),
|
||||
totalPages = book.totalPages.coerceAtLeast(1)
|
||||
)
|
||||
position = app.readerStateCoordinator.latest(book.id)?.toReaderPosition()
|
||||
?: restoredPosition
|
||||
position = restoredPosition
|
||||
?: app.readerStateCoordinator.latest(book.id)?.toReaderPosition()
|
||||
?: databasePosition
|
||||
restoredPosition = null
|
||||
publishPosition()
|
||||
@@ -589,10 +594,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
if (finishingReader) return
|
||||
when (event) {
|
||||
ReaderEvent.ShellReady -> binding.readerLoadingText.text = "Открываю книгу…"
|
||||
ReaderEvent.ToggleControls -> {
|
||||
val sinceNativeToggle = SystemClock.uptimeMillis() - lastNativeControlsToggleAt
|
||||
if (sinceNativeToggle > NATIVE_TAP_DUPLICATE_WINDOW_MS) toggleControls()
|
||||
}
|
||||
ReaderEvent.ToggleControls -> toggleControls()
|
||||
ReaderEvent.Navigation -> Unit
|
||||
is ReaderEvent.BookReady -> {
|
||||
bookReady = true
|
||||
@@ -669,6 +671,14 @@ class ReaderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleControls() {
|
||||
if (binding.readerSettingsOverlay.isVisible || binding.readerContentsOverlay.isVisible ||
|
||||
binding.readerSelectionOverlay.isVisible || binding.noteEditorOverlay.isVisible
|
||||
) return
|
||||
binding.readerControlsOverlay.isVisible = !binding.readerControlsOverlay.isVisible
|
||||
renderChromeVisibility()
|
||||
}
|
||||
|
||||
private fun observeNativeReaderTap(event: MotionEvent) {
|
||||
when (event.actionMasked) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
@@ -694,38 +704,46 @@ class ReaderActivity : AppCompatActivity() {
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
val elapsed = event.eventTime - readerTouchDownAt
|
||||
val normalizedX = event.x / binding.readerWebView.width.coerceAtLeast(1)
|
||||
val modalVisible = binding.readerLoadingOverlay.isVisible ||
|
||||
binding.readerSettingsOverlay.isVisible ||
|
||||
binding.readerContentsOverlay.isVisible ||
|
||||
binding.readerSelectionOverlay.isVisible ||
|
||||
binding.noteEditorOverlay.isVisible
|
||||
val shouldToggle = readerTouchActive &&
|
||||
val hitType = binding.readerWebView.hitTestResult.type
|
||||
val interactiveTarget = hitType == WebView.HitTestResult.SRC_ANCHOR_TYPE ||
|
||||
hitType == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE ||
|
||||
hitType == WebView.HitTestResult.EDIT_TEXT_TYPE ||
|
||||
hitType == WebView.HitTestResult.EMAIL_TYPE ||
|
||||
hitType == WebView.HitTestResult.PHONE_TYPE ||
|
||||
hitType == WebView.HitTestResult.GEO_TYPE
|
||||
val shouldHandle = readerTouchActive &&
|
||||
!readerTouchMoved &&
|
||||
elapsed in 0..NATIVE_TAP_MAX_DURATION_MS &&
|
||||
normalizedX in READER_CENTER_ZONE_START..READER_CENTER_ZONE_END &&
|
||||
bookReady &&
|
||||
!finishingReader &&
|
||||
currentSelection == null &&
|
||||
!modalVisible
|
||||
!modalVisible &&
|
||||
!interactiveTarget
|
||||
readerTouchActive = false
|
||||
readerTouchMoved = false
|
||||
if (shouldToggle) {
|
||||
lastNativeControlsToggleAt = SystemClock.uptimeMillis()
|
||||
toggleControls()
|
||||
if (!shouldHandle) return
|
||||
|
||||
val normalizedX = event.x / binding.readerWebView.width.coerceAtLeast(1)
|
||||
when {
|
||||
normalizedX in READER_CENTER_ZONE_START..READER_CENTER_ZONE_END -> toggleControls()
|
||||
preferences.pageTurnMode != ReaderPreferences.PAGE_TURN_TAP &&
|
||||
preferences.pageTurnMode != ReaderPreferences.PAGE_TURN_TAP_SWIPE -> Unit
|
||||
normalizedX < READER_CENTER_ZONE_START -> {
|
||||
if (preferences.invertZones) webController.next() else webController.previous()
|
||||
}
|
||||
else -> {
|
||||
if (preferences.invertZones) webController.previous() else webController.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleControls() {
|
||||
if (binding.readerSettingsOverlay.isVisible || binding.readerContentsOverlay.isVisible ||
|
||||
binding.readerSelectionOverlay.isVisible || binding.noteEditorOverlay.isVisible
|
||||
) return
|
||||
binding.readerControlsOverlay.isVisible = !binding.readerControlsOverlay.isVisible
|
||||
renderChromeVisibility()
|
||||
}
|
||||
|
||||
private fun renderChromeVisibility() {
|
||||
binding.pageHeader.isVisible = preferences.showTitle &&
|
||||
!binding.readerControlsOverlay.isVisible &&
|
||||
@@ -1523,17 +1541,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun handleBack() {
|
||||
when {
|
||||
binding.noteEditorOverlay.isVisible -> closeNoteEditor()
|
||||
binding.readerSelectionOverlay.isVisible -> closeSelection()
|
||||
binding.readerContentsOverlay.isVisible -> closeContents()
|
||||
binding.readerSettingsOverlay.isVisible -> closeSettings()
|
||||
binding.readerControlsOverlay.isVisible -> {
|
||||
binding.readerControlsOverlay.isVisible = false
|
||||
renderChromeVisibility()
|
||||
}
|
||||
else -> finishReader()
|
||||
}
|
||||
finishReader()
|
||||
}
|
||||
|
||||
private fun openExternalLink(url: String) {
|
||||
@@ -1719,9 +1727,8 @@ class ReaderActivity : AppCompatActivity() {
|
||||
private const val PROGRESS_SAVE_DEBOUNCE_MS = 1_500L
|
||||
private const val SETTINGS_SAVE_DEBOUNCE_MS = 180L
|
||||
private const val NATIVE_TAP_MAX_DURATION_MS = 350L
|
||||
private const val NATIVE_TAP_DUPLICATE_WINDOW_MS = 450L
|
||||
private const val READER_CENTER_ZONE_START = 0.28f
|
||||
private const val READER_CENTER_ZONE_END = 0.72f
|
||||
private const val READER_CENTER_ZONE_START = 1f / 3f
|
||||
private const val READER_CENTER_ZONE_END = 2f / 3f
|
||||
private val FATAL_ERROR_STAGES = setOf(
|
||||
"book.load",
|
||||
"api.loadBook",
|
||||
|
||||
@@ -629,13 +629,13 @@
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bg_reader_v2_control"
|
||||
android:contentDescription="@null"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="17dp"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_reader_v2_minus"
|
||||
android:tag="reader_v2_control" />
|
||||
</FrameLayout>
|
||||
@@ -650,13 +650,13 @@
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bg_reader_v2_control"
|
||||
android:contentDescription="@null"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="13dp"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_reader_v2_plus"
|
||||
android:tag="reader_v2_control" />
|
||||
</FrameLayout>
|
||||
@@ -832,13 +832,13 @@
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bg_reader_v2_control"
|
||||
android:contentDescription="@null"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="17dp"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_reader_v2_minus"
|
||||
android:tag="reader_v2_control" />
|
||||
</FrameLayout>
|
||||
@@ -853,13 +853,13 @@
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bg_reader_v2_control"
|
||||
android:contentDescription="@null"
|
||||
android:importantForAccessibility="no"
|
||||
android:padding="13dp"
|
||||
android:padding="6dp"
|
||||
android:src="@drawable/ic_reader_v2_plus"
|
||||
android:tag="reader_v2_control" />
|
||||
</FrameLayout>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="reader_no_book_selected">Книга для чтения не выбрана</string>
|
||||
<string name="app_name">Алетея</string>
|
||||
|
||||
<string name="tab_library">Мои книги</string>
|
||||
|
||||
Reference in New Issue
Block a user