Anki-Android icon indicating copy to clipboard operation
Anki-Android copied to clipboard

[BUG]: localStorage does not seem to be persistent in version 2.17.5

Open pganssle opened this issue 2 years ago • 4 comments

Checked for duplicates?

  • [X] This issue is not a duplicate

What are the steps to reproduce this bug?

  1. Create a card with the following contents on it somewhere:
<script>
const STORAGE_KEY = "example-storage-location";

let existing_storage = localStorage.getItem(STORAGE_KEY);
if (existing_storage === null) {
    existing_storage = 0;
} else {
    existing_storage = parseInt(existing_storage);
}

console.log("This template has been accessed " + existing_storage + " times.");

existing_storage = existing_storage + 1;

localStorage.setItem(STORAGE_KEY, existing_storage);
console.log(STORAGE_KEY + " set to " + existing_storage);
</script>
  1. Connect phone in debug mode.
  2. Open chrome://inspect on phone and check the console logs.
  3. Go to front, back, multiple cards, etc.
  4. Exit deck to list of decks
  5. Select same deck, repeat steps 2-4.

Expected behaviour

The console should say: "This template has been accessed 0 times", then increment by 1 for each time the template is accessed (once for front, once for back, etc). The number should not reset when you exit and then re-enter the deck.

Actual behaviour

All localStorage seems to be lost when exiting the deck.

Debug info

AnkiDroid Version = 2.17.5 (1c1aa94ec466f37d33fd2f75020d9f9021ac811e)
Backend Version = 0.1.34-anki23.12.1 (23.12.1 1a1d4d5419c6b57ef3baf99c9d2d9cf85d36ae0a)
Android Version = 14 (SDK 34)
ProductFlavor = play
Manufacturer = Google
Webview User Agent = Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro Build/UQ1A.240205.004; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/122.0.6261.119 Mobile Safari/537.36
ACRA UUID = 
Crash Reports Enabled = true

(Optional) Anything else you want to share?

I have been using localStorage to store persistent per-deck settings, e.g. "Show pictures automatically" or "Play TTS automatically", etc, because depending on the review situation, I want more or less automatic behavior (e.g. if I am in a room where I don't have headphones and I need to be quiet, I don't want TTS going off automatically). This worked in previous versions, but now my settings get lost any time I exit the deck.

Seems like someone else is having the same issue as well, and they appear to be using localStorage to share information across decks.

Research

  • [X] I am reporting a bug specific to AnkiDroid (Android app)
  • [X] I have checked the manual and the FAQ and could not find a solution to my issue
  • [ ] (Optional) I have confirmed the issue is not resolved in the latest alpha release (instructions)

pganssle avatar Mar 15 '24 18:03 pganssle

Hello! 👋 Thanks for logging this issue. Please remember we are all volunteers here, so some patience may be required before we can get to the issue. Also remember that the fastest way to get resolution on an issue is to propose a change directly, https://github.com/ankidroid/Anki-Android/wiki/Contributing

welcome[bot] avatar Mar 15 '24 18:03 welcome[bot]

Cause:

https://github.com/ankidroid/Anki-Android/blob/de53c357fa4da65400d161038bc85106a352a0be/AnkiDroid/src/main/java/com/ichi2/anki/pages/AnkiServer.kt#L26-L27

Local storage is not shared if we're hosting on a dynamic port

david-allison avatar Mar 18 '24 20:03 david-allison

@pganssle As far as I understand it, Anki Desktop loses localStorage once it's been closed.

After the fix, AnkiDroid will do the same. If more is required, please let me know

Note: this needs more work - two AnkiServer instances can't share the same port. This can currently occur when two screens are available simultaneously

        /**
         * Converts [INITIAL_PORT] into a port which is consistent
         * throughout execution of AnkiDroid
         *
         * This allows localStorage to save data between 
         */
        val FIXED_PORT = try {
            INITIAL_PORT.ifZero { ServerSocket(0).use { it.localPort } }
        } catch (e: Exception) {
            INITIAL_PORT
        }

david-allison avatar Mar 18 '24 20:03 david-allison

Thanks for the quick response! I tried tracking this down a bit and couldn't quite figure out what had changed, I'm glad you were able to figure it out so quickly!

@pganssle As far as I understand it, Anki Desktop loses localStorage once it's been closed.

After the fix, AnkiDroid will do the same. If more is required, please let me know

It looks like this is the case, which is maybe a bug that should be raised in Anki Desktop as well, since my understanding is that localStorage is supposed to persist between sessions, while sessionStorage is supposed to close after a given browser session. For my use case, having localStorage clear when exiting AnkiDroid would not be ideal (not sure when that happens on Android, presumably on restarts and updates, plus at random times depending on how the OS manages it and what else you are doing with the phone). I am mostly using it to store per-deck settings. The proposed fix would be an improvement over the current behavior (since the settings are mostly stable, and when I want them to be different it's usually for a single session anyway, so I can edit the deck to change the settings long term, and use the settings toggles as per-session controls), but I do think it's still a regression over the previous behavior.

pganssle avatar Mar 19 '24 14:03 pganssle

Hello 👋, this issue has been opened for more than 3 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically

github-actions[bot] avatar Sep 12 '24 02:09 github-actions[bot]

https://github.com/ikkz/anki-storage

You can use this tool I just developed to use persistent localStorage in ankidroid

ikkz avatar Dec 26 '24 15:12 ikkz

@ikkz you may want to try the "new reviewer" (which uses the upstream anki reviewer code vs local code here) and see if it works better for your use cases without needing much (if any) code. I'm under the impression that it does not reload the WebView nearly as frequently

You enable it as a developer option currently - and if you're not running a locally-built version of AnkiDroid then you enable developer options by going to Settings -> About then tapping the logo a bunch of times. Now you can go to Settings -> Developer Options and turn on "New reviewer" at the bottom

The New reviewer is still a work in progress in that it is missing mappable keybindings and I think text-to-speech but otherwise is working and it will be the default in the future as the last couple features from the old reviewer are implemented in it

mikehardy avatar Dec 26 '24 15:12 mikehardy

@mikehardy Thank you for your detailed guidance. I followed these steps to try the new reviewer, and the experience was great. However, it seems that the page is still running on a random port, which has caused the localStorage in the reviewer to stop working, and my tool is also not functioning anymore. 🥲

ikkz avatar Dec 27 '24 14:12 ikkz

However, it seems that the page is still running on a random port,

It is

BrayanDSO avatar Dec 28 '24 10:12 BrayanDSO