feat(editor): flush pending autosaves on project switch and keep newer-on-disk drafts as conflicts

Merged
GN
5d ago
+1354-40

Summary

A project switch cancelled pending editor autosaves. A saved draft was also dropped without notice when the file changed on disk after the draft was taken. This change writes pending autosaves before the switch continues and shows a conflict instead of dropping the draft.

Related Issue

Refs #1074

Type of Change

  • feat: new feature
  • fix: bug fix
  • docs: documentation only
  • style: formatting or non-functional styling changes
  • refactor: internal cleanup with no behavior change
  • perf: performance improvement
  • test: adds or updates tests
  • build: build or dependency changes
  • ci: CI/CD workflow changes
  • chore: maintenance or tooling
  • revert: reverts a previous change

What Changed

  • flushPendingAutoSaves() saves every file with a pending autosave timer. A failed save keeps the file unsaved and is logged.
  • The restore flow for a project waits for that flush before it persists the old project.
  • A restored draft that is older than the file on disk opens as a conflict. The file shows the disk content and a banner with Keep my draft and Use disk version.
  • A file with a conflict counts as unsaved. Closing it shows the usual unsaved-changes prompt.
  • The persisted state keeps the conflict draft, so a later restore checks it again.

How It Was Tested

  • bun run ci (Biome lint + format + imports, strict mode)
  • bun run typecheck
  • bun run test
  • cargo clippy --all-targets -- -D warnings (in src-tauri)
  • cargo test (in src-tauri)
  • Manual verification completed
  • Not applicable

Scoped Vitest runs cover the flush, the draft rules, the banner and the persistence round trip. The full Vitest run happens in CI.

Screenshots or Recordings

Screenshot follows in a comment after the run.

CI & Review Gate

  • All CI checks pass (PR Validation, Rust Checks, Build Verification, Security Scans)
  • Code review comments from CodeRabbit / Claude have been addressed or resolved
  • No unresolved review findings remain

Checklist

  • My PR title follows the conventional commit format used by this repo
  • I linked the related issue or explained why none exists
  • I updated docs when needed
  • I added or updated tests when needed
  • I verified the change does not introduce unrelated modifications
  • I read AGENTS.md and followed the contributor guidelines
  • A human reviewed the complete diff before submission

Summary by cubic

Switching projects cancelled pending editor autosaves, and a restored draft was silently dropped when the file had changed on disk after the draft was saved. Now the switch flushes pending autosaves before persisting the old project, and a draft older than the disk file opens as a visible conflict instead of being discarded.

Behavior

  • Pending auto-saves are written before the old project is persisted; a failed save leaves the file dirty, logs the basename only, and re-arms the retry timer.
  • A restored draft older than the file on disk opens with the disk content plus a banner offering Keep my draft or Use disk version; keeping the draft turns it into an unsaved edit.
  • A conflicted file counts as needing attention everywhere (close prompt, dirty indicator, app-close count), locks the editor and its markdown frontmatter (edits are dropped), and refuses save/reload until resolved; Save in a close prompt reveals the tab (clearing fullscreen if needed) and warns instead of failing silently.
  • The persisted state keeps an unresolved conflict stamped with the draft time, so a later restore re-evaluates it against disk.

Summary by CodeRabbit

  • New Features
    • Pending autosaves are written before switching projects, helping preserve recent edits.
    • When a restored draft conflicts with newer disk content, both versions remain available. Choose whether to keep the draft or use the disk version.
  • Bug Fixes
    • Files with unresolved draft conflicts are treated as needing attention, with clearer unsaved-change indicators and safeguards against closing or saving them unintentionally.