Skip to content

Add auto-saving draft with Save / Save As and Wipe#108

Open
alex-rawlings-yyc wants to merge 7 commits into
mainfrom
save-draft-project
Open

Add auto-saving draft with Save / Save As and Wipe#108
alex-rawlings-yyc wants to merge 7 commits into
mainfrom
save-draft-project

Conversation

@alex-rawlings-yyc

@alex-rawlings-yyc alex-rawlings-yyc commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Editing the interlinearizer no longer writes to the active project on every keystroke. Each source project now has an always-present draft (draft:{sourceProjectId}) that auto-saves every edit to papi storage, decoupled from the user's saved projects and never shown in the picker, so work is never lost.

Persistence is now explicit:

  • Save writes the draft to the active project
  • Save As writes the draft to a new project, or overwrites an existing one
  • New starts an empty draft (a project is created only on Save As)
  • Open loads a project into the draft as a working copy
  • Wipe clears the draft — the current book or the whole thing

Switching projects (New / Open) while the draft is dirty prompts to discard. The tab title shows a "●" marker while the draft has unsaved changes, toggled via updateWebViewDefinition (Platform.Bible exposes no native unsaved-tab indicator).

Implementation:

  • DraftProject type + isDraftProject guard; getDraft/saveDraft storage with a per-source serialization queue; getDraft/saveDraft backend commands.
  • useDraftProject hook owns the draft (autosave, dirty tracking, and a draftVersion that remounts the editor on New/Open/Wipe).
  • New SaveAsProjectModal, WipeConfirm, and DiscardDraftConfirm; the New modal is repurposed to configure a draft rather than create a project.
  • removeBookFromAnalysis util backs the per-book wipe.

Alignment links are intentionally not carried in the draft yet (no link-editing feature exists); Save preserves a target project's existing links.

Deferred UX decisions are recorded in user-questions.md. 988 tests, 100% coverage, lint clean.


This change is Reviewable

Summary by CodeRabbit

Release Notes

  • New Features
    • Added auto-saving draft system that persists your work between sessions
    • Added Save and Save As commands to persist draft changes to projects
    • Added Wipe options to clear the current book or entire draft
    • Added unsaved-changes indicator (●) on the editor tab
    • Added active-project badge in the project selection modal

@alex-rawlings-yyc alex-rawlings-yyc self-assigned this Jun 15, 2026
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

This PR adds a per-project draft buffer with save, save as, discard, and wipe flows, updates the loader and modal wiring around that draft state, introduces morphology display and editing controls, bundles view options, and expands tests, strings, menus, settings, and supporting mocks.

Changes

Draft workflow and morphology UI

