Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion archive/folderview.plus-2026.04.04.18.txz.sha256

This file was deleted.

1 change: 0 additions & 1 deletion archive/folderview.plus-2026.04.04.19.txz.sha256

This file was deleted.

1 change: 0 additions & 1 deletion archive/folderview.plus-2026.04.04.21.txz.sha256

This file was deleted.

1 change: 0 additions & 1 deletion archive/folderview.plus-2026.04.04.22.txz.sha256

This file was deleted.

Binary file modified archive/folderview.plus-2026.04.05.13.txz
Binary file not shown.
2 changes: 1 addition & 1 deletion archive/folderview.plus-2026.04.05.13.txz.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
fd666a1a845fda4412b6291235511896c9145ec207650165289c129ac7d51065 folderview.plus-2026.04.05.13.txz
0c11a3a4b88d277a780a4bbe305d0dce2e4bc36371d2bcfdff56d4b613cdf674 folderview.plus-2026.04.05.13.txz
Binary file not shown.
1 change: 1 addition & 0 deletions archive/folderview.plus-2026.04.05.14.txz.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c1355026951b4550af7c33c740a33754ba6d638f0cb29e6e043dbee1411eb33d folderview.plus-2026.04.05.14.txz
Binary file not shown.
1 change: 1 addition & 0 deletions archive/folderview.plus-2026.04.06.02.txz.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ccfec89a12588f5b0ae89508fa4f75cd6e0120964276d0f902f267335eab6ef7 folderview.plus-2026.04.06.02.txz
Binary file not shown.
1 change: 1 addition & 0 deletions archive/folderview.plus-2026.04.06.03.txz.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3ff8122e479e6962068ed7ad888d80d98d5f14fd3d231818f3ef35cfe4e7116b folderview.plus-2026.04.06.03.txz
Binary file not shown.
1 change: 1 addition & 0 deletions archive/folderview.plus-2026.04.06.04.txz.sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
b3d81601d5230e584fe16e87706833c006df502dbc67ccdc18195e574033f76f folderview.plus-2026.04.06.04.txz
14 changes: 14 additions & 0 deletions docs/releases/2026.04.06.04.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
This release includes the full cumulative delta since `v2026.04.05.13`.

### Runtime and Preview Fixes
- Stabilized Docker and VM runtime rows, folder state handling, and action refresh paths so status surfaces stay aligned during in-place actions.
- Fixed Docker preview cards, status icons, labels, and action buttons to live-refresh after folder actions instead of showing stale started, paused, or stopped state.
- Ensured Docker preview click menus and native container menus resync runtime state before opening so context actions match the current container state.

### Diagnostics and Clarity
- Diagnostics health cards now call out the real Docker or VM integrity issue instead of falling back to generic folder, rule, or backup counts.
- Added targeted regression coverage for diagnostics summary rendering, orphaned-member reporting, and path-issue presentation.

### Quality and Release Hardening
- Expanded regression coverage around runtime refresh behavior and Docker preview state synchronization.
- Hardened CI, packaging, and main-to-dev release artifact reconciliation so stable release publishing and follow-up syncs stay reliable.
129 changes: 87 additions & 42 deletions folderview.plus.plg
Original file line number Diff line number Diff line change
Expand Up @@ -5,56 +5,101 @@
<!ENTITY github "alexphillips-dev/FolderView-Plus">
<!ENTITY launch "Settings/FolderViewPlus">
<!ENTITY plugdir "/usr/local/emhttp/plugins/&name;">
<!ENTITY pluginURL "https://raw.githubusercontent.com/&github;/main/folderview.plus.plg">
<!ENTITY version "2026.04.05.13">
<!ENTITY md5 "00b9d05e73769e5945b8d637dd710d6d">
<!ENTITY pluginURL "https://raw.githubusercontent.com/&github;/dev/folderview.plus.plg">
<!ENTITY version "2026.04.06.04">
<!ENTITY md5 "22f685ec46010ba4c5d51249fb9cbd51">
]>

<PLUGIN name="&name;" author="&author;" version="&version;" launch="&launch;" pluginURL="&pluginURL;" icon="folder-icon.png" support="https://forums.unraid.net/topic/197631-plugin-folderview-plus/" min="7.0.0">
<CHANGES>

