Skip to content

fix(anki-26.09): defer reloading the page until 'Save & Optimize' has been handled - #22165

Merged
mikehardy merged 5 commits into
ankidroid:mainfrom
david-allison:anki-26-09-2-part-8
Sep 30, 2026
Merged

mikehardy merged 5 commits into
ankidroid:mainfrom
david-allison:anki-26-09-2-part-8

Conversation

@david-allison

Copy link
Copy Markdown
Member

Note

Assisted-by: GPT-6

Purpose / Description

In 26.09, Save & Optimize starts a save, then reloads. This can interrupt the response to AnkiDroid and broke one of our instrumentation tests.

This appears to be a legitimate failure due to a missing await: https://github.com/ankitects/anki/blob/41d7464c9b673e2aa15f76daa76d77ee110d7533/ts/routes/deck-options/FsrsOptions.svelte#L352-L353

Run python3 .github/report_emulator_test_failures.py AnkiDroid/build/outputs/androidTest-results/connected adb-log.txt
Error: com.ichi2.anki.pages.DeckOptionsTest.optimizingAllPresetsSavesAndReloadsOptions
java.lang.AssertionError: options did not reload after optimization
	at org.junit.Assert.fail(Assert.java:89)
	at kotlin.test.junit.JUnitAsserter.fail(JUnitSupport.kt:56)
	at kotlin.test.AssertionsKt__AssertionsKt.fail(Assertions.kt:564)
	at kotlin.test.AssertionsKt.fail(Unknown Source:1)
	at com.ichi2.anki.testutil.WaitUtilsKt.waitUntil-KLykuaI(WaitUtils.kt:31)
	at com.ichi2.anki.pages.DeckOptionsTest.optimizingAllPresetsSavesAndReloadsOptions$lambda$0(DeckOptionsTest.kt:79)
	at com.ichi2.anki.pages.DeckOptionsTest.$r8$lambda$FG7CRc2X4s57kecsqD6fJ-RL8Ro(DeckOptionsTest.kt:0)
	at com.ichi2.anki.pages.DeckOptionsTest$$ExternalSyntheticLambda18.invoke(R8$$SyntheticClass:0)
	at com.ichi2.anki.pages.DeckOptionsTest.withDeckOptions(DeckOptionsTest.kt:125)
	at com.ichi2.anki.pages.DeckOptionsTest.optimizingAllPresetsSavesAndReloadsOptions(DeckOptionsTest.kt:72)
Skipped tests (9)
  • if we get a failure; we don't want to navigate away as that loses state
  • if we navigate during the frontend reading the body, it is treated as an error

Fixes

Approach

We hook into the save request, deferring a page reload until the frontend has handled the successful response.

We work around this by hooking into blob() and reporting this to AnkiDroid. After the read occurred, it's safe to reload (even if this discards the UI handling of the response - we were reloading anyway).

How Has This Been Tested?

Heavily unit tested, the existing instrumented test now passes.

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

In 26.09, save & optimize performed a refresh, which was a legitimate bug
if there was a delayed response.

These extracted functions allow the next commit to focus on the race
condition via properly detecting a reload.

Part of 21926

Assisted-by: GPT-6
Part of 21926

Assisted-by: GPT-6
Reading a cloned response was not a good signal.
Instead, observe `blob()`.

Assisted-by: GPT-6
We want to guard against navigation while the operation is
in progress.

fetch/body-read errors are rethrown (frontend displays them).

Assisted-by: GPT-6
The 26.09 frontend reloads immediately after starting Save & Optimize.

This needs to be deferred until we have consumed the response

* if we get a failure; we don't want to navigate away,
  as this loses state
* if we navigate during the frontend reading the body,
  it is treated as an error

Requesting the reload is still required for 26.05.

Part of 21926

Assisted-by: GPT-6
@david-allison david-allison added the Review High Priority Request for high priority review label Sep 28, 2026

@mikehardy mikehardy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — after adversarial review + local CI-parity (lint/unit/emulator on API36_GAPI_PS16K) on a rebase onto current main.

@mikehardy mikehardy added Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Review High Priority Request for high priority review Needs Review labels Sep 30, 2026
@mikehardy
mikehardy added this pull request to the merge queue Sep 30, 2026
Merged via the queue into ankidroid:main with commit 0ee995f Sep 30, 2026
23 of 25 checks passed
@david-allison
david-allison deleted the anki-26-09-2-part-8 branch September 30, 2026 11:25
@github-actions github-actions Bot removed the Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) label Sep 30, 2026
@github-actions github-actions Bot added this to the 2.26 release milestone Sep 30, 2026
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

Successfully merging this pull request may close these issues.

2 participants