From d08819a06f7ba8a6e1785f4e5562230064ce214a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Menu?= Date: Fri, 3 May 2024 13:23:10 +0200 Subject: [PATCH] Fix applying preferences while recreating EPUB fragments (#507) --- CHANGELOG.md | 1 + .../navigator/epub/EpubNavigatorFragment.kt | 13 +++---- .../r2/navigator/pager/R2EpubPageFragment.kt | 37 ++++++++++++++++++- .../java/org/readium/r2/opds/OPDS1Parser.kt | 2 +- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2456b7c77..ed7df82fc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file. Take a look #### Navigator * [#325](https://github.com/readium/kotlin-toolkit/issues/325) Top EPUB selections no longer break when dragging the selection handles. +* Fixed applying preferences while the EPUB navigator fragment is being recreated. ## [3.0.0-alpha.2] diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt index b9f8541819..4c6f60d0a1 100644 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt @@ -294,8 +294,7 @@ public class EpubNavigatorFragment internal constructor( public suspend fun evaluateJavascript(script: String): String? { val page = currentReflowablePageFragment ?: return null page.awaitLoaded() - val webView = page.webView ?: return null - return webView.runJavaScriptSuspend(script) + return page.runJavaScriptSuspend(script) } private val viewModel: EpubNavigatorViewModel by viewModels { @@ -665,17 +664,17 @@ public class EpubNavigatorFragment internal constructor( private fun run(command: RunScriptCommand) { when (command.scope) { RunScriptCommand.Scope.CurrentResource -> { - currentReflowablePageFragment?.webView + currentReflowablePageFragment ?.runJavaScript(command.script) } RunScriptCommand.Scope.LoadedResources -> { r2PagerAdapter?.mFragments?.forEach { _, fragment -> - (fragment as? R2EpubPageFragment)?.webView + (fragment as? R2EpubPageFragment) ?.runJavaScript(command.script) } } is RunScriptCommand.Scope.Resource -> { - loadedFragmentForHref(command.scope.href)?.webView + loadedFragmentForHref(command.scope.href) ?.runJavaScript(command.script) } is RunScriptCommand.Scope.WebView -> { @@ -713,9 +712,9 @@ public class EpubNavigatorFragment internal constructor( // SelectableNavigator override suspend fun currentSelection(): Selection? { - val webView = currentReflowablePageFragment?.webView ?: return null + val fragment = currentReflowablePageFragment ?: return null val json = - webView.runJavaScriptSuspend("readium.getCurrentSelection();") + fragment.runJavaScriptSuspend("readium.getCurrentSelection();") .takeIf { it != "null" } ?.let { tryOrLog { JSONObject(it) } } ?: return null diff --git a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt index 7f0d474c2e..5a613ddce9 100755 --- a/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt +++ b/readium/navigator/src/main/java/org/readium/r2/navigator/pager/R2EpubPageFragment.kt @@ -11,7 +11,6 @@ package org.readium.r2.navigator.pager import android.annotation.SuppressLint import android.graphics.PointF -import android.os.Build import android.os.Bundle import android.util.DisplayMetrics import android.view.* @@ -30,6 +29,8 @@ import androidx.lifecycle.repeatOnLifecycle import androidx.webkit.WebViewClientCompat import androidx.webkit.WebViewCompat import androidx.webkit.WebViewFeature +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine import kotlin.math.roundToInt import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch @@ -213,6 +214,8 @@ internal class R2EpubPageFragment : Fragment() { override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) + onPageFinished() + link?.let { webView.listener?.onResourceLoaded(webView, it) } @@ -249,6 +252,26 @@ internal class R2EpubPageFragment : Fragment() { return containerView } + private var isPageFinished = false + private val pendingPageFinished = mutableListOf<() -> Unit>() + + /** + * Will run the given [action] when the content of the [WebView] is loaded. + */ + fun whenPageFinished(action: () -> Unit) { + if (isPageFinished) { + action() + } else { + pendingPageFinished.add(action) + } + } + + private fun onPageFinished() { + isPageFinished = true + pendingPageFinished.forEach { it() } + pendingPageFinished.clear() + } + /** * Will run the given [action] when the content of the [WebView] is fully laid out. */ @@ -448,6 +471,18 @@ internal class R2EpubPageFragment : Fragment() { } } + fun runJavaScript(script: String, callback: ((String) -> Unit)? = null) { + whenPageFinished { + requireNotNull(webView).runJavaScript(script, callback) + } + } + + suspend fun runJavaScriptSuspend(javascript: String): String = suspendCoroutine { cont -> + runJavaScript(javascript) { result -> + cont.resume(result) + } + } + companion object { private const val textZoomBundleKey = "org.readium.textZoom" diff --git a/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt b/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt index e8991f53e8..15cffc5e6f 100644 --- a/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt +++ b/readium/opds/src/main/java/org/readium/r2/opds/OPDS1Parser.kt @@ -81,7 +81,7 @@ public class OPDS1Parser { ReplaceWith("parse(jsonData, url.toUrl()!!)"), DeprecationLevel.ERROR ) - public fun parse(jsonData: ByteArray, url: URL): ParseData = + public fun parse(xmlData: ByteArray, url: URL): ParseData = throw NotImplementedError() private fun parseFeed(root: ElementNode, url: Url): Feed {