###2026.04.06.04
- Fix: Diagnostics health cards now name the real Docker or VM integrity finding instead of falling back to generic folder, rule, and backup counts.
- Quality: Add contract coverage for orphaned-member and path-issue diagnostics summary rendering.


###2026.04.06.03
- Fix: Docker folder preview click menus now follow live container started, paused, and stopped state after folder actions.
- Fix: Default-context preview cards and stored member rows now resync runtime state classes before native container menus are opened.
- Quality: Added regression coverage for Docker preview state-surface synchronization.


###2026.04.06.02
- Fix: Docker folder preview rows now live-refresh container started, paused, and stopped state after in-place folder actions.
- Fix: Docker preview runtime sync now updates per-container status icons and labels alongside preview action buttons.
- Quality: Added regression coverage for in-place Docker preview status refresh.


###2026.04.05.14
- Fix: Docker runtime rows, folder state, and container interactions.
- Fix: VM runtime rows, folder state, and VM actions.
- Quality: Release automation, CI smoke coverage, and packaging guards.


###2026.04.05.13
- Feature: Added a compact `Bulk move` workflow directly to the Folder Editor `Members` tab for both Docker and VM folders, so users can move shown or included members into another folder without leaving the editor.
- Feature: Bulk move supports the scopes `Shown`, `Included shown`, `Excluded shown`, and `All included`.
- Feature: Bulk move reuses the guarded server-side bulk assignment path instead of duplicating a second editor-only mover.
- Feature: Each bulk move creates a backup first and exposes an editor-local undo path.
- Fix: Fixed multi-row Docker preview `Console` and `Logs` actions so they keep their real runtime wiring instead of falling back to a top-of-page anchor jump.
- Fix: Fixed Folder Editor startup crashes introduced by the new Members-tab bulk move flow when hydration reached the bulk move helpers before those functions finished initializing.
- Fix: Fixed the Folder Editor post-bulk-move lockup so the page no longer gets trapped behind a blocking success or undo modal after the move completes.
- Fix: Fixed Members-tab bulk move live refresh so moved Docker containers and VMs disappear from the current folder immediately instead of remaining visible until the folder is submitted or reloaded.
- Fix: Fixed the leave-page warning after a successful Members-tab bulk move by syncing the member baseline correctly, while keeping the normal unsaved-changes prompt for regular manual member edits.
- UX: The Members-tab bulk move flow now keeps the editor live after completion and shows a non-blocking inline undo action inside the bulk move summary area.
- UX: Folder Editor bulk move status messaging now updates in place instead of interrupting the editor with follow-up confirmation dialogs.
- Compatibility: Added versioned asset URLs for shipped FolderView Plus JavaScript, CSS, vendor includes, and locale assets so plugin updates no longer depend on users manually clearing browser cache to see new changes.
- Quality: Hardened the main release process so stable cuts now require explicit curated release notes instead of falling back to generic seeded `CHANGES` text.
- Quality: Added a local `simulate_main_release.sh` path so the full stable-release flow can be rehearsed before merging and pushing `main`.
- Quality: Unified stable packaging through the shared `release_prepare.sh` entrypoint so the local and GitHub release flows use the same preparation path.
- Quality: Hardened back-merge handling so release-only artifacts and stable-only metadata do not keep breaking the `main` to `dev` sync path.
- Quality: Tightened workflow self-checks, release-note consistency validation, include-order coverage, and related release/package guards around the new release path.
- Quality: Release runs no longer hard-require browser smoke or theme matrix URLs, so stable merges can proceed even when smoke targets are unavailable.
- Quality: Remote publish validation now retries until raw GitHub artifacts reflect the pushed release, preventing false failures from raw cache lag.
- Quality: Back-merge restores now skip missing release-only paths cleanly, preventing archive rename conflicts from failing automation.
- UX: Settings workspace layout, section flows, and table behavior.
- Quality: Release automation, CI smoke coverage, and packaging guards.


###2026.04.05.12
- UX: Folder editor flows, previews, and bootstrap behavior.


