refactor(browse): remove dead code, document state shape

Pure cleanup, no behavior change:

- tree.js: drop the unused setSort() method (only setSortExplicit is wired,
  via the toolbar dropdown) and its doubly-stale comment (claimed there was
  no sort UI — there is).
- app.js: remove the augmentRoot/passThroughEntries identity stub. It was a
  leftover from when browse merged virtual canonical folders client-side;
  zddc-server emits them now and nothing reads window.app.modules.augmentRoot.
- loader.js: splitExt now delegates to window.zddc.splitExtension (identical
  behavior — lowercased, dotfile/trailing-dot → '') per the CLAUDE.md rule
  that extension handling goes through window.zddc; drop the unused export.
- upload.js: remove the dead `else if (refreshUrl)` comment-only branch (and
  the unused refreshUrl var) — refreshListing is always present since it was
  exported.
- init.js: declare scopeCanonicalFolder, scopeOnPlanReview, and showHidden in
  the state initializer. They were read/written across modules but never
  listed in the canonical state shape (implicit undefined).

All 6 browse Playwright specs pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-06-03 15:32:05 -05:00
parent b0d0ff13cd
commit b2c16063c4
5 changed files with 19 additions and 40 deletions

View file

@ -8,17 +8,6 @@
var tree = window.app.modules.tree; var tree = window.app.modules.tree;
var events = window.app.modules.events; var events = window.app.modules.events;
// Virtual canonical folder injection used to live here (browse
// appended archive/working/staging/reviewing entries at a project
// root when missing). zddc-server now emits them in the listing
// directly so the .zddc `display:` map can override their labels
// the same as real entries. This pass-through stub keeps the
// events.js rescope contract intact without doing any merging.
function passThroughEntries(entries) { return entries; }
// Expose for events.js's client-side rescope on dblclick.
window.app.modules.augmentRoot = passThroughEntries;
// Walk a `?file=` path segment-by-segment from the current root. // Walk a `?file=` path segment-by-segment from the current root.
// Each non-leaf segment is matched against the parent's children // Each non-leaf segment is matched against the parent's children
// by name; if found and it's a folder, expand+load it (so its // by name; if found and it's a folder, expand+load it (so its

View file

@ -69,8 +69,19 @@
// scopeDropTarget: cascade's drop_target at currentPath // scopeDropTarget: cascade's drop_target at currentPath
// scopeDefaultTool: cascade's default_tool at currentPath // scopeDefaultTool: cascade's default_tool at currentPath
// (empty when no default declared) // (empty when no default declared)
// scopeCanonicalFolder: cascade's canonical-folder slot
// ('incoming'|'received'|'working'|'staging'|…),
// drives scope-aware menu items
// scopeOnPlanReview: cascade above has an on_plan_review block
// All refreshed by loader.js from response headers on each fetch.
scopeDropTarget: false, scopeDropTarget: false,
scopeDefaultTool: '', scopeDefaultTool: '',
scopeCanonicalFolder: '',
scopeOnPlanReview: false,
// Whether the listing includes dotfiles. Toggled by the
// "Show hidden files" menu item; URL-persisted via ?hidden=1.
showHidden: false,
// Autofilter — when non-empty, the tree hides files that // Autofilter — when non-empty, the tree hides files that
// don't match and folders whose subtree has no matches. // don't match and folders whose subtree has no matches.

View file

@ -11,10 +11,12 @@
var state = window.app.state; var state = window.app.state;
// Lowercased extension (no leading dot), '' for dotfiles / no-ext /
// trailing-dot names. Delegates to the shared parser so the rule
// stays in one place (CLAUDE.md: all extension handling goes through
// window.zddc).
function splitExt(name) { function splitExt(name) {
var i = name.lastIndexOf('.'); return window.zddc.splitExtension(name).extension;
if (i <= 0 || i === name.length - 1) return '';
return name.substring(i + 1).toLowerCase();
} }
// Build a raw entry from the server's FileInfo shape. // Build a raw entry from the server's FileInfo shape.
@ -222,7 +224,6 @@
fetchServerChildren: fetchServerChildren, fetchServerChildren: fetchServerChildren,
fetchFsChildren: fetchFsChildren, fetchFsChildren: fetchFsChildren,
autoDetectServerMode: autoDetectServerMode, autoDetectServerMode: autoDetectServerMode,
splitExt: splitExt,
ensureJSZip: ensureJSZip ensureJSZip: ensureJSZip
}; };
})(); })();

View file

@ -460,10 +460,6 @@
el.innerHTML = html; el.innerHTML = html;
} }
// Sort headers no longer exist in the DOM (the tree replaced the
// table); the tree.setSort() method still works but only via
// programmatic callers — there's no UI for changing sort yet.
// True when this .zip node lives inside another zip, so its bytes // True when this .zip node lives inside another zip, so its bytes
// can't be fetched as a standalone server resource: we read them // can't be fetched as a standalone server resource: we read them
// through the containing handle (offline / nested) or by fetching // through the containing handle (offline / nested) or by fetching
@ -690,15 +686,6 @@
loadChildren: loadChildren, loadChildren: loadChildren,
snapshotState: snapshotState, snapshotState: snapshotState,
restoreState: restoreState, restoreState: restoreState,
setSort: function (key) {
if (state.sort.key === key) {
state.sort.dir = -state.sort.dir;
} else {
state.sort.key = key;
state.sort.dir = 1;
}
render();
},
// Set both key and direction explicitly. dir: 1 (asc) or -1 (desc). // Set both key and direction explicitly. dir: 1 (asc) or -1 (desc).
// Used by the toolbar's sort dropdown. // Used by the toolbar's sort dropdown.
setSortExplicit: function (key, dir) { setSortExplicit: function (key, dir) {

View file

@ -286,20 +286,11 @@
if (lastResolved) msg += ' — last at ' + lastResolved; if (lastResolved) msg += ' — last at ' + lastResolved;
note(msg, 'success'); note(msg, 'success');
} }
// Reload the listing of the workflow folder so the new +Cn file // Reload the current listing so the new +Cn file appears in the
// appears in the tree. The workflow folder is the parent of the // tree. Best-effort.
// virtual `received/` (i.e., the URL with one `/received/<file>`
// suffix stripped).
var refreshUrl = targetURL.replace(/\/received\/[^/]+\/?$/, '/');
try { try {
var ev = window.app.modules.events; var ev = window.app.modules.events;
if (ev && typeof ev.refreshListing === 'function') { if (ev && typeof ev.refreshListing === 'function') ev.refreshListing();
ev.refreshListing();
} else if (refreshUrl) {
// Best-effort fallback: re-navigate to the workflow folder
// so its listing is refreshed.
// (No action — refreshListing absence implies older browse.)
}
} catch (_e) { /* refresh is best-effort */ } } catch (_e) { /* refresh is best-effort */ }
} }