Layer / File(s) Summary
Draft contracts and command registration
src/types/interlinearizer.d.ts, src/types/type-guards.ts, src/types/view-options.ts, src/main.ts, src/interlinearizer.web-view.tsx, contributions/menus.json, user-questions.md
Adds DraftProject, draft command signatures, bundled ViewOptions, backend and webview command registration, webview definition forwarding, menu entries, and draft workflow documentation.
Draft storage and hook behavior
src/services/projectStorage.ts, src/hooks/useDraftProject.ts, src/types/empty-factories.ts, src/utils/analysis-book.ts, src/__tests__/hooks/useDraftProject.test.ts, src/__tests__/services/projectStorage.test.ts, src/__tests__/main.test.ts, src/__tests__/types/type-guards.test.ts, src/__tests__/utils/analysis-book.test.ts
Adds empty draft creation, draft validation and storage, book-removal helpers, the draft-management hook, and tests for loading, autosave, wipe, sync, command handling, and serialization.
Modal save and wipe flows
src/components/modals/*, src/__tests__/components/modals/*, __mocks__/platform-bible-react.tsx, contributions/localizedStrings.json
Refactors create to collect draft config, adds discard and wipe confirmation dialogs, adds Save As and active-project modal behavior, wires save and wipe toolbar actions, and extends strings and tests for those flows.
Loader draft integration
src/components/InterlinearizerLoader.tsx, src/__tests__/components/InterlinearizerLoader.test.tsx
Moves the loader to draft-backed state, updates the tab title for dirty or pending edits, routes save and wipe commands, resets phrase mode on draft replacement, and rewrites loader tests around async draft behavior.
Pending edits and view option plumbing
src/components/AnalysisStore.tsx, src/components/Interlinearizer.tsx, src/components/ContinuousView.tsx, src/components/SegmentListView.tsx, src/components/SegmentView.tsx, src/components/PhraseStripContext.tsx, src/hooks/usePhraseStripSetup.ts, src/components/controls/ViewOptionsDropdown.tsx, contributions/projectSettings.json, src/__tests__/components/{AnalysisStore,ContinuousView,Interlinearizer,SegmentView}.test.tsx, src/__tests__/components/controls/ViewOptionsDropdown.test.tsx
Adds pending-edit reporting, bundles display toggles into viewOptions, adds the show-morphology setting and dropdown toggle, and updates contexts, views, and tests to use the new plumbing.
Morphology editor and token UI
src/components/{MorphemeEditor,TokenChip,PhraseBox}.tsx, src/components/__mocks__/AnalysisStore.tsx, __mocks__/platform-bible-react.tsx, src/__tests__/components/{MorphemeEditor,PhraseBox,TokenChip}.test.tsx, REVIEW.md, cspell.json
Adds morpheme breakdown and gloss editing UI, updates token and phrase focus behavior when morphology is shown, extends test mocks, and adds coverage for popover, token, and phrase interactions.
Analysis slice morphology reducers
src/store/analysisSlice.ts, src/__tests__/store/analysisSlice.test.ts
Refactors token-analysis helper logic, adds morpheme write, delete, and gloss actions and selectors, and extends reducer tests for cleanup, id preservation, and orphan-link repair.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant InterlinearizerLoader
  participant ProjectModals
  participant Main
  participant ProjectStorage

  User->>InterlinearizerLoader: Save / Save As / Wipe action
  InterlinearizerLoader->>ProjectModals: open saveAs or confirm flow
  ProjectModals->>Main: createProject / saveAnalysis / getProject
  InterlinearizerLoader->>Main: saveDraft
  Main->>ProjectStorage: saveDraft(sourceProjectId, draft)
  ProjectModals-->>InterlinearizerLoader: markSynced or loadFromProject
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

🟥High, up next

Suggested reviewers

  • imnasnainaec

Poem

🐇 I found a draft beneath the clover,
Saved its notes and wiped them over.
Tiny morphemes hopped in line,
Glosses blinked and tabs would shine.
A rabbit bows: “What a busy burrow!”

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch save-draft-project

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@alex-rawlings-yyc alex-rawlings-yyc linked an issue Jun 15, 2026 that may be closed by this pull request
coderabbitai[bot]

This comment was marked as outdated.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@alex-rawlings-yyc resolved 7 discussions.
Reviewable status: 0 of 29 files reviewed, all discussions resolved (waiting on alex-rawlings-yyc).

@alex-rawlings-yyc alex-rawlings-yyc force-pushed the save-draft-project branch 3 times, most recently from c99f7ea to 6fa7dfa Compare June 17, 2026 15:30
@alex-rawlings-yyc alex-rawlings-yyc marked this pull request as ready for review June 17, 2026 16:13
coderabbitai[bot]

This comment was marked as outdated.

@alex-rawlings-yyc

This comment was marked as outdated.

@coderabbitai

This comment was marked as outdated.

alex-rawlings-yyc and others added 5 commits June 17, 2026 14:34
Editing the interlinearizer no longer writes to the active project on every
keystroke. Each source project now has an always-present draft
(draft:{sourceProjectId}) that auto-saves every edit to papi storage,
decoupled from the user's saved projects and never shown in the picker, so
work is never lost.

Persistence is now explicit:
- Save     writes the draft to the active project
- Save As  writes the draft to a new project, or overwrites an existing one
- New      starts an empty draft (a project is created only on Save As)
- Open     loads a project into the draft as a working copy
- Wipe     clears the draft — the current book or the whole thing

Switching projects (New / Open) while the draft is dirty prompts to discard.
The tab title shows a "●" marker while the draft has unsaved changes, toggled
via updateWebViewDefinition (Platform.Bible exposes no native unsaved-tab
indicator).

Implementation:
- DraftProject type + isDraftProject guard; getDraft/saveDraft storage with a
  per-source serialization queue; getDraft/saveDraft backend commands.
- useDraftProject hook owns the draft (autosave, dirty tracking, and a
  draftVersion that remounts the editor on New/Open/Wipe).
- New SaveAsProjectModal, WipeConfirm, and DiscardDraftConfirm; the New modal
  is repurposed to configure a draft rather than create a project.
- removeBookFromAnalysis util backs the per-book wipe.

Alignment links are intentionally not carried in the draft yet (no link-editing
feature exists); Save preserves a target project's existing links.

Deferred UX decisions are recorded in user-questions.md. 988 tests, 100%
coverage, lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- markSynced now only clears the dirty flag when the live draft still matches the persisted snapshot, so a gloss edit made during an in-flight Save / Save As no longer clears the unsaved-changes indicator while the project is left stale. The save paths pass the analysis they wrote.
- The discard-changes confirmation overlays the active modal instead of replacing it, so canceling returns to the Create dialog with its typed input intact, and confirming Open no longer unmounts and re-fetches the still-open select modal underneath.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
coderabbitai[bot]

This comment was marked as outdated.

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.

Store draft project automatically

1 participant