###2026.04.05.11
- Fix: Folder editor Members-tab bulk move now removes reassigned Docker containers and VMs from the live member list immediately instead of keeping them visible until the editor is submitted or reloaded.


###2026.04.05.10
- UX: Folder editor flows, previews, and bootstrap behavior.


###2026.04.05.09
- Quality: Release automation, CI smoke coverage, and packaging guards.
- Docs: Project documentation and support guidance.


###2026.04.05.08
- UX: Folder editor flows, previews, and bootstrap behavior.


###2026.04.05.07
- Fix: Folder editor startup no longer crashes on bulk-move-enabled builds when hydration reaches the current scope and target helpers before those Members-tab bulk move utilities finish initializing.


###2026.04.05.06
- UX: Folder editor flows, previews, and bootstrap behavior.


###2026.04.05.05
- Fix: Folder editor startup no longer crashes on bulk-move-enabled builds when hydration updates Members-tab bulk move UI before the scope collector finishes initializing.


###2026.04.05.04
- UX: Folder editor flows, previews, and bootstrap behavior.
- UX: Settings workspace layout, section flows, and table behavior.
- Refactor: Shared runtime contracts, request plumbing, and cross-page foundations.
- Quality: Release automation, CI smoke coverage, and packaging guards.


###2026.04.05.03
- Fix: Multi-row Docker preview Console and Logs buttons now keep their action wiring after compact preview rendering, so they open the terminal and logs instead of falling back to a top-of-page anchor jump.


###2026.04.05.02
- Fix: Release validation now recognizes locale keys referenced through shared i18n wrappers, preventing false failures in the language-usage guard.
- Fix: Manual Release On Main dispatches now force the publish path correctly so failed stable releases can be retried without editing workflow files again.
- Fix: Removed dead selector leftovers from Docker, Folder Editor, and Settings styles so strict dead-code validation passes cleanly during stable release publishing.
- Quality: Rebuilt the stable package and archive metadata for the April 5, 2026 release cut so GitHub release automation publishes a fully synchronized main-channel artifact set.

###2026.04.04.30
- Feature: Added Copy Folder Settings and Paste Folder Settings to Docker and VM folder menus, plus Apply to folders in the editor to batch-apply the current folder configuration to existing folders without changing names, parents, members, regex, or ids.
- Feature: Rebuilt the support bundle as v2 with structured troubleshooting sections, sanitized redaction manifests, export preview, build identity, loaded assets, recent actions, browser error snapshots, and richer plugin-specific diagnostics.
- UX: Retired the legacy folder editor and moved fully to the modern editor with major improvements to parent selection, icon workflows, live preview, rules, diagnostics, and light-theme editor surfaces.
- UX: Polished the folder editor and settings UI across parent picker, icon picker, diagnostics workbench, dashboard layouts, and chevron/dropdown chrome for dark and light themes.
- Fix: Docker update detection now stays aligned with native Unraid update state for containers, folders, root folders, and folder-editor update summaries.
- Fix: Multi-row Docker previews now open the normal container menu from visible preview cards again while keeping WebUI, Console, and Logs quick actions separate.
- Fix: Theme-token coverage was expanded across runtime menus, dialogs, diagnostics, icon surfaces, parent-picker surfaces, and folder/status tokens to eliminate remaining hardcoded dark-mode regressions.
- Fix: Diagnostics, issue reports, and support exports now report theme/runtime state correctly, sanitize sensitive fields in sanitized mode, and include the client/server context needed for support.
- Fix: Docker order sync now runs only when folder membership or order inputs change, uses lightweight runtime state, coalesces concurrent sync requests, and avoids rewriting unchanged Docker order/autostart files.
- Refactor: Split major monoliths across settings, folder editor, Docker runtime, and server helper modules so the main runtimes act as coordinators instead of carrying most implementation details directly.
- Quality: Removed dead runtime code, tightened unused-code guards, expanded regression coverage, and strengthened include-order, performance-budget, install-smoke, and release validation.
- Quality: Hardened release automation with stronger smoke-test enforcement and subsystem-aware release-note generation so stable releases reflect the actual promoted work.
- Fix: Docker runtime rows, folder state, and container interactions.
- Fix: VM runtime rows, folder state, and VM actions.
- UX: Dashboard layouts, quick rails, and folder card interactions.
- UX: Folder editor flows, previews, and bootstrap behavior.
- UX: Settings workspace layout, section flows, and table behavior.
- Fix: Server endpoints, runtime payloads, and persistence or validation paths.


