Mobile Checklist Experience
.claude/plans/mobile-checklist-experience.md · 2026-07-21What we're building on
- Checked state syncs for free — content is one markdown string through
SyncEnvelope, field-level LWW ChecklistMarkdownin NoteSparrowCore is pure Foundation and parses both checkbox forms — the iOS renderer reuses it, no new dialect- Dictation's Done-moment offer already creates
[ ]lists (passed round-1 step 12)
- No way to check off an item on iOS — the core unmet need
- No add-item or convert-to-checklist affordance on mobile
- Resumed dictation drops the second list 2 root causes found — whole-transcript averaging suppresses the offer, and sustained listening silently gives up after 5 empty windows
Interaction model — settled 2026-07-21
- Empty note → opens straight into the keyboard
- Note without checklists → read view; tap anywhere → edit
- Checklist row, tap → toggle — whole row, always. An accidental toggle is self-inverse; an accidental keyboard pop is the worst failure mid-shop, so the reversible action wins the ambiguity
- Plain text or blank space below content, tap → edit, cursor at end (blank-space tap also covers all-checklist notes)
- Checklist row, long-press → edit — the escape hatch for fixing that item's text
- Edit ↔ Done in the toolbar → the always-visible mode switch; Done is the only exit — swiping the keyboard away stays in edit (people dismiss it to scroll)
- "Add item" row → always visible at the end of each checklist block; extends the list without ever leaving read mode — the in-store flow is check, check, add, check on one continuous surface
Accepted limitation: the transition tap can't carry its location into TextEditor — entering edit lands the cursor at the end. Once inside, native tap-to-place-cursor works normally everywhere. (iOS 18 TextSelection is a future refinement, not a dependency.)
Key decisions
[ ]↔[x] in the string and saves instantly (bypassing the 2s debounce, same persist-now pattern voice capture uses) — shrinking the known ~1s LWW race window. Rapid toggles coalesce in the existing 1s sync flush.Phases
ChecklistDocumentin NoteSparrowCore: parse content into stable-ID line models (plain / checklist) on top ofChecklistMarkdowntogglingLine(at:),appendingItem(...),convertingPlainLinesToChecklist()— all byte-exact on untouched lines, convert is a true toggle- Round-trip unit tests: both forms, indents, blanks, unicode, reversibility
- Read/edit mode state in
NoteDetailView(Edit ↔ Done pair, blank-space tap, keyboard-dismiss stays in edit); newChecklistReadViewrenders rows with design-token styling, 44pt targets, light haptic, long-press-to-edit - Toggle path with stale-state guard (
currentNotere-resolve) and immediateupdateNote - Live re-render on remote changes (Mac toggles appear on a watched phone); attachments/footer unchanged; VoiceOver labels + toggle action
- Always-visible "Add item" inline field per checklist block — return commits and re-arms for rapid entry, never leaves read mode
- "Convert to Checklist" menu action with count confirmation + reverse; dismissible hint row on list-shaped plain notes
- Defect A: segment-aware
looksLikeList— a wordy resumed segment can't suppress an earlier clean list; offer converts just the list-shaped ranges - Defect B: reset
emptyRestartson voice-band activity; raise the sustained ceiling; if recognition truly stops, end visibly — never a live-looking mic with no recognizer - Segmenter regression tests (list-then-prose, list-pause-list); verify
merge()overlap-stitching still dedupes
- Closes round-1 debt: iOS→Mac direction (untested step 11) verified end-to-end
- Manual QA Sarah: check off five items walking the store; 30s-pause resumed dictation captures both sets; Add-item and Convert flows on real notes
- Document the ~1s LWW window honestly (two toggle surfaces now); update mobile-app and note-editing blueprints
Final review
Pros. Smallest architecture that delivers tap-to-check; reuses the shared parser; touches no edit/save/sync plumbing; every phase ships value alone; dictation fixes target root causes found by code reading.
Cons, stated plainly. (1) Read-mode-first changes tap-to-edit muscle memory for all notes — now de-risked: the interaction model was walked through the shop flow and settled; residual cost is the cursor-at-end transition tap. (2) Two toggle surfaces widen exposure to the known ~1s LWW window; simultaneous Mac+iPhone toggles resolve to one writer — documented, not fixed (per-line merge would be a sync-engine project). (3) Defect B's fix leans on the level meter distinguishing voice activity; fallback is honest-but-less-magical visible session end. (4) Segment-scoped conversion has fiddly range bookkeeping — the likeliest task to slip, and whole-transcript offers still work if it does.
Edge cases to watch. Very large notes re-parsing per keystroke in the add-item field; RTL/localized strikethrough; a Mac edit turning a checklist line into prose while the phone's read view is open mid-tap.