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 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.
// 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

View file

@ -69,8 +69,19 @@
// scopeDropTarget: cascade's drop_target at currentPath
// scopeDefaultTool: cascade's default_tool at currentPath
// (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,
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
// don't match and folders whose subtree has no matches.

View file

@ -11,10 +11,12 @@
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) {
var i = name.lastIndexOf('.');
if (i <= 0 || i === name.length - 1) return '';
return name.substring(i + 1).toLowerCase();
return window.zddc.splitExtension(name).extension;
}
// Build a raw entry from the server's FileInfo shape.
@ -222,7 +224,6 @@
fetchServerChildren: fetchServerChildren,
fetchFsChildren: fetchFsChildren,
autoDetectServerMode: autoDetectServerMode,
splitExt: splitExt,
ensureJSZip: ensureJSZip
};
})();

View file

@ -460,10 +460,6 @@
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
// can't be fetched as a standalone server resource: we read them
// through the containing handle (offline / nested) or by fetching
@ -690,15 +686,6 @@
loadChildren: loadChildren,
snapshotState: snapshotState,
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).
// Used by the toolbar's sort dropdown.
setSortExplicit: function (key, dir) {

View file

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