###2026.04.05.01
- Fix: Docker runtime rows, folder state, and container interactions.
- UX: Folder editor flows, previews, and bootstrap behavior.
- UX: Settings workspace layout, section flows, and table behavior.
- Quality: Release automation, CI smoke coverage, and packaging guards.
- Docs: Project documentation and support guidance.


###2026.04.04.29
Expand Down Expand Up @@ -4925,7 +4970,7 @@
</CHANGES>

<FILE Name="/boot/config/plugins/&name;/&name;-&version;.txz" Run="upgradepkg --install-new">
<URL>https://raw.githubusercontent.com/&github;/main/archive/&name;-&version;.txz</URL>
<URL>https://raw.githubusercontent.com/&github;/dev/archive/&name;-&version;.txz</URL>
<MD5>&md5;</MD5>
</FILE>

Expand Down
2 changes: 1 addition & 1 deletion folderview.plus.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Description>
FolderView Plus organizes Docker, VM, and Dashboard views into folders in Unraid, with starter setup tools, rules, bulk assignment, recovery, templates, and diagnostics.
</Description>
<Date>2026-04-05</Date>
<Date>2026-04-06</Date>
<MinVer>7.0.0</MinVer>
<ExtraSearchTerms>folder view docker vm dashboard organization groups sorting import export backup recovery rules templates diagnostics</ExtraSearchTerms>
<Support>https://forums.unraid.net/topic/197631-plugin-folderview-plus/</Support>
Expand Down
26 changes: 13 additions & 13 deletions scripts/perf_baseline.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": 1,
"generatedAt": "2026-04-05T18:00:10.161Z",
"generatedAt": "2026-04-06T02:05:39.171Z",
"notes": "Baseline for perf ratchet guard. Update intentionally when expected growth is accepted.",
"assets": {
"scripts/folderviewplus.runtime-parity.js": {
Expand Down Expand Up @@ -40,8 +40,8 @@
"gzipBytes": 14264
},
"scripts/folderviewplus.settings-tree.js": {
"bytes": 23018,
"gzipBytes": 4645
"bytes": 29142,
"gzipBytes": 5727
},
"scripts/folderviewplus.folder-editor.js": {
"bytes": 39957,
Expand All @@ -68,8 +68,8 @@
"gzipBytes": 5528
},
"scripts/folderviewplus.js": {
"bytes": 376325,
"gzipBytes": 70170
"bytes": 376346,
"gzipBytes": 70192
},
"scripts/folderviewplus.wizard.js": {
"bytes": 219026,
Expand Down Expand Up @@ -108,16 +108,16 @@
"gzipBytes": 16527
},
"scripts/folder.js": {
"bytes": 213832,
"gzipBytes": 44359
"bytes": 215435,
"gzipBytes": 44656
}
},
"totals": {
"totalJs": 2549779,
"totalCss": 378935,
"totalJsGzip": 493899,
"totalCssGzip": 50689,
"settingsRuntimeJs": 1043130,
"settingsRuntimeJsGzip": 196991
"totalJs": 2557527,
"totalCss": 379472,
"totalJsGzip": 495300,
"totalCssGzip": 50751,
"settingsRuntimeJs": 1049275,
"settingsRuntimeJsGzip": 198095
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ const getDockerRuntimeActionsApi = () => {
runDockerGuardedAction: (actionName, action, context = {}) =>
runDockerGuardedAction(actionName, action, context),
getDockerMenuLabel: (key, fallback) => getDockerMenuLabel(key, fallback),
refreshDockerRuntimeState: (options = {}) => refreshDockerRuntimeStateInPlace(options),
loadlist: () => loadlist(),
eventURL,
debugEnabled: FOLDER_VIEW_DEBUG_MODE,
Expand Down Expand Up @@ -4402,7 +4403,6 @@ const folderCustomAction = async (id, actionIndex) => {
if (!folder || !folder.actions || !folder.actions[actionIndex]) {
if (FOLDER_VIEW_DEBUG_MODE) console.error(`[FV3_DEBUG] folderCustomAction: Folder or action definition not found for id ${id}, actionIndex ${actionIndex}.`);
$('div.spinner.fixed').hide('slow');
loadlist();
return;
}
let act = folder.actions[actionIndex];
Expand Down Expand Up @@ -4521,9 +4521,12 @@ const folderCustomAction = async (id, actionIndex) => {

if (FOLDER_VIEW_DEBUG_MODE) console.log(`[FV3_DEBUG] folderCustomAction (id: ${id}): Awaiting ${prom.length} promises for custom action.`);
await Promise.all(prom);
if (FOLDER_VIEW_DEBUG_MODE) console.log(`[FV3_DEBUG] folderCustomAction (id: ${id}): All promises resolved. Reloading list.`);

loadlist();
if (FOLDER_VIEW_DEBUG_MODE) console.log(`[FV3_DEBUG] folderCustomAction (id: ${id}): All promises resolved. Refreshing runtime state.`);
if (act.type === 0) {
await refreshDockerRuntimeStateInPlace({ followupDelayMs: 650 });
} else {
loadlist();
}
$('div.spinner.fixed').hide('slow');
if (FOLDER_VIEW_DEBUG_MODE) console.log(`[FV3_DEBUG] folderCustomAction (id: ${id}): Exit.`);
};
Expand Down Expand Up @@ -5232,6 +5235,39 @@ const fetchDockerStateSignature = async () => {
return buildDockerStateSignature(parsed, true);
};

const refreshDockerRuntimeStateInPlace = async (options = {}) => {
const followupDelayMs = Math.max(0, Number(options?.followupDelayMs) || 0);
const fallbackToLoadlist = () => {
queueLoadlistRefresh({ suppressLoadingUi: true });
};
const applyStatePayload = async () => {
const payload = await $.get(buildDockerRuntimeInfoUrl('state')).promise();
const parsed = parseJsonPayloadSafe(payload);
if (!parsed || Object.keys(parsed).length <= 0) {
throw new Error('Docker runtime state payload was empty.');
}
dockerRuntimeInfoByName = normalizeDockerRuntimeInfoMap(parsed, dockerRuntimeInfoByName);
const nextSignature = buildDockerStateSignature(parsed, true);
if (nextSignature) {
lastLiveRefreshStateSignature = nextSignature;
}
syncDockerVisibleFoldersFromRuntimeCache();
return true;
};
try {
await applyStatePayload();
if (followupDelayMs > 0) {
window.setTimeout(() => {
Promise.resolve(applyStatePayload()).catch(() => fallbackToLoadlist());
}, followupDelayMs);
}
return true;
} catch (_error) {
fallbackToLoadlist();
return false;
}
};

const readDockerHostOrderFromDom = () => {
const order = [];
document.querySelectorAll('#docker_list > tr.sortable').forEach((row) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
? win.FolderViewPlusFolderSettingsTransfer.createApi({ window: win })
: null);
const refreshDockerList = typeof deps.loadlist === 'function' ? deps.loadlist : (() => {});
const refreshDockerRuntimeState = typeof deps.refreshDockerRuntimeState === 'function'
? deps.refreshDockerRuntimeState
: refreshDockerList;
const eventUrl = String(deps.eventURL || win?.eventURL || '').trim();
const debugEnabled = deps.debugEnabled === true;
const consoleRef = deps.console || win?.console || null;
Expand Down Expand Up @@ -977,10 +980,10 @@
type: 'error',
html: true,
confirmButtonText: 'Ok'
}, refreshDockerList);
}, () => refreshDockerRuntimeState({ followupDelayMs: 650 }));
} else {
debugLog(`[FV3_DEBUG] actionFolder (id: ${id}): No errors. Reloading list.`);
refreshDockerList();
debugLog(`[FV3_DEBUG] actionFolder (id: ${id}): No errors. Refreshing runtime state in place.`);
await Promise.resolve(refreshDockerRuntimeState({ followupDelayMs: 650 }));
}
} catch (error) {
if (consoleRef && typeof consoleRef.error === 'function') {
Expand Down
Loading
Loading