* refactor(web): split koolook_sidebar.js into 7 sidebar modules Pure mechanical split — zero behavior change. Implements the design from issue #49 (common-case layout with patchCanvasMenu extracted). Old: web/koolook_sidebar.js (1973 lines, monolithic) New: web/koolook_sidebar.js (48-line entry) + 7 modules in web/sidebar/ - constants.js (130) — REPOS, TAB_*, storage keys, event names, URLs, ensureStyle, toast, compareNames - picks_store.js (117) — localStorage user picks: load/save/add (tri-state) /remove/notify/seed/export - workflows_store.js (347) — workflowsCache + persistMutation + snapshotCache + commit + persist*/load*/seed* + in-memory ops; cache is module-private - canvas_io.js (192) — serialize*/canvasIsNonEmpty/loadWorkflowOntoCanvas /insertNode/getSelectedNodeTypes - modals.js (384) — makeModalShell + showInputModal/showConfirmModal /showSaveWorkflowModal/showContextMenu - canvas_menu.js (45) — patchCanvasMenu (idempotent LGraphCanvas patch) - tree.js (825) — pathStates (module-private) + gatherers + DOM row factories + buildFolder + workflow/dir context menus + rebuildTree + renderPanel Encapsulation invariants verified: - workflowsCache: zero references outside workflows_store.js - pathStates: zero references outside tree.js - All 8 files pass node --check - CSS string byte-identical to original - URL constants resolve to same targets after the extra `..` adjustment Documentation updated: dev-iteration-loop.md and workflows-sidebar.md now point pathStates references at web/sidebar/tree.js. Other doc references to koolook_sidebar.js as the entry remain accurate. Closes #49. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(web): drop unreachable defensive guard in gatherWorkflows Review feedback on #51: the `if (!dir) continue;` after `dirOf(dirName)` is unreachable — `listDirectoryNames()` enumerates the same module-private `workflowsCache.directories` keys that `dirOf()` reads, synchronously, within a single event-loop turn. Removing the guard restores strict "byte-identical move" semantics for the file-split refactor. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.6 KiB
3.6 KiB
Workflows sidebar — quick reference
The "Workflows" section of the Curated Nodes sidebar tab; implementation
shares web/koolook_sidebar.js with the
Curated Nodes feature.
Save / load loop
- Click 💾 (whole canvas) or ✂ (selection only) in the Workflows action bar.
- Modal: Directory → Base on existing (optional) → Action → Workflow name (shown only when needed).
- Saved entry appears at the bottom of its directory in the tree.
- Click any workflow row to load it onto a fresh tab; the tab title takes the workflow's name.
Action semantics
| Action | Resulting name | Archive behavior |
|---|---|---|
| New name | typed | auto-archives only if the typed name happens to collide |
| Use existing name (archive previous) | base | always archives the existing entry |
| Modify existing name | base, edited | no archive (different name) |
The archive trigger is a name collision with any existing active entry,
regardless of which action was selected. The Action dropdown is UX
guidance; the underlying logic flows from the resulting (name, dir) pair.
Right-click menus
- Workflow row: Load / Rename /
→ <other dir>/ Move to archive (or Restore from archive if already archived) / Delete. - Directory row: Rename / Delete (with confirm if non-empty).
Storage
| Where | What |
|---|---|
/userdata/koolook_workflows.json (ComfyUI install) |
Primary. Per-install. |
localStorage["koolook.workflows.fallback.v1"] |
Used only if /userdata is unreachable. |
localStorage["koolook.workflows.seeded.v1"] |
"1" once defaults have been seeded for this install. |
web/workflow_defaults.json (in repo) |
Distributed starter pack — seeded once into /userdata on first load with empty workflow data. |
JSON shape:
{
"directories": {
"<dir>": {
"workflows": {
"<name>": {
"savedAt": "<ISO timestamp>",
"graph": { /* serialized ComfyUI workflow JSON */ },
"archived": true
}
}
}
}
}
archived is optional (false/missing means active).
Reset (force re-seed from defaults)
Delete the userdata file in the live ComfyUI install:
rm <ComfyUI>/user/default/userdata/koolook_workflows.json
Then in the ComfyUI page DevTools console:
localStorage.removeItem("koolook.workflows.seeded.v1");
localStorage.removeItem("koolook.workflows.fallback.v1");
location.reload();
Things that surprised us — keep in mind
- Selection saves are partial graphs. Only the selected nodes + links between them survive; links into/out of non-selected nodes are nulled out, so the loaded workflow never has dangling references.
- Workflow tab name comes from
app.loadGraphData(graph, true, true, name, {})'s 4th arg. The tab flips from "Unsaved Workflow (N)" to the saved name, and Ctrl+S pre-fills with that name. (Verified againstComfy-Org/ComfyUI_frontendsrc/scripts/app.ts.) - Folder expansion state persists across re-renders (the
pathStatesMap inweb/sidebar/tree.js). Saving never collapses the directory you were viewing. - Archive sub-folder is rendered above active workflows in each directory, so the latest active workflow sits closest to the bottom — easy to spot.
- No auto-pruning of archives. Re-saving the same name many times leaves many timestamped archive entries. Right-click → Delete to remove individual ones when no longer useful.
- Same-pattern distribution as
curated_defaults.json— seecurated-sidebar.mdfor the seeding semantics that also apply here.