Repository navigation
fix(docker): blank page on re-navigation, check-updates survival, cache busting - #18
Merged
Merged
Conversation
…he busting The /Docker page could fail to load (entirely blank — no toolbar, no skeleton) when navigating away and back, and a "check for updates" run started before navigating gave no feedback after returning. Root causes and fixes: - Mount-point race: on the newer Unraid web-component shell the legacy .page body (our #modernui-docker-root) can be injected a tick after our head-loaded bundle runs. boot() did a one-shot querySelector and bailed permanently if absent, leaving the page blank with no retry. Now waits for the mount point via a MutationObserver (10s cap) before bailing. - Check-for-updates didn't survive navigation: the run is a detached server-side worker (PID lock), but the "Checking…" UI was a per-instance flag that reset on reload. boot() now re-attaches to an in-flight run and resumes polling, so the badges refresh on completion as if uninterrupted. - Completion was silent (especially the "0 updates" case). Added a transient, dismissible result banner: "N updates available" / "All containers up to date" / failure note. Fires on both the normal and resumed paths. - Stale-bundle blank after updates: loader.js injected the page bundles with no cache-busting (though loader.js + modernui.css already used filemtime busting). A plugin update could serve a stale bundle until a hard refresh. install.php now appends ?v=<filemtime> to each injected bundle URL. Also adds gated debug logging (enable with ?dockerdebug=1) across the boot / resync / poll path plus a server-side transient-503 log line, to make this class of "fails to load" report diagnosable from the console. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ?dockerdebug=1 flag was persisted to localStorage, so once enabled it stayed on across every page load forever — surprising and noisy. Move it to sessionStorage: it still survives a same-tab navigate-away-and-back (the repro this logging is for), but clears when the tab closes. Also drop any leftover localStorage flag on load so previously-enabled sessions turn off. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The poll-check-updates tests gave the page a mock store without getState, so _announceCheckResult() (added with the result banner) threw a swallowed TypeError on every completion tick — the banner path ran in production but had zero test coverage and spewed misleading "status poll failed" noise. Add getState to the mock (parameterised by container list) and assert the banner: the "all up to date" case on the existing completion test, plus a new test for the pluralised "N updates available" count. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inch-high
added a commit
that referenced
this pull request
Jun 7, 2026
…tes survival Patch release of the PR #18 fix set (already merged to main): - /Docker no longer blanks on navigate-away-and-back (MutationObserver waits for the mount point instead of a one-shot querySelector that bailed). - A "check for updates" run survives navigation — boot() re-attaches to the in-flight detached worker and resumes polling. - New transient result banner reports the check outcome, including "0 updates". - install.php cache-busts the injected page bundles (?v=<filemtime>). - Gated debug logging (?dockerdebug=1) across boot/resync/poll. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the /Docker page failing to load when navigating away and back — especially while an update or "check for updates" is running — plus related UX gaps surfaced while debugging.
Originated from a report: "It fails to load when updates are running or it's checking for updates and you navigate away and back again." The visible symptom was a completely blank page (no toolbar, no skeleton), which turned out to be a mount-point race rather than the data-fetch path.
Changes
Blank page on re-navigation (
boot.ts) — On the newer Unraid web-component shell, the legacy.pagebody (our#modernui-docker-root) can be injected a tick after our head-loaded bundle executes.boot()did a one-shotquerySelectorand bailed permanently if the root was absent, leaving the page blank with no retry. Now waits for the mount point via aMutationObserver(10s cap) before giving up.Check-for-updates survives navigation (
md-docker-page.ts,boot.ts) — The run is a detached server-side worker (PID lock), but the "Checking…" UI was a per-instance flag that reset on reload.boot()now re-attaches to an in-flight run (resumeCheckForUpdatesIfRunning) and resumes polling, so badges refresh on completion as if uninterrupted.Completion banner (
md-docker-page.ts) — Completion was silent, especially the "0 updates" case. Added a transient, dismissible result banner: N updates available / All containers up to date / failure note. Fires on both the normal and resumed paths. Unit-tested via the real poll loop (poll-check-updates.test.ts).Cache-busting (
install.php) —loader.jsinjected the page bundles with no cache-busting (even thoughloader.js+modernui.cssalready used filemtime busting), so a plugin update could serve a stale bundle until a hard refresh. Now appends?v=<filemtime>to each injected bundle URL.Gated debug logging (
debug.ts,actions.ts,boot.ts,md-docker-page.ts,docker-state.php) — Off by default; enable with?dockerdebug=1(or themodernui-docker-debugsessionStorage key — per-session, cleared when the tab closes). Timestamped trace across boot / resync / poll, aSnapshotErrorcarrying the HTTP status (distinguishes the transient 503), and a server-side transient-503 log line. This is what made the root cause diagnosable from the console; kept in because it's inert unless enabled.Testing
npx vitest run tests/unit-ts/docker— 117 passed (adds 1 test covering the completion banner)biome ci src— cleanphp -l+ php-cs-fixer — cleanloader.jscarries?v=<mtime>on every bundle.Note:
tests/unit-php/save-docker-autostart.test.phpfails on this branch, but it fails identically onmain(pre-existing, unrelated to these changes).Notes
No version bump / release tag in this PR — it's the fix set only. Debug logging is left in (gated). Happy to strip it or cut a release as a follow-up.
🤖 Generated with Claude Code