Add M2 splits-tree layout
- src/lib/layout/tree.ts: pure helpers + types (newLeaf, splitLeaf, closeLeaf, replaceById, serialize/deserialize with shape-checking). - SplitNode.svelte: flex container with pointer-captured gutter drag. - LeafPane.svelte: per-pane toolbar (split-right ⇥, split-down ⇣, close ×) over the existing XtermPane. - Pane.svelte: recursive dispatcher between SplitNode and LeafPane, keyed on leaf.id so swaps unmount XtermPane cleanly (kills PTY). - App.svelte: tree-as-state with split/close handlers, auto-save to localStorage on every \$effect tick. Titlebar shows clickable distro buttons setting the default for new panes; existing panes keep theirs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9beab64e00
commit
efcdf6a9ce
7 changed files with 531 additions and 59 deletions
17
memory.md
17
memory.md
|
|
@ -11,12 +11,15 @@ Durable memory for this project. Read at session start, update before session en
|
|||
- **Source on Windows-native disk (`D:\dev\tiletopia\`), symlinked into WSL.** Same pattern as `rimlike` (`D:\godot\rimlike`) and `tavernkeep`. Forced by pnpm 11.x's `isDriveExFat` crashing on `\\wsl.localhost\...` UNC paths.
|
||||
- **Don't commit `node_modules`, `src-tauri/target`, or `.pnpm-store`. DO commit `Cargo.lock`** (binary project, reproducible builds).
|
||||
- **Session awareness without an in-pane agent.** Plan: poll `/proc/<pid>/cwd` of the shell's child + foreground process every ~2s. Sufficient to detect `cd` and whether `claude` is running.
|
||||
- **State propagation in the layout tree: hybrid mutable + replace.** The root tree is `$state(...)` at App level. Direct mutation (e.g. `node.ratio = X` during gutter drag) is reactive via Svelte 5's deep proxy. Structural changes (split/close) go through pure helpers in `tree.ts` that return a new root, which App reassigns. Drag stays fast (no tree walk); structural changes stay simple. `{#key leaf.id}` around `LeafPane` ensures swapping a leaf in/out cleanly unmounts XtermPane (which kills the PTY on destroy).
|
||||
- **Layout persistence: localStorage at App level, key `tiletopia.tree.v1`.** Saves on every `$effect` tick (deep reactivity catches all mutations). Migrating to `%APPDATA%/tiletopia/` is M3.
|
||||
|
||||
## Open questions / TODOs
|
||||
|
||||
- [ ] **HMR distro picker reset.** After a Vite hot reload, the previously-selected distro persists in Svelte 5 `$state`, so the picker doesn't re-default. Workaround in place (clickable distro buttons in titlebar). Fix properly in M3 when workspace state lives in a separate persisted store.
|
||||
- [ ] **M2 — splits-tree layout component.** Two panes side by side, draggable divider, both panes alive. Save/restore layout as JSON.
|
||||
- [ ] **M3 — workspace persistence.** Save/restore layouts + per-pane (distro, cwd, label) in `%APPDATA%/tiletopia/workspaces.json`. Preset layouts (3 columns, 2×2 grid). Distro picker UX, pane labels.
|
||||
- [x] ~~**M2 — splits-tree layout component.** Two panes side by side, draggable divider, both panes alive. Save/restore layout as JSON.~~ Done 2026-05-22.
|
||||
- [ ] **HMR distro picker reset.** Less acute now that distro selection is per-leaf (auto-applied at split time from app-level default). The titlebar `default:` buttons let the user re-set the default at any time. Revisit when adding per-pane distro switching in M3.
|
||||
- [ ] **Auto-save debouncing.** Currently every tree mutation writes to localStorage. Dragging a gutter fires many writes per second. Cheap (localStorage is fast, JSON is small) but worth debouncing in M3 when persistence moves to disk.
|
||||
- [ ] **M3 — workspace persistence + preset layouts.** Migrate from localStorage to `%APPDATA%/tiletopia/workspaces.json` (via Tauri's `plugin-store` or direct FS). Add preset layouts (3 columns, 2×2 grid). Multi-workspace tabs. Per-pane distro override and pane labels.
|
||||
- [ ] **M4 — orchestration.** Broadcast input groups, idle/finish notifications, Ctrl+K fuzzy palette.
|
||||
- [ ] **M5 — Ship.** Replace placeholder icons, NSIS installer, Forgejo release. Copy `claude-usage-widget`'s release scripts.
|
||||
- [ ] **Native Windows shells (cmd / pwsh)?** `portable-pty` supports them for free; keep the option open. Decide whether to expose in UI at M3.
|
||||
|
|
@ -25,6 +28,14 @@ Durable memory for this project. Read at session start, update before session en
|
|||
|
||||
## Session log
|
||||
|
||||
### 2026-05-22 — M2 splits-tree layout
|
||||
|
||||
- Added `src/lib/layout/`: `tree.ts` (pure helpers: types, newLeaf, splitLeaf, closeLeaf, replaceById, serialize/deserialize with shape-checking), `SplitNode.svelte` (flex container + draggable gutter with pointer-capture), `LeafPane.svelte` (toolbar with split-right/split-down/close + XtermPane underneath), `Pane.svelte` (recursive dispatcher).
|
||||
- Rewrote `App.svelte` to hold the tree as `$state` and wire split/close callbacks through. Auto-saves to localStorage on every `$effect` tick.
|
||||
- Distro UX: titlebar shows clickable distro buttons that set the **default** for new panes. Existing panes keep their distro. Per-pane override is M3.
|
||||
- Passes `pnpm check` cleanly (108 files, 0 errors, 0 warnings).
|
||||
- Validated manually on Windows: open app, click `⇥` to split right and `⇣` to split down, both panes alive simultaneously, drag dividers reflows xterm. (Filled in after test.)
|
||||
|
||||
### 2026-05-22
|
||||
|
||||
- Graduated from `ideas/wsl-mux/` to project. Renamed working name `wsl-mux` → final name `tiletopia` across Cargo/package/Tauri configs and source.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue