Skip to content

feat(web): the Display tab is an ES-module page, with a page-visibility service (stage 4) - #771

Merged
ChuckBuilds merged 2 commits into
mainfrom
feat/web-display-es-module
Oct 5, 2026
Merged

ChuckBuilds merged 2 commits into
mainfrom
feat/web-display-es-module

Conversation

@ChuckBuilds

Copy link
Copy Markdown
Owner

Step 8 of the web UI's ES-module migration (docs/WEB_FRONTEND_ARCHITECTURE.md): the Display tab, and the page-visibility service it needs first. Follows #767 (Schedule, General).

The visibility service: core/visibility.js

Each mounted page gets ctx.visibility. The registry has a new mountContext option, and boot.js uses it to bind one handle to each mount:

Member What it does
whileVisible(start, stop) start() when the page comes on screen (at once if it mounts on screen), stop() when it leaves. Returns an end function
every(ms, fn) fn() at once, then every ms while on screen. The interval is cleared while hidden and restarted, with an immediate fn(), when the page is back
isVisible() The page's tab is the active tab and the browser tab is visible

Everything a page registers ends when its ctx.signal aborts, after destroy(), so a swapped-out partial leaves no interval behind. The service reads the active tab from window.LEDVisibility (app-shell.js) at call time, so the page modules agree with the classic partials that still use it (Overview, Logs, Tools). Each registration gets its own key, so registrations never replace each other or a classic one. Without LEDVisibility, the browser tab's visibility alone decides. Moving the tracker itself out of app-shell.js is still the separate shell-service row.

The Display tab: pages/display.js

  • display.html loses its two inline scripts (292 lines), its onclick and its onchange. Its root is data-page="display".
  • The 5 s multi-display sync poll uses ctx.visibility.every(5000, ...). The status request and the scroll-speed hint go through ctx.api with ctx.signal. So does the Vegas order widget's plugin-list request.
  • The Advanced section's button is a delegated data-action="toggle-section" that calls the shared toggleSection. The settings form keeps its hx-on call to showSaveResult and its onsubmit call to fixInvalidNumberInputs, as Rotation's does.
  • window.updateSyncUI is a deprecated alias in boot.js.
  • The partial's escapeHtml and escapeAttr were never called, so they are dropped, along with their entry in test_html_escaping.js.

Behaviour differences

  • With sync on, opening the tab asks for the status once instead of twice: the old updateSyncUI() and the visibility start each polled. A Display tab that mounts while not on screen now waits until it is on screen before asking.
  • A login redirect during a poll no longer flashes "Sync status unavailable".
  • window.syncStatusInterval (the old timer id) is gone. Nothing read it.
  • When the partial is swapped out, a pending scroll-hint request or widget retry is dropped. The old poll did not leak: LEDVisibility replaced it by key when the script re-ran. It now also ends when the partial goes without being replaced.

Tests

  • New dom/test_visibility_service.js: real LEDVisibility from app-shell.js, the real registry, no server. It covers starting and stopping with the active tab and with browser-tab visibility, that no interval runs while hidden or after a swap-out, one interval after five swaps, registrations staying independent, a destroyed page registering nothing, a throwing start() being contained, and the fallback when LEDVisibility is absent.
  • New dom/test_display_page.js: the real partial, the real plugin-order-list widget, real LEDVisibility and real API shapes. After five swaps there is one page and one sync interval, and each control acts once. The poll runs only while the tab is on screen and never after a swap-out. Sync states and hostile names render as text. Failure and login answers, the debounced hint, the late widget and updateSyncUI are covered too.
  • unit/test_display_partial_ids.js now imports the module on a fake root that answers only for ids the partial renders. unit/test_page_registry.js covers mountContext. test_es_modules.py registers the page and its alias.
  • Mutation-checked. Each of these made the new suites fail:
    • aborting no longer ends registrations
    • every() no longer clears its interval
    • one key per page instead of one per registration
    • the page polls with a bare setInterval
    • the destroy and signal guards on the hint timer removed
    • a lookup of #brightness-display
    • the registry ignoring mountContext
    • the fallback ignoring document.hidden
    • a role change that does not poll
  • REQUIRE_DOM=1 node test/js/run_all.js: all 35 suites pass. python scripts/build_css.py --check: up to date.
  • Python (test/web_interface, web smoke and settings UI, partial save, display hardware, JS unit suites): the FAILED lists are identical on this branch and an origin/main baseline. Both have 11 failures, the existing Windows ones such as test_starlark_pixlet_routes.
  • Browser, real web interface on :5000:
    • The Display page mounts with no inline script.
    • The sync poll ran every 5 s with role Leader, stopped on another tab (0 requests in 11 s, no interval), polled at once on return, and stopped while the document was hidden.
    • The Advanced toggle worked, brightness and resolution followed their inputs, and Save stored the change.
    • updateSyncUI warned once and forwarded.
    • No console errors came from the new modules.

🤖 Generated with Claude Code

…ty service (stage 4)

- core/visibility.js: each page gets ctx.visibility (whileVisible, every,
  isVisible). Work registered there runs only while the page's tab is
  active and the browser tab visible, and ends when the page is swapped
  out. It reads the active tab from window.LEDVisibility, so it agrees
  with the classic partials. The registry gained a mountContext option for
  per-mount services.
- pages/display.js replaces display.html's two inline scripts. The 5 s
  sync status poll runs through ctx.visibility.every; the status and
  scroll-speed hint requests go through ctx.api with ctx.signal, as does
  the Vegas order widget's plugin-list request. The Advanced toggle is a
  delegated data-action; window.updateSyncUI is a deprecated alias.
- New DOM suites test_visibility_service.js and test_display_page.js;
  test_display_partial_ids.js imports the module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e83d9c03-4490-4cf0-85e1-951619fcde4c
📥 Commits

Reviewing files that changed from the base of the PR and between bb475a7 and 21baf76.

📒 Files selected for processing (15)
  • CHANGELOG.md
  • docs/WEB_FRONTEND_ARCHITECTURE.md
  • test/js/README.md
  • test/js/dom/test_display_page.js
  • test/js/dom/test_visibility_service.js
  • test/js/run_all.js
  • test/js/unit/test_display_partial_ids.js
  • test/js/unit/test_html_escaping.js
  • test/js/unit/test_page_registry.js
  • test/web_interface/test_es_modules.py
  • web_interface/static/v3/js/core/boot.js
  • web_interface/static/v3/js/core/registry.js
  • web_interface/static/v3/js/core/visibility.js
  • web_interface/static/v3/js/pages/display.js
  • web_interface/templates/v3/partials/display.html
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 150 complexity · 0 duplication

Metric Results
Complexity 150
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

…troy

Codacy's object-injection rule flagged v[id] and ctx.state[name].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ChuckBuilds
ChuckBuilds merged commit c20c0be into main Oct 5, 2026
15 checks passed
@ChuckBuilds
ChuckBuilds deleted the feat/web-display-es-module branch October 5, 2026 13:53
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