Repository navigation
feat: mobile Sessions sheet + touch actions (stacked on session sidebar) - #2
Conversation
|
Same battery, run against this branch.
Nothing here regresses the base. Same caveat as #1: gates measured, no live-vault smoke-test. Best regards, 🤖 Written with Claude Code |
…rmove The divider assigned data.sessionSidebarWidth on every pointermove, and the store setter saves on assignment, so a single drag produced a burst of whole-file data.json writes - the write pattern behind the 2026-09-27 corruption incident. Rendering and persistence are now separate: a drag previews into component-local state and commits once on pointerup; a held arrow key is coalesced through a 250ms quiet period; destroy() flushes so a chosen width is not lost on unmount. Covered by test/components/sessionResizePersistence.test.ts - a gesture persists exactly once, and the value still survives a reload.
Each row now shows what happened to its last turn instead of only a spinner for running sessions. Running, done, failed, cancelled and interrupted each carry a distinct icon AND a text label, so colour is never the only signal. idle is the honest unknown, not a synonym for done: the registry only holds sessions that have been opened, so an unopened row has no live state to read and renders nothing rather than implying an outcome. A pair left streaming by a mid-run close reports interrupted - it is neither done nor failed, and guessing would put a false claim on a status surface. Terminal state comes from the last message pair's assistant state, which the session already holds reactively, so a row updates as a run settles.
…rip ends the drag Integrates the two parallel resize fixes: the commit-on-pointerup width model with its four tests, plus pointer capture and pointercancel handling. Without capture a pointerup landing outside the 5px strip, or over an iframe, is lost and the drag sticks to the cursor.
Resize fix integrated with pointer capture —
|
| Gate | Result |
|---|---|
biome lint src test |
exit 0 |
svelte-check |
0 errors, 0 warnings |
vitest run |
146 files / 2011 tests, 9 of them new (resize + status) |
npm run build |
build/prod/main.js 6,336.36 kB, exit 0 |
The single test failure is test/skills/bootstrapDefaultSkills.test.ts → leaves an up-to-date skill untouched despite CRLF and a trailing newline. It reproduces identically on the untouched base commit (886d30b), so it is not caused by this change — it is sensitive to a Windows checkout with core.autocrlf=true.
Still outstanding
This has not been smoke-tested against a live Obsidian vault. The remaining gate is a real drag on the divider (and the save-count check it is meant to satisfy), which needs a running app.
One cue per settled run, fired from ChatSession's finally so it happens once however many panes have the thread open. The outcome is read from the state the catch block has already normalised, so a post-success bookkeeping failure still reports success rather than a false failure. Cancelled runs stay silent. Sound and notification are independent toggles, both defaulting on. The settings read is guarded: the finally can execute with no plugin initialised (headless, or the unit tests for this path) and a cue must never break the bookkeeping of a run that has already settled.
Run cues (sound + notification) —
|
| Gate | Result |
|---|---|
biome lint src test |
exit 0 |
svelte-check (both configs) |
0 errors, 0 warnings |
vitest run |
147 files / 2017 tests — 6 new in test/stores/runCue.test.ts, all passing |
npm run build |
build/prod/main.js 6,338.37 kB, exit 0 |
The single failure remains test/skills/bootstrapDefaultSkills.test.ts (CRLF), which reproduces on the untouched base — pre-existing and unrelated, as noted earlier.
Still outstanding
Not smoke-tested against a live Obsidian. The audio and notification halves are feature-detected and cannot be exercised in this repo's test environment; the decision logic is unit-tested, the emission is not. A live check needs a real run started from a gesture.
Stacked on #1 (chat session sidebar). Base is
feat/session-sidebar; will retarget tomainafter #1 merges.What
Makes the session list usable on mobile / narrow panes, where the in-leaf sidebar is hidden (<600px).
SessionList.svelte— the in-leaf sidebar and the mobile sheet render the exact same list (no divergence).Menu: Open/Pin/Archive/Rename/Delete/Restore). Hover action buttons are kept on pointer devices via@media (hover), so desktop is unchanged and touch is fully served.SessionSheetModal(extendsSvelteModal) hosts the shared list; full-screen on phones. Opening a chat closes it.!wide && enableSessionSidebar).ThreadPathStore, so it stays correct in both the sidebar and the sheet.Gates
npm run checkclean · biome lint 0 errors · feature tests pass (vitest) ·npm run buildsucceeds. Each step reviewed; whole-branch review clean.Note
Not yet smoke-tested on a real mobile device — desktop verifies the trigger→modal→open/close flow (narrow the pane <600px); the touch "⋯" menu shows on touch devices. Recommend a phone check before merge.
🤖 Generated with Claude Code