odysseus/static
Léo 663d6879b7
fix(ui): stop the whirlpool spinner animating when it is never attached (#5990)
_drawWhirlpool re-armed requestAnimationFrame forever whenever its element
had never been connected to the document. The grace period is there so a
spinner can keep drawing between start() and the caller appending the
element, but it had no deadline: while the element has never been connected
_wpWasConnected stays false, so the guard stays true and the else branch is
unreachable. Any caller that starts a spinner and then takes an early return,
such as an aborted request or a panel that resolved from cache, leaves a loop
redrawing an 84-segment spiral into a detached canvas at one frame per
displayed frame until the tab closes.

Put a 2 second deadline on the grace period. Callers append in the same task
as start(), so that is far more slack than any of them need. A spinner that
is actually in the document is unaffected.

Two supporting changes in the same file:

- Both self-terminate paths now call stop() instead of setting isRunning
  directly, so termination always runs one cancelAnimationFrame and never
  depends solely on inferring DOM connectivity. Both draw functions bail at
  the top when they are no longer running, and _requestFrame() clears rafId
  as the callback enters so it is a truthful "a frame is pending" flag.
- start() arms a visibilitychange listener and stop() removes it. A hidden
  tab cancels the pending frame, a re-shown tab re-arms it. Chrome throttles
  background rAF but does not reliably stop the canvas work, and owning the
  listener from start/stop means a dead spinner never leaves one behind.

Adds tests/test_spinner_stops_when_never_attached_js.py, which drives the
real module under node with a fake clock and a manual frame pump. It covers
all four exits and, importantly, the converse: a spinner that is attached
keeps running well past the grace window.
2026-08-12 00:25:03 +01:00
..
fonts feat(a11y): add a Text size control and an OpenDyslexic font option (#4210) 2026-06-22 13:53:46 +02:00
icons Cookbook model workflow fixes 2026-06-21 11:02:35 +00:00
js fix(ui): stop the whirlpool spinner animating when it is never attached (#5990) 2026-08-12 00:25:03 +01:00
lib Odysseus v1.0 2026-05-31 23:58:26 +09:00
app.js perf(ui): stop session loading from blocking shell (#5927) 2026-08-10 19:37:21 +01:00
icon.ico feat(launcher): add portable windows launcher (#976) 2026-06-16 04:58:16 +01:00
index.html perf(ui): stop session loading from blocking shell (#5927) 2026-08-10 19:37:21 +01:00
login.html fix(auth): centralize password and username validation constants (#4120) 2026-06-16 09:52:15 +02:00
manifest.json pwa missing icons added (#428) 2026-06-15 16:00:13 +09:00
modal-control-variants.html Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
style.css perf(ui): stop session loading from blocking shell (#5927) 2026-08-10 19:37:21 +01:00
sw.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
wave-variants.html Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
whirlpool-variants.html Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00