Commit graph

3 commits

Author SHA1 Message Date
533b830d2c feat(classifier): export/import a whole workspace; fix short-viewport welcome
The scan is the expensive part (minutes on cloud mounts), so a workspace is now
portable between browsers/machines without re-scanning:
- Per-workspace "Export" downloads the snapshot + classify map as one
  <name>.zddc-workspace.json (the source-directory handle is omitted — it can't
  be serialized across browsers).
- Landing-page "Import" recreates the workspace from that JSON; the user clicks
  "Connect directory" once on the new browser to re-attach the folder (no
  re-scan — the snapshot carries the 2-hour walk). A classification-dataset JSON
  is rejected with a pointer to the in-app Import.

Also fix the welcome screen clipping its top on short viewports: the base
.empty-state centers with align-items:center, which overflows symmetrically and
puts the card's top out of scroll reach. Center the inner card with auto margins
instead — they collapse when it's taller than the viewport, keeping the top
reachable.

Test: workspace import recreates a transferable record (snapshot + map, no handle); 46 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 13:50:58 -05:00
01b01f8f7a feat(classifier): welcome rewrite + resumable scan + reconnect on restore
- Welcome: drop the 'absorbed into Browse' notice; bigger, inviting intro with
  a two-method tutorial (Classify & copy — recommended/non-destructive; Rename
  in place — edits files) and a OneDrive 'keep on device' tip.
- Resumable scan: the snapshot now records per-folder scan state, the workspace
  record is created up front, and the partial snapshot is persisted every 5s
  during the (slow) scan. scanner.resumeScan() resolves handles for only the
  still-pending folders and drains them — so an interrupted scan picks up where
  it left off instead of starting over.
- Reconnect on restore: opening a workspace no longer assumes the source is
  connected; a header 'Connect directory' button (and a prompt) re-grants the
  persisted handle in one click or lets you re-pick it. Until connected you can
  still edit the data model; connecting also resumes any pending scan.
- Tests: resume-scan via mock root handle (31 classify/classifier green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 16:38:08 -05:00
1d09abdc8b feat(classifier): workspaces — scan-once, resume from snapshot (phase 6)
The classifier re-scanned the source on every session; on cloud-backed mounts
(OneDrive/Samba) that's minutes of per-op latency. Workspaces fix it: scan a
folder ONCE, snapshot the completed tree, and resume instantly — all
classification runs on the data model; the filesystem is only touched at copy.

- persist.js v2: multi-workspace IndexedDB (tiny 'index' store for the welcome
  list + 'data' store holding the source handle, tree snapshot, and map). DB v2.
- scanner.js: snapshotTree()/loadSnapshot() (compact, handle-less, marked done,
  totals recomputed) + lazy resolveFileHandle/resolveDirHandle from the root.
- workspace.js: welcome manager (new/open/rename/delete), debounced autosave of
  the active workspace, 'Refresh from disk' (re-scan → re-snapshot, path-keyed
  map carries over). New workspace = the one slow full scan; reopen = instant.
- copy.js: resolves snapshot files' handles from the workspace root with a
  one-click read permission re-grant; missing-on-disk files surface as errors.
- app.js: enterAppShell() shared by rename/workspace flows; exposes setMode;
  classify.js decoupled from persistence.
- template/css: welcome workspace list + header 'Workspaces' button.
- tests: snapshot round-trip, persist CRUD + classify-only-preserves-tree,
  copy-from-snapshot via mock root handle (28 classify/classifier tests green).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 15:07:40 -05:00