Skip to content

Commit b1b19e0

Browse files
authored
Emit onJumpToLocator when swiping across resources in scroll mode (#330)
1 parent e14cbc6 commit b1b19e0

File tree

3 files changed

+79
-33
lines changed

3 files changed

+79
-33
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ All notable changes to this project will be documented in this file. Take a look
1414
* New `EPUBNavigatorFragment.Configuration.useReadiumCssFontSize` option to revert to the 2.2.0 strategy for setting the font size of reflowable EPUB publications.
1515
* The native font size strategy introduced in 2.3.0 uses the Android web view's [`WebSettings.textZoom`](https://developer.android.com/reference/android/webkit/WebSettings#setTextZoom(int)) property to adjust the font size. 2.2.0 was using Readium CSS's [`--USER__fontSize` variable](https://readium.org/readium-css/docs/CSS12-user_prefs.html#font-size).
1616
* `WebSettings.textZoom` will work with more publications than `--USER__fontSize`, even the ones poorly authored. However the page width is not adjusted when changing the font size to keep the optimal line length.
17+
* Scroll mode: jumping between two EPUB resources with a horizontal swipe triggers the `Navigator.Listener.onJumpToLocator()` callback.
18+
* This can be used to allow the user to go back to their previous location if they swiped across chapters by mistake.
1719

1820
#### Changed
1921

readium/navigator/src/main/java/org/readium/r2/navigator/R2BasicWebView.kt

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(conte
6565
fun onProgressionChanged()
6666
fun onHighlightActivated(id: String)
6767
fun onHighlightAnnotationMarkActivated(id: String)
68-
fun goForward(animated: Boolean = false, completion: () -> Unit = {}): Boolean
69-
fun goBackward(animated: Boolean = false, completion: () -> Unit = {}): Boolean
68+
fun goForward(animated: Boolean = false, completion: () -> Unit = {}): Boolean = false
69+
fun goBackward(animated: Boolean = false, completion: () -> Unit = {}): Boolean = false
7070

7171
/**
7272
* Returns the custom [ActionMode.Callback] to be used with the text selection menu.
@@ -75,15 +75,23 @@ open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(conte
7575

7676
@InternalReadiumApi
7777
fun javascriptInterfacesForResource(link: Link): Map<String, Any?> = emptyMap()
78-
7978
@InternalReadiumApi
8079
fun shouldOverrideUrlLoading(webView: WebView, request: WebResourceRequest): Boolean = false
81-
8280
@InternalReadiumApi
8381
fun shouldInterceptRequest(webView: WebView, request: WebResourceRequest): WebResourceResponse? = null
84-
8582
@InternalReadiumApi
8683
fun resourceAtUrl(url: String): Resource? = null
84+
85+
/**
86+
* Requests to load the next resource in the reading order.
87+
*
88+
* @param jump Indicates whether it's a discontinuous jump from the current locator. Used
89+
* for scroll mode.
90+
*/
91+
@InternalReadiumApi
92+
fun goToNextResource(jump: Boolean, animated: Boolean): Boolean = false
93+
@InternalReadiumApi
94+
fun goToPreviousResource(jump: Boolean, animated: Boolean): Boolean = false
8795
}
8896

8997
var listener: Listener? = null
@@ -183,22 +191,31 @@ open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(conte
183191
val listener = listener ?: return@launch
184192
listener.onScroll()
185193

186-
fun goRight() {
194+
val isRtl = (listener.readingProgression == ReadingProgression.RTL)
195+
196+
fun goRight(jump: Boolean) {
187197
if (listener.readingProgression == ReadingProgression.RTL) {
188-
listener.goBackward(animated = animated)
198+
listener.goBackward(animated = animated) // Legacy
199+
listener.goToPreviousResource(jump = jump, animated = animated)
189200
} else {
190-
listener.goForward(animated = animated)
201+
listener.goForward(animated = animated) // Legacy
202+
listener.goToNextResource(jump = jump, animated = animated)
191203
}
192204
}
193205

194-
if (scrollMode || !this@R2BasicWebView.canScrollHorizontally(1)) {
195-
goRight()
196-
} else {
197-
runJavaScript("readium.scrollRight();") { success ->
198-
if (!success.toBoolean()) {
199-
goRight()
206+
when {
207+
scrollMode ->
208+
goRight(jump = true)
209+
210+
!this@R2BasicWebView.canScrollHorizontally(1) ->
211+
goRight(jump = false)
212+
213+
else ->
214+
runJavaScript("readium.scrollRight();") { success ->
215+
if (!success.toBoolean()) {
216+
goRight(jump = false)
217+
}
200218
}
201-
}
202219
}
203220
}
204221
}
@@ -209,22 +226,29 @@ open class R2BasicWebView(context: Context, attrs: AttributeSet) : WebView(conte
209226
val listener = listener ?: return@launch
210227
listener.onScroll()
211228

212-
fun goLeft() {
229+
fun goLeft(jump: Boolean) {
213230
if (listener.readingProgression == ReadingProgression.RTL) {
214-
listener.goForward(animated = animated)
231+
listener.goForward(animated = animated) // legacy
232+
listener.goToNextResource(jump = jump, animated = animated)
215233
} else {
216-
listener.goBackward(animated = animated)
234+
listener.goBackward(animated = animated) // legacy
235+
listener.goToPreviousResource(jump = jump, animated = animated)
217236
}
218237
}
219238

220-
if (scrollMode || !this@R2BasicWebView.canScrollHorizontally(-1)) {
221-
goLeft()
222-
} else {
223-
runJavaScript("readium.scrollLeft();") { success ->
224-
if (!success.toBoolean()) {
225-
goLeft()
239+
when {
240+
scrollMode ->
241+
goLeft(jump = true)
242+
243+
!this@R2BasicWebView.canScrollHorizontally(-1) ->
244+
goLeft(jump = false)
245+
246+
else ->
247+
runJavaScript("readium.scrollLeft();") { success ->
248+
if (!success.toBoolean()) {
249+
goLeft(jump = false)
250+
}
226251
}
227-
}
228252
}
229253
}
230254
}

readium/navigator/src/main/java/org/readium/r2/navigator/epub/EpubNavigatorFragment.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -763,11 +763,13 @@ class EpubNavigatorFragment internal constructor(
763763
r2Activity?.highlightAnnotationMarkActivated(id)
764764
}
765765

766-
override fun goForward(animated: Boolean, completion: () -> Unit): Boolean =
767-
goToNextResource(animated, completion)
766+
override fun goToPreviousResource(jump: Boolean, animated: Boolean): Boolean {
767+
return this@EpubNavigatorFragment.goToPreviousResource(jump = jump, animated = animated)
768+
}
768769

769-
override fun goBackward(animated: Boolean, completion: () -> Unit): Boolean =
770-
goToPreviousResource(animated, completion)
770+
override fun goToNextResource(jump: Boolean, animated: Boolean): Boolean {
771+
return this@EpubNavigatorFragment.goToNextResource(jump = jump, animated = animated)
772+
}
771773

772774
override val selectionActionModeCallback: ActionMode.Callback?
773775
get() = config.selectionActionModeCallback
@@ -791,7 +793,7 @@ class EpubNavigatorFragment internal constructor(
791793

792794
override fun goForward(animated: Boolean, completion: () -> Unit): Boolean {
793795
if (publication.metadata.presentation.layout == EpubLayout.FIXED) {
794-
return goToNextResource(animated, completion)
796+
return goToNextResource(jump = false, animated = animated, completion)
795797
}
796798

797799
val webView = currentReflowablePageFragment?.webView ?: return false
@@ -809,7 +811,7 @@ class EpubNavigatorFragment internal constructor(
809811

810812
override fun goBackward(animated: Boolean, completion: () -> Unit): Boolean {
811813
if (publication.metadata.presentation.layout == EpubLayout.FIXED) {
812-
return goToPreviousResource(animated, completion)
814+
return goToPreviousResource(jump = false, animated = animated, completion)
813815
}
814816

815817
val webView = currentReflowablePageFragment?.webView ?: return false
@@ -825,12 +827,16 @@ class EpubNavigatorFragment internal constructor(
825827
return true
826828
}
827829

828-
private fun goToNextResource(animated: Boolean, completion: () -> Unit): Boolean {
830+
private fun goToNextResource(jump: Boolean, animated: Boolean, completion: () -> Unit = {}): Boolean {
829831
val adapter = resourcePager.adapter ?: return false
830832
if (resourcePager.currentItem >= adapter.count - 1) {
831833
return false
832834
}
833835

836+
if (jump) {
837+
locatorToNextResource()?.let { listener?.onJumpToLocator(it) }
838+
}
839+
834840
resourcePager.setCurrentItem(resourcePager.currentItem + 1, animated)
835841

836842
currentReflowablePageFragment?.webView?.let { webView ->
@@ -845,11 +851,15 @@ class EpubNavigatorFragment internal constructor(
845851
return true
846852
}
847853

848-
private fun goToPreviousResource(animated: Boolean, completion: () -> Unit): Boolean {
854+
private fun goToPreviousResource(jump: Boolean, animated: Boolean, completion: () -> Unit = {}): Boolean {
849855
if (resourcePager.currentItem <= 0) {
850856
return false
851857
}
852858

859+
if (jump) {
860+
locatorToPreviousResource()?.let { listener?.onJumpToLocator(it) }
861+
}
862+
853863
resourcePager.setCurrentItem(resourcePager.currentItem - 1, animated)
854864

855865
currentReflowablePageFragment?.webView?.let { webView ->
@@ -864,6 +874,16 @@ class EpubNavigatorFragment internal constructor(
864874
return true
865875
}
866876

877+
private fun locatorToPreviousResource(): Locator? =
878+
locatorToResourceAtIndex(resourcePager.currentItem - 1)
879+
880+
private fun locatorToNextResource(): Locator? =
881+
locatorToResourceAtIndex(resourcePager.currentItem + 1)
882+
883+
private fun locatorToResourceAtIndex(index: Int): Locator? =
884+
publication.readingOrder.getOrNull(index)
885+
?.let { publication.locatorFromLink(it) }
886+
867887
private val r2PagerAdapter: R2PagerAdapter?
868888
get() = if (::resourcePager.isInitialized) resourcePager.adapter as? R2PagerAdapter
869889
else null

0 commit comments

Comments
 (0)