odysseus/static/js
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
..
calendar fix(security): escape backslashes in calendar bg-image CSS url() (#4712) 2026-06-22 21:17:52 +02:00
color fix: theme color parsing breaks on #rgb shorthand hex (#1213) 2026-06-03 00:30:03 +09:00
compare Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
editor Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
emailLibrary fix(email): route summaries through shared LLM adapter (#5841) 2026-08-08 23:06:41 +02:00
markdown Ignore non-string markdown table rows (#1648) 2026-06-03 14:17:02 +09:00
model fix: model cost/info matches first substring key (gpt-4o-mini billed as gpt-4o) (#1439) 2026-06-04 03:05:37 +01:00
research Show thumbnails on past research cards 2026-06-30 08:00:01 +00:00
util fix: monthly schedule label shows 21th/22th/31th (ordinal suffix for days >20) (#1577) 2026-06-03 08:57:47 +09:00
a11y.js Improve accessibility across core flows (#86) 2026-06-01 22:04:00 +02:00
admin.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
assistant.js refactor(tools): move model-interaction tools to the agent_tools registry (#4445) 2026-06-18 05:56:37 +00:00
calendar.js Merge dev into main for testing 2026-06-28 14:07:23 +00:00
censor.js Ignore censor preference storage errors (#1652) 2026-06-03 14:16:55 +09:00
chat.js perf(chat): batch live thinking rendering and bound timer updates (#5931) 2026-08-10 20:11:48 +01:00
chatRenderer.js fix(tool_parsing): require a pipe on the Qwen bare end marker (#5829) 2026-08-07 19:33:14 +02:00
chatStream.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
codeRunner.js Fix/windows llama cpp serve and test upstream (#2669) 2026-06-05 14:53:33 +02:00
colorPicker.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
composerArrowUpRecall.js fix(chat): stop ArrowUp from eating an unsent multi-line prompt (#5875) 2026-08-07 19:34:50 +02:00
cookbook-deps-recipes.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbook-diagnosis.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbook-hwfit.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbook.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbookDownload.js Checkpoint Odysseus local update 2026-07-07 00:50:07 +00:00
cookbookPorts.js fix(cookbook): only block model launch on real port collisions (#4760) 2026-06-24 19:44:09 +02:00
cookbookProgressSignal.js Don't falsely declare a dependency build stale (#1568) (#1768) 2026-06-03 13:23:35 +09:00
cookbookRunning.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
cookbookSchedule.js Cookbook UI: Ollama browser, advanced serve fold, API tokens form, diagnosis toolbar, polish 2026-06-09 09:46:19 +09:00
cookbookServe.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
document.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
documentLibrary.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
dragSort.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
emailInbox.js fix(email): make unread opens one authoritative IMAP operation (#5923) 2026-08-10 18:45:34 +01:00
emailLibrary.js perf(email): make library prewarm idle and bounded (#5925) 2026-08-10 19:14:10 +01:00
emailShared.js Polish mobile UI and editor workflows 2026-06-27 13:05:44 +00:00
emojiPicker.js fix(modal): keep body-portaled dropdowns above their tool modal at any stack depth (#4720) (#4724) 2026-06-23 10:24:31 +02:00
emojiShortcodes.js Render emoji shortcodes as icons in chat (#345) (#629) 2026-06-05 02:28:42 +02:00
escMenuStack.js fix: make transient dropdown/popup menus close on Escape 2026-06-01 14:23:22 -04:00
fileHandler.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
gallery.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
galleryEditor.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
group.js fix: group selection drop-downs recreation and repopulation logic (#3424) 2026-06-26 13:35:25 +01:00
init.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
keyboard-shortcuts.js fix: _matchesCombo crashes on non-string keybind from server (#2049) 2026-07-11 03:15:19 +01:00
langIcons.js fix: langIcon throws on an explicit null opts argument (#1740) 2026-06-03 13:29:21 +09:00
liveThinkingThrottle.js perf(chat): batch live thinking rendering and bound timer updates (#5931) 2026-08-10 20:11:48 +01:00
markdown.js fix(markdown): restore extracted blocks verbatim so $& and $$ survive (#5768) 2026-07-30 10:48:31 +01:00
memory.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
modalManager.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
modalSnap.js Merge remote-tracking branch 'origin/dev' into test-main-dev-merge-20260615 2026-06-15 21:20:15 +09:00
modelPicker.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
models.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
modelSort.js Ignore invalid model sort inputs (#1653) 2026-06-03 14:16:52 +09:00
MODULE_SUMMARY.md perf(chat): batch live thinking rendering and bound timer updates (#5931) 2026-08-10 20:11:48 +01:00
notes.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
package.json Fix test suite: ESM module loading and stub isolation (#844) 2026-06-02 11:29:29 +09:00
platform.js Ignore AltGr keystrokes in Ctrl+Alt keyboard shortcuts (#825) 2026-06-02 11:12:54 +09:00
presets.js fix: group selection drop-downs recreation and repopulation logic (#3424) 2026-06-26 13:35:25 +01:00
providerDeviceFlow.js feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
providers.js feat(discovery): detect llama.cpp servers and label local providers (#4729) 2026-06-23 23:39:56 +02:00
rag.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
researchSynapse.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
search-chat.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
search.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
section-management.js Fix Models section collapse dead pause and missing animation 2026-06-01 16:53:46 +02:00
sessions.js perf(ui): stop session loading from blocking shell (#5927) 2026-08-10 19:37:21 +01:00
settings.js fix(email): open settings after OAuth callback (#5803) 2026-07-30 14:57:07 +01:00
sidebar-layout.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
signature.js Constrain signature uploads to PNG data (#2844) 2026-06-05 13:17:43 +02:00
skills.js Fix #5870: stale skills panel data on tab reopen (#5876) 2026-08-07 22:06:17 +02:00
slashAutocomplete.js feat: add ChatGPT Subscription provider (#2876) 2026-06-08 10:19:18 +02:00
slashCommands.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
spinner.js fix(ui): stop the whirlpool spinner animating when it is never attached (#5990) 2026-08-12 00:25:03 +01:00
startupShell.js perf(ui): stop session loading from blocking shell (#5927) 2026-08-10 19:37:21 +01:00
storage.js feat(a11y): add a Text size control and an OpenDyslexic font option (#4210) 2026-06-22 13:53:46 +02:00
streamingRenderer.js fix(chat): stop code-block button flicker during streaming (#3023) 2026-06-06 04:08:54 -06:00
streamingSegmenter.js fix(chat): stop code-block button flicker during streaming (#3023) 2026-06-06 04:08:54 -06:00
tasks.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
theme.js feat(a11y): add a Text size control and an OpenDyslexic font option (#4210) 2026-06-22 13:53:46 +02:00
tileManager.js fix(ui): restore all-edge modal snap zones (#2260) 2026-06-15 12:36:34 +02:00
toolWindowZOrder.js fix(modal): keep body-portaled dropdowns above their tool modal at any stack depth (#4720) (#4724) 2026-06-23 10:24:31 +02:00
tourAutoplay.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
tourHints.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
tts-ai.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
ui.js Merge verified Odysseus fixes 2026-07-23 14:49:02 +00:00
voiceRecorder.js Odysseus v1.0 2026-05-31 23:58:26 +09:00
windowDrag.js fix(windowDrag): disable duplicate top-edge fullscreen snap (#3495) 2026-06-15 16:10:40 +09:00
windowResize.js Make tool windows resizable by dragging edges or corners 2026-06-01 19:49:23 +02:00
workspace.js feat(agent): confine agent file/shell tools to a selectable workspace (#3665) 2026-06-11 18:17:54 +02:00