Skip to content

feat: Notion-style implicit toggle body + debounced saves - #2

Merged
rikiyanai merged 1 commit into
masterfrom
fix/notion-toggle-model
Jul 20, 2026
Merged

rikiyanai merged 1 commit into
masterfrom
fix/notion-toggle-model

Conversation

@rikiyanai

@rikiyanai rikiyanai commented Jul 20, 2026 •

Copy link
Copy Markdown
Owner
  • Toggle body is now implicit: everything under a title down to the next toggle (or EOF) collapses — anything typed/pasted underneath is automatically inside. Ledger maintains only title lines (shift / re-anchor / dedupe); the boundary bug class is gone.
  • Title-touching edits re-anchor instead of dropping the toggle.
  • Saves coalesced to 1/sec (was a full-canvas write per keystroke), flushed on quit/Clear/terminate.

Verified: 8 new-model ledger replica cases + full headless suite. Root-cause trail in docs/FAILURE_LOG.md (2026-07-21).


Note

Medium Risk
Toggle fold/containment logic is substantially reworked (data loss risk if debounced save isn’t flushed before a hard kill); debounced saves are mitigated by flush on normal quit/terminate.

Overview
Toggle lists now match Notion’s container model: bodyEndLine is removed from ToggleEntry, and collapse covers everything under a title until the next toggle’s title or EOF via bodyEnd(forToggleAt:). Create/remove/flip, fold rendering, caret containment, and context menu all use that implicit range; nested toggles split at a new title instead of flattening overlaps.

The edit ledger only tracks title lines—shift when edits are at/above the title, re-anchor when the title line is edited (instead of dropping the toggle), dedupe duplicate title lines. Legacy toggles.json with bodyEndLine still decodes.

Canvas persistence no longer writes on every keystroke: scheduleSave() debounces to once per second; flushSave() runs on Clear, Quit, and applicationWillTerminate.

docs/FAILURE_LOG.md documents the implicit-body model, re-anchoring, and performance fix.

Reviewed by Cursor Bugbot for commit d50547b. Bugbot is set up for automated code reviews on this repo. Configure here.

- toggle body is now implicit: everything under a title down to the next
  toggle (or EOF) collapses; ledger maintains only title lines
  (shift / re-anchor / dedupe), removing the boundary bug class
- title-touching edits re-anchor instead of dropping the toggle
- saves coalesced to 1/sec (was full-canvas write per keystroke),
  flushed synchronously on quit/Clear/terminate

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d50547b. Configure here.

Comment thread TermiNotesAppKit.swift

func textDidChange(_ notification: Notification) {
saveContent()
scheduleSave()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toggles persist ahead of notes

High Severity

textDidChange still writes toggles.json on every edit while notes.txt is deferred by up to one second via scheduleSave. If the process exits before a flush (crash, force quit, kill), disk toggles match the live buffer but the canvas file does not, so reload pairs stale text with shifted title-line metadata.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d50547b. Configure here.

@rikiyanai
rikiyanai merged commit b239fbf into master Jul 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant