Releases: Inch-high/Unraid-Reskin
Releases · Inch-high/Unraid-Reskin
Release list
v0.8.6
###v0.8.6 (2026-06-07)
- Fix (docker): the
/Dockerpage no longer renders completely blank (no toolbar, no skeleton) when you navigate away and back — especially while a container update or a "check for updates" run is in flight. On the newer Unraid web-component shell the legacy.pagebody (our mount point) can be injected a tick after our head-loaded bundle runs;boot()did a one-shotquerySelectorand bailed permanently when the root was absent. It now waits for the mount point via aMutationObserver(10s cap) before giving up. - Fix (docker): a "check for updates" run now survives navigation. The run is a detached server-side worker (PID lock), but the "Checking…" UI was a per-instance flag that reset on reload, so returning to the page looked idle while the worker kept walking the registry.
boot()re-attaches to an in-flight run and resumes polling, so the update badges refresh on completion as if uninterrupted. - Feat (docker): a transient, dismissible banner now reports the result of a completed update check — N updates available / All containers up to date / a failure note — including the previously-silent "0 updates" case. Fires on both the normal and resumed paths.
- Fix (docker):
install.phpnow appends?v=<filemtime>to each injected page bundle URL, matching the cache-busting already applied toloader.js+modernui.css. A plugin update could otherwise serve a stale bundle until a hard refresh (the classic blank-page-after-upgrade). - Chore (docker): added gated debug logging (off by default; enable with
?dockerdebug=1, a per-session sessionStorage flag) 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. Inert unless enabled. 117 TS docker suites green.
v0.8.5
###v0.8.5 (2026-06-02)
- Fix (docker): stop
/Dockerfrom blanking — and stop a stale "update available" badge — while a container update is in flight. During the stockupdate_containerflow's rewrite of thewebui-infodocker.json,getAllInfo()momentarily returns an empty list (still HTTP 200), which overwrote the populated store with nothing and poisoned the per-tab snapshot cache, leaving the page blank across refreshes until the update finished.docker-state.phpnow cross-checksgetAllInfo()againstgetDockerContainers()(the docker socket, unaffected by the rewrite) and responds503when the daemon still lists containers but the cache reads empty; the client keeps its current rows and retries on the next resync instead of clobbering them. A genuinely empty server (every container deleted) still returns[]and renders the empty state — fixing the inverse "ghost rows after delete-all" bug the first client-side guard introduced. No extra docker calls: both sources were already fetched on every load. - Fix (docker): clear the freshly-updated "update available" badge without a manual reload. The
_DONE_handler now resyncs before clearing the update probes, so the id-rotation reconcile (the definitive "pull succeeded, container recreated" signal) can force-clear the badge over Unraid's lagging digest cache while the probe still exists; clearing first left reconcile nothing to match and the stale badge persisted. Newdocker-state.test.phpfor the transient-empty disambiguation plusboot.ts/store.tsordering coverage; 116 TS + PHP suites green.
v0.8.4
###v0.8.4 (2026-06-01)
- Chore (version): make
package.jsonthe single source of truth for the plugin version so it can no longer drift across files. The front-end reads it via a Vitedefine(src/ts/version.ts), render-time PHP pages read a build-emittedversionfile (modernui_plugin_version()), and a newnpm run version:checkguard — wired into CI and release — fails the build ifpackage.json,package-lock.json, and the.plg<!ENTITY version>disagree. - Fix (settings): the Settings → Theme "About" footer and the shell user-menu now show the real plugin version instead of stale hardcoded literals (
v0.7.0 (Phase 7)/v0.4.2), and the user-menu's GitHub link points at the real repo. - Docs: README gains a screenshot tour of the rebuilt surfaces (Dashboard, Main, Docker folder/tag management).
v0.8.3
###v0.8.3 (2026-06-01)
- Fix (docker): keep the
/Docker"Check for updates" button honest. The status poll cleared the "Checking…" state on its very first 2s tick — areturninside thetryfell through to afinallythat reset the flag — so on a 40+ container host the button flipped back to idle almost immediately while the real per-image registry walk was still running, making the check look instant and out of sync with the container count. The poll now only concludes once the worker has genuinely completed (it has observedrunning:true, or afinishedAtnewer than a pre-launch baseline has landed), so the button stays active for the full walk and the snapshot is re-fetched only after the worker rewrites thewebui-infocache — every container's update badge reflects the fresh check. - Fix (docker): the 60s poll limit was a hard total-runtime cap, shorter than a real 40+ container walk, so it could cut the post-check snapshot refresh off mid-walk and read stale
updatedflags. It is now an inactivity watchdog, reset on every observedrunning:true, so a provably-alive worker runs as long as it needs while a worker that never establishes (or wedges) its lock still bails. NewcheckUpdatesCompleted()pure helper covers the decision; +5 unit cases. 456 TS suites green; backend untouched (verified correct against the stockgetAllInfo/reloadUpdateStatuspath on a live host).
v0.8.2
###v0.8.2 (2026-05-31)
- Fix (docker): repair the
/Docker"check for updates" pipeline end-to-end. The detached worker had been silently failing on every run — itrequiredDockerClient.phpfrom inside the worker function, scoping that file's top-level$dockerManPathsas a function-local, sogetAllInfo()'sglobal $dockerManPathssaw null and threw "Path must not be empty" before writing anything. The docker stack is now bootstrapped at FILE scope in the CLI dispatch block (matchingdocker-state.php), and the worker callsgetAllInfo($reload=true)instead ofreloadUpdateStatus()directly so it rewrites the per-containerwebui-infocache (theupdatedfield the snapshot reads) in the same pass — update badges now actually surface. - Fix (docker): clear a stuck "Update available" badge after a successful update. Unraid's
unraid-update-status.jsoncan keep the pre-update local digest andreloadUpdateStatus()reuses it, so the badge could persist forever. When an update probe completes via container id rotation (the definitive sign the pull succeeded and the container was recreated), the modern store now force-clearsupdateAvailableinstead of trusting the stale shared cache; a genuine future update re-surfaces normally. - Perf (docker): new stale-while-revalidate snapshot cache (
sessionStorage, 10-min TTL, per-tab) so/Dockerpaints real rows instantly on navigation instead of a loading state, then revalidates against the server and overwrites. Verified live on an Unraid host. 451 TS + 13 PHP suites green.
v0.8.1
###v0.8.1 (2026-05-31)
- Fix (dashboard): disk rows in the Array and Cache cards now align their state / temp / SMART / progress / percentage columns across mixed active and standby rows. The disk list owns the grid column tracks and each row is a subgrid spanning them, instead of every row sizing its own
autocolumns independently (which let active rows with a temp + SMART glyph drift out of alignment from standby rows with "—" placeholders). - Fix (docker): the update/remove confirmation dialogs now use a styled
md-docker-confirm-modal(matching the drive-info / folder / tag modal family) in place of the nativewindow.confirm(). Destructive (remove) confirms focus Cancel so a stray Enter can't trigger a removal; primary (update) confirms keep action-button autofocus to mirror native behaviour; and an open confirm resolves cleanly if the page is torn down mid-prompt. +md-docker-confirm-modalunit coverage (confirm/cancel/backdrop/Escape resolution, listener cleanup, tone-based focus). 450 TS + PHP suites green.
v0.8.0
###v0.8.0 (2026-05-31)
- Feat (main): click any device tile on
/Mainto open a reskinned drive-info modal with five tabs — Health (SMART pass/fail verdict, temperature, power-on hours/cycles, capacity, identity), Attributes (ATA SMART table with failing/key attributes flagged, NVMe health log, SCSI counters), Self-test (run short/extended, live progress, abort, history log), Errors (array read-errors + disabled/unmountable reason + SMART error log), and Settings (spin-down delay + warning/critical temperature + SMART notification thresholds). The drive-name link still opens the stock/Main/Devicepage as an escape hatch. - Feat (main): new read-only
main-smart.phprunssmartctl --jsonto source the SMART data. It is deliberately a SEPARATE file frommain-state.php(whose zero-shell CI invariant is untouched), resolves the/devnode fromdisks.inirather than client input,escapeshellargs every token, and passes-n standbyso opening the panel never spins up a sleeping disk — it offers an explicit "wake & read" instead. The self-test trigger (short/extended/abort) validatescsrf_tokenagainstvar.ini; a new CI guard asserts the file may only ever invoke/usr/sbin/smartctl. Spin-down delay and SMART threshold writes reuse the stock/update.htm+/update.phpendpoints — no new privileged writes. - Feat (main): the Array Operation panel's Parity / Disks / System detail now sits behind a default-collapsed "Array details" disclosure to keep the top of the page compact; the array state + Start/Stop control and the capacity hero stay visible.
- Tests: +
main-smart.test.php(device-node resolution / controller-type arg escaping / smartctl-JSON normalization incl. NVMe, failing-disk, standby, exit-code bitmask, defensive parsing) + drive-info action-builder coverage. 442 TS + 13 PHP suites green.
v0.7.0
###v0.7.0 (2026-05-31)
- Feat (main): the
/Maindevice list is now a responsive grid of compact disk tiles instead of a wide row table. Each tile shows the device type (HDD / SSD / NVMe / USB icon), name + model, online/standby state, used-of-total with a utilization bar or radial ring, and a temp / SMART / errors footer — every critical fact survives, the horizontal scroll does not. An array capacity hero (used/free + parity protection + healthy count) tops the page, with a per-device state LED strip on the Array group.deviceTypeis derived server-side inmain-state.php(nvme by kernel name, usb for the flash device, the rotational flag for SSD vs HDD). - Feat (main): one-click Bar / Ring toggle in the
/Mainheader switches how every disk's usage is drawn and persists per-install — written via the stock save endpoint and restored with no flash on reload. Replaces the old full-width 11-column device rows; backend, nchan live updates, and the Array Operation panel are unchanged. - CI/Tests: the PHP suite now runs in both the per-PR CI and the release workflow (setup-php 8.2, matching Unraid 7.x) so the server-side endpoints are gated, not just the dev box. Added device-tile / capacity-hero / page-util coverage and made
modernui_map_device_type's sysfs base injectable so the rotational→SSD branch is unit-tested; the Bar/Ring persist POST prefers the snapshot's authoritative CSRF token. 439 TS + PHP suites green.
v0.6.1
###v0.6.1 (2026-05-30)
- Security (main):
main-state.phpno longer emits the per-boot CSRF token in its read-only JSON snapshot. The token is delivered solely via the#modernui-main-rootdata-csrf attribute (htmlspecialchars-escaped), which the front-end already treats as authoritative — keeping it out of a readable response body (data minimization / defense-in-depth). No functional change: action POSTs still read the token from the attribute. - Fix (main): Unassigned Devices "Historical (previous) devices" detection now compares serials exactly instead of with a loose bidirectional substring test. A previously-seen device whose serial happens to be a substring of an attached disk's serial (or vice-versa) is no longer wrongly treated as present and hidden from the Historical list.
v0.5.8
###v0.5.8 (2026-05-30)
- Feat (docker): floating top-right update-progress panel (
<md-docker-update-panel>) that surfaces in-flight container updates — name + overall % + download speed. Subscribes to the/sub/dockernchan channel stock Unraid'supdate_containerscript publishes to and parses its NUL-delimited protocol. Overall % is byte-weighted across layers (downloaded ÷ total), which stays monotonic where a raw per-layer mean would lurch backwards as fresh layers join at 0%; chunked layers with no declared total are excluded from the % but still feed the byte/speed totals. Download speed is inferred from a rolling 2.5s byte-rate window since the stock script doesn't emit it. State persists tosessionStorage(writes throttled to ≤1/750ms so a multi-layer pull doesn't storm the main thread; 5-min TTL matching the updating watchdog) so navigating away from /Docker and back doesn't blank the panel mid-update. The script's_DONE_end-of-batch marker force-clears the updating set + refetches, bypassing the 5-min watchdog when stock's digest-status cache lags reconcile detection. - Feat (docker): "Update all (N)" action in the toolbar when updates are available and nothing's selected — one click pulls + recreates every container with an available update, saving the user from expanding collapsed folders to tick each one. Soft-accent styling keeps it subordinate to the primary Add Container CTA.
- Fix (docker): the folder-default Expanded/Collapsed segmented control flipped manually-toggled folders to the OPPOSITE of the user's intent — explicit per-folder toggles are stored as "flip the default", so changing the default inverted every override. New
setCollapseAll()clears the per-folder overrides so the new default applies uniformly; boot-time hydration still preserves them. - Fix (docker): the row + tag-modal checkbox tick rendered low-and-right of center. The rotated-rectangle
::afterhad abox-sizing: content-boxborder-inflation bug (the 5×9 rect was really 7×11) and the L-shape's pixel mass lands off the rotation pivot. Swapped for a mathematically centered, sharper inline-SVG check. - CI: new GitHub Actions workflow runs the TS test suite + asset build on every pull request and push to main, so regressions are caught before merge instead of at release-tag time.
- Tests: +parser / sessionStorage round-trip / TTL expiry /
_DONE_callback / chunked-advance / byte-weighted % /setCollapseAll/clearAllUpdating/selectPanelViewcoverage. 349 total, all green.