Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some EPUB books don't restore the expected location after rotation or fold action for foldables #348

Open
radusalagean opened this issue Apr 17, 2023 · 2 comments

Comments

@radusalagean
Copy link

Bug Report

What happened?

Sometimes, some EPUB books don't keep the last viewed position when rotating the device or folding a foldable device, like the Galaxy Z Fold4 for example. I noticed it only on EPUBs which are not split across chapters and the whole content is delivered as one large xhtml resource.

Screen.Recording.2023-04-17.at.21.21.46.mov

Another video showing the behavior on a foldable emulator - size too large to fit github limit

Expected behavior

When rotating or folding a foldable device, our users expect the position to be at least close to the last position that was displayed, before the rotation / fold action.

How to reproduce?

  1. Download this ebook and unzip it:
    test-book.zip
  2. Open it in the Readium Sample App - I used the main branch
  3. Jump somewhere in the middle of the book
  4. Rotate or fold the device

Environment

  • Readium version: 2.3.0

Development environment

  • OS: macOS 13.3.1 (22E261)
  • IDE: Android Studio Electric Eel | 2022.1.1 Patch 2

Testing device

  • Android version: 13
  • Model: Resizable (Experimental) API 33 with 3GB RAM - also reported by a user to happen on Samsung Galaxy Z Fold4 with Android 13
  • Is it an emulator? Yes

Additional context

The behavior is non-deterministic and based on my investigation of the Readium Sample app, is caused by this line.

I forked the repo and added some logs and notes with my observations to give you more context. Please have a look at the videos where I reproduced the issue and check the equivalent logs in my commit.

As you can see in the videos, the callback from: webView.evaluateJavascript("true") sometimes fires before the webView.publicComputeHorizontalScrollRange() can return the correct value, while the alternative callback from postVisualStateCallback always seems to run after the page is loaded, and thus the issue cannot be reproduced with the second approach.

webView.numPages is read here, a value which relies on webView.computeHorizontalScrollRange. Because webView.computeHorizontalScrollRange is read before the content is fully loaded (due to the webView.evaluateJavascript("true") callback firing early, numPages will have a lower value than expected, and the item will have an unexpected value as well because of that.

@mickael-menu
Copy link
Member

Thank you, I appreciate that you spent some time debugging this issue.

As you noticed, it's a tricky problem without a clear solution, since AFAIK there's no JS event that we can use to know when the page is fully laid out. I don't think we ever tried using postVisualStateCallback, and it sounds promising. I'll take a look into your findings later this week.

@mickael-menu
Copy link
Member

I copied your logs and used the book you shared.

On both my device and the resizable API 33 emulator, I mostly didn't see any difference between postVisualStateCallback and evaluateJavascript("true").

Screenshot 2023-04-21 at 17 22 25

Rarely, I noticed a one-page difference:

Screenshot 2023-04-21 at 17 23 31

The location were more or less restored, although I ended up a couple of pages before or after. I think on such large chapters, using the scroll progression is not so accurate.

All this probably depends on the device though, it's tricky...

As you pointed out, using only postVisualStateCallback might not work on all devices. Maybe a combination of evaluateJavascript("true") + additional arbitrary delay coupled with postVisualStateCallback could help.

Here's another alternative as food-for-thought:

  1. Instead of relying on the scroll progression, compute the CSS selector of the first visible DOM element (+ probably a character range offset, in case the DOM element spans several screens).
  2. When jumping to a particular location (which contains the CSS selector), make sure we reposition the web page to the location every time the web page size changes, until the user interacts with the content (taps, swipes, etc.).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants