Skip to content

Add a shell-level auto-refresh pause/resume control (#4222) - #4365

Merged
erikdarlingdata merged 1 commit into
devfrom
feature/4222-shell-play-pause
Sep 26, 2026
Merged

erikdarlingdata merged 1 commit into
devfrom
feature/4222-shell-play-pause

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Refs #4222.

Why

Erik's ruling on #4222 (alert-notebook MVP): the notebook must be LIVE, not frozen, and the operator needs a shell-level play/pause control for the 60s auto-refresh — usable on every page, not just the alert-notebook view. Before this change, the refresh loop in app.js only paused automatically while the browser tab was hidden; there was no way for an operator to stop it on a visible tab (for example, while reading a notebook mid-incident) short of closing the tab.

What changes

  • Shell chrome: a real <button id="auto-refresh-toggle"> added to the sidebar's brand block in index.html, so it renders once and survives every route change (it lives outside #main, which every page render replaces).
  • app.js:
    • initAutoRefreshToggle() wires the button, sets its label/aria-label/title to "Pause auto-refresh" / "Resume auto-refresh", and toggles aria-pressed.
    • State persists under the darling.autoRefreshPaused localStorage key (isAutoRefreshPaused/setAutoRefreshPaused), so it survives a reload or navigation.
    • Both poll paths — the 60s setInterval tick and the visibilitychange handler — check !isAutoRefreshPaused() in addition to the existing !document.hidden check. The existing hidden-tab pause is unchanged; the new control is an independent gate on top of it.
    • Resuming (clicking the button while paused) runs one refresh() immediately, rather than waiting out whatever is left of the 60s window.
    • refresh()'s existing poll-skip guard (editor/notebookEditor/alertEditor routes) now also skips #/triage — the alert-notebook deep-link landing page. The fix-shape draft's cost item said the periodic tick must not re-render triage every 60s; this reuses the exact same guard line the composer routes already use, computed before the sidebar/view-list/AG-nav reads start their own tick. Nothing else about the triage page changed.
  • app.css: a small pill-style button (.auto-refresh-toggle) using the existing theme variables (--muted, --accent, --border, --fg); no new colors introduced.
  • Test: Darling.Tests/WebFetchLayerTests.cs gets three new source pins (this repo has no JS test runner, so these are text-scan pins over the shipped module, same pattern as the existing AppJs_RefreshSkips... tests):
    • AppJs_RefreshSkipsTriageRouteToo — pins that routeName === "triage" is in the guard and runs before this tick's own reads start.
    • AppJs_HasAShellLevelAutoRefreshPauseThatGatesBothPollPaths — pins the localStorage key, the toggle functions, and that BOTH poll paths (interval + visibilitychange) check the paused flag, not just document.hidden.
    • IndexHtml_HasTheAutoRefreshToggleButtonInTheShellChrome — pins the button markup lives in the shell chrome.

Not in this slice: the /api/alert-notebook endpoint, the notebook read cell type, and views.js are other #4222 lanes' files and were not touched. #4191 (aborting superseded reads) is not implemented here; the new pause/resume gate is orthogonal to that later re-entrancy guard and does not block it.

Test plan

  • dotnet build Darling/Darling.Tests/Darling.Tests.csproj -p:EnableWindowsTargeting=true — 0 warnings, 0 errors (macOS, cross-compiled; Darling.Tests targets net10.0-windows and cannot run here — CI decides the full class).
  • dotnet build Lite.Tests/Lite.Tests.csproj -p:EnableWindowsTargeting=true — 0 warnings, 0 errors (untouched by this change; built to confirm nothing else broke).
  • WebFetchLayerTests (new pins) — CI decides.
  • Full Windows test suite — CI decides.

Lite parity: N/A. This is Darling web viewer only; Lite is the WPF desktop app and has no browser tab or localStorage.

CHANGELOG entry

SECTION: Added
ENTRY:

For the coordinator

Refs #4222.

The web viewer's 60s refresh loop only paused while a tab was hidden.
Add a real button in the shell chrome, usable on every page, that lets
the operator pause/resume the tick directly. State persists in
localStorage; resuming runs one refresh immediately. Also add the
#/triage route (the alert-notebook deep link landing page) to the
existing poll skip guard so the periodic tick does not re-render it.
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.

1 participant