Skip to content

Persist input prompt drafts on cancel/escape#1044

Merged
chhoumann merged 6 commits intomasterfrom
1021
Dec 19, 2025
Merged

Persist input prompt drafts on cancel/escape#1044
chhoumann merged 6 commits intomasterfrom
1021

Conversation

@chhoumann
Copy link
Copy Markdown
Owner

@chhoumann chhoumann commented Dec 19, 2025

Summary

  • persist session draft input for single and multi-line prompts on cancel/escape and restore on reopen per prompt signature
  • clear drafts on submit or when the user cancels with an empty input
  • add a lightweight in-memory draft store shared by prompt modals

Testing

  • bun run build-with-lint

Notes

  • No migration or release impact

Closes #1021

Summary by CodeRabbit

  • New Features

    • Input prompts now persist drafts across prompt reopenings; drafts clear on submit or when empty.
    • A new setting lets you enable/disable draft persistence; turning it off clears stored drafts.
    • Draft persistence integrated across multiple input prompts and synced with the live input when submitting or closing.
  • Chores

    • Settings schema reorganized and defaults centralized.
  • Performance

    • Draft storage is session-scoped with bounded retention to avoid unbounded memory growth.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 19, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
quickadd Ready Ready Preview Dec 19, 2025 3:10pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 19, 2025

Warning

Rate limit exceeded

@chhoumann has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 22 minutes and 51 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fe81e69 and dbe3702.

📒 Files selected for processing (3)
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts (7 hunks)
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (7 hunks)
  • src/settings.ts (1 hunks)

Walkthrough

Adds session-scoped in-memory draft persistence for input prompts, a settings toggle to enable/disable it, and integrates a draft handler/store into single-line, wide, and date input prompts to hydrate, track, persist on close, and clear on submit.

Changes

Cohort / File(s) Change Summary
Draft storage
src/utils/InputPromptDraftStore.ts
New singleton implementing an in-memory draft store with typed keys, 100-entry capacity, timestamp-based eviction, and API: getInstance(), makeKey(), get(), set(), clear(), clearAll(). Exports InputPromptDraftKind and InputPromptDraftKey.
Draft handler
src/utils/InputPromptDraftHandler.ts
New InputPromptDraftHandler class that wraps InputPromptDraftStore and settings persistence toggle; methods: hydrate(initialValue), markChanged(), persist(value, didSubmit).
Single-line prompt integration
src/gui/GenericInputPrompt/GenericInputPrompt.ts
Adds draftHandler field, hydrates initial input via handler, replaces direct input assignments with onInputChanged(value), adds syncInputFromEl() and persistDraft() helpers; persists draft on close (if not submitted) and clears on submit.
Wide / multi-line prompt integration
src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
Same lifecycle wiring as single-line: draftHandler init/hydration, onInputChanged, DOM sync before submit/close, persistDraft() logic, clear on submit.
Date prompt minor wiring
src/gui/VDateInputPrompt/VDateInputPrompt.ts
Input change handler calls onInputChanged(newValue) instead of direct assignment; debounced preview logic preserved.
Settings module
src/settings.ts
New QuickAddSettings interface and DEFAULT_SETTINGS constant exported from src/settings.ts (moved/centralized from previous file).
Settings store & imports updated
src/settingsStore.ts, src/main.ts, src/migrations/Migrations.ts, src/gui/AIAssistantSettingsModal.ts
Redirected imports to src/settings for QuickAddSettings / DEFAULT_SETTINGS where previously from quickAddSettingsTab.
QuickAdd UI tab (UI only)
src/quickAddSettingsTab.ts
Reworked tab to remove exported QuickAddSettings/DEFAULT_SETTINGS, add a UI toggle persistInputPromptDrafts wired to settingsStore, and clear drafts when toggle disabled.

Sequence Diagram(s)

sequenceDiagram
  participant Prompt as Prompt UI (GenericInputPrompt / GenericWide / VDate)
  participant Handler as InputPromptDraftHandler
  participant Store as InputPromptDraftStore
  participant Settings as settingsStore

  Note over Prompt,Handler: Open prompt
  Prompt->>Handler: construct(key, shouldPersist?)
  Handler->>Settings: read persistInputPromptDrafts
  Handler->>Store: get(key) (if shouldPersist)
  Store-->>Handler: persistedValue?
  Handler-->>Prompt: hydratedValue

  Note over Prompt: User types
  Prompt->>Handler: markChanged() / onInputChanged(value)

  alt Close without submit
    Prompt->>Handler: persist(currentValue, didSubmit=false)
    Handler->>Settings: check shouldPersist
    Handler->>Store: set(key, value) or clear(key)
  else Submit
    Prompt->>Handler: persist(value, didSubmit=true)
    Handler->>Store: clear(key)
  end

  Note over Settings: User toggles persist setting
  Settings->>Store: (if disabled) clearAll()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review InputPromptDraftStore eviction logic and key generation.
  • Verify InputPromptDraftHandler persistence conditions (didChange, trim/empty handling).
  • Inspect prompt submit/close paths for correct DOM->state sync and no unintended clearing when persistence disabled.
  • Check settings toggle wiring and clearing behavior when disabled.

Possibly related PRs

Poem

🐰 I nibbled words between the keys,

I tucked your lines in tiny leaves,
Escape, cancel — your thoughts stay near,
Reopen the box, your notes appear,
A little hop keeps drafts sincere.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the main objective of the PR: persisting input prompt drafts when modals are dismissed via cancel/escape.
Linked Issues check ✅ Passed The PR implements all coding requirements: adds in-memory draft store with session-scoped persistence, integrates draft handler into prompt modals (GenericInputPrompt, GenericWideInputPrompt, VDateInputPrompt), clears drafts on submit, restores drafts on reopen, and provides settings control.
Out of Scope Changes check ✅ Passed Changes include refactoring of settings module structure (moving QuickAddSettings to settings.ts) which appears necessary for integrating the new persistInputPromptDrafts setting, and aligns with the stated objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/utils/InputPromptDraftStore.ts (1)

45-54: Consider refreshing timestamp on get() for true LRU behavior.

Currently, the timestamp is only updated on set(). If you want true LRU (Least Recently Used) eviction, the timestamp should also be updated when a draft is accessed via get(). This would prevent frequently-accessed drafts from being evicted even if they were originally created a while ago.

However, if the current behavior (evicting oldest by creation/modification time) is intentional, this is fine as-is.

🔎 Optional: Update timestamp on get for LRU
 get(key: string): string | undefined {
-	return this.drafts.get(key)?.value;
+	const entry = this.drafts.get(key);
+	if (entry) {
+		entry.timestamp = Date.now();
+	}
+	return entry?.value;
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e5659b and 7231042.

📒 Files selected for processing (4)
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts (6 hunks)
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (6 hunks)
  • src/gui/VDateInputPrompt/VDateInputPrompt.ts (2 hunks)
  • src/utils/InputPromptDraftStore.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in src/: core logic under engine/, services/, and utils/; Svelte UI in src/gui; shared types in src/types; settings entry in src/quickAddSettingsTab.ts

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/utils/InputPromptDraftStore.ts
  • src/gui/VDateInputPrompt/VDateInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Biome enforces tab indentation (width 2), LF endings, and an 80-character line guide; align editor settings
Use camelCase for variables and functions
Prefer type-only imports in TypeScript files
Route logging through the logger utilities for consistent output
Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or tests/obsidian-stub.ts

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/utils/InputPromptDraftStore.ts
  • src/gui/VDateInputPrompt/VDateInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
src/**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/utils/InputPromptDraftStore.ts
  • src/gui/VDateInputPrompt/VDateInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
🧬 Code graph analysis (2)
src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (2)
tests/obsidian-stub.ts (1)
  • Modal (443-447)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-73)
src/gui/GenericInputPrompt/GenericInputPrompt.ts (2)
tests/obsidian-stub.ts (2)
  • Modal (443-447)
  • TextComponent (122-149)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-73)
🔇 Additional comments (11)
src/gui/VDateInputPrompt/VDateInputPrompt.ts (1)

71-75: LGTM!

The change to call this.onInputChanged(newValue) correctly integrates with the parent class's draft tracking mechanism. The currentInput field is still maintained separately for the preview functionality, which is appropriate since it serves a different purpose (debounced date preview).

src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (3)

66-76: LGTM!

The draft key generation and restoration logic is well-structured. Using kind: "multi" correctly differentiates wide input prompts from single-line prompts. Loading the draft after setting the initial value from parameters, and then recording initialValue after the draft load, ensures proper change detection.


190-215: LGTM!

The draft lifecycle methods are well-implemented:

  • onInputChanged properly tracks changes
  • syncInputFromEl ensures DOM/state consistency
  • persistDraft correctly handles all cases: clearing on submit, no-op on unchanged input, clearing on empty, and persisting meaningful changes

231-236: LGTM!

The onClose flow correctly synchronizes the input value from the DOM only when not submitted (since submit() already reads it), then persists the draft before resolving.

src/gui/GenericInputPrompt/GenericInputPrompt.ts (3)

66-76: LGTM!

Draft key generation using kind: "single" correctly distinguishes single-line prompts from multi-line ones. The draft loading and initialValue tracking follows the same pattern as GenericWideInputPrompt, maintaining consistency.


186-189: LGTM!

Making onInputChanged protected is the right choice, as it allows VDateInputPrompt (and other subclasses) to call this method to properly track input changes for draft persistence.


197-211: LGTM!

The persistDraft logic correctly handles all edge cases and is consistent with the implementation in GenericWideInputPrompt.

src/utils/InputPromptDraftStore.ts (4)

1-13: LGTM!

The type definitions are well-structured. Using a discriminated kind type with "single" | "multi" ensures type safety when creating draft keys.


15-29: LGTM!

The singleton pattern is correctly implemented with a private constructor. The session-only design aligns with the PR objectives.


31-39: LGTM!

Including a version field (v: 1) in the key format is a good practice for forward compatibility if the key structure needs to change in the future.


60-62: clearAll() is currently unused but useful for testing.

This method isn't called anywhere in the current codebase but provides a clean way to reset state in tests. Consider documenting this intent or adding it to test setup.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/gui/GenericInputPrompt/GenericInputPrompt.ts (1)

14-20: Consider extracting shared draft logic into a utility or mixin.

The draft persistence logic is nearly identical between GenericInputPrompt and GenericWideInputPrompt. If this pattern expands to more prompt types, consider extracting the shared behavior.

Current duplication is manageable for two classes, so this is a low-priority enhancement.

Also applies to: 189-227

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7231042 and 37c09dc.

📒 Files selected for processing (4)
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts (6 hunks)
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (6 hunks)
  • src/quickAddSettingsTab.ts (4 hunks)
  • src/utils/InputPromptDraftStore.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/InputPromptDraftStore.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in src/: core logic under engine/, services/, and utils/; Svelte UI in src/gui; shared types in src/types; settings entry in src/quickAddSettingsTab.ts

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/quickAddSettingsTab.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Biome enforces tab indentation (width 2), LF endings, and an 80-character line guide; align editor settings
Use camelCase for variables and functions
Prefer type-only imports in TypeScript files
Route logging through the logger utilities for consistent output
Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or tests/obsidian-stub.ts

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/quickAddSettingsTab.ts
src/**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components

Files:

  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/quickAddSettingsTab.ts
🧬 Code graph analysis (3)
src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (2)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-76)
src/settingsStore.ts (1)
  • settingsStore (8-21)
src/gui/GenericInputPrompt/GenericInputPrompt.ts (3)
tests/obsidian-stub.ts (2)
  • Modal (443-447)
  • TextComponent (122-149)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-76)
src/settingsStore.ts (1)
  • settingsStore (8-21)
src/quickAddSettingsTab.ts (2)
src/settingsStore.ts (1)
  • settingsStore (8-21)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-76)
🔇 Additional comments (7)
src/quickAddSettingsTab.ts (1)

19-19: LGTM! Clean implementation of the draft persistence setting.

The setting follows the established patterns in the codebase:

  • Properly integrates with settingsStore for state management
  • Correctly clears all drafts when persistence is disabled (line 442-444)
  • Default value of true aligns with the PR objective to prevent accidental data loss

Also applies to: 24-24, 67-67, 430-448

src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (3)

67-79: LGTM! Draft loading logic is well-structured.

The draft key construction uses kind: "multi" to differentiate from single-line prompts, and draft loading is gated behind shouldPersistDrafts(). The initialValue capture enables proper change detection.


204-220: LGTM! Draft persistence logic handles edge cases correctly.

The method properly:

  • Clears draft on successful submit (line 207-210)
  • Avoids saving unchanged content (line 212)
  • Clears stale drafts when input is whitespace-only (line 214-217)

240-248: LGTM! Close handling correctly synchronizes state before persisting.

The conditional sync ensures:

  • On cancel/escape: DOM value is captured before persistence
  • On submit: Value is already captured at line 177, avoiding double-read
src/gui/GenericInputPrompt/GenericInputPrompt.ts (3)

67-79: LGTM! Draft initialization follows the same pattern as GenericWideInputPrompt.

Uses kind: "single" to distinguish drafts from multi-line prompts, ensuring each prompt type maintains its own draft namespace.


189-192: Good choice using protected for onInputChanged.

This aligns with the protected input field (line 16) and allows potential subclasses to extend input handling behavior while still participating in draft tracking.


200-216: LGTM! Draft persistence and close handling are correctly implemented.

The implementation is consistent with GenericWideInputPrompt, maintaining uniform behavior across both prompt types.

Also applies to: 236-244

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37c09dc and fe81e69.

📒 Files selected for processing (9)
  • src/gui/AIAssistantSettingsModal.ts (1 hunks)
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts (7 hunks)
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (7 hunks)
  • src/main.ts (1 hunks)
  • src/migrations/Migrations.ts (1 hunks)
  • src/quickAddSettingsTab.ts (3 hunks)
  • src/settings.ts (1 hunks)
  • src/settingsStore.ts (1 hunks)
  • src/utils/InputPromptDraftHandler.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in src/: core logic under engine/, services/, and utils/; Svelte UI in src/gui; shared types in src/types; settings entry in src/quickAddSettingsTab.ts

Files:

  • src/gui/AIAssistantSettingsModal.ts
  • src/settings.ts
  • src/utils/InputPromptDraftHandler.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/settingsStore.ts
  • src/quickAddSettingsTab.ts
  • src/migrations/Migrations.ts
  • src/main.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: Biome enforces tab indentation (width 2), LF endings, and an 80-character line guide; align editor settings
Use camelCase for variables and functions
Prefer type-only imports in TypeScript files
Route logging through the logger utilities for consistent output
Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or tests/obsidian-stub.ts

Files:

  • src/gui/AIAssistantSettingsModal.ts
  • src/settings.ts
  • src/utils/InputPromptDraftHandler.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/settingsStore.ts
  • src/quickAddSettingsTab.ts
  • src/migrations/Migrations.ts
  • src/main.ts
src/**/*.{ts,tsx,svelte}

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for classes and Svelte components

Files:

  • src/gui/AIAssistantSettingsModal.ts
  • src/settings.ts
  • src/utils/InputPromptDraftHandler.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/settingsStore.ts
  • src/quickAddSettingsTab.ts
  • src/migrations/Migrations.ts
  • src/main.ts
src/main.ts

📄 CodeRabbit inference engine (AGENTS.md)

Preserve the hand-ordered imports in src/main.ts; disable auto-sorting there

Files:

  • src/main.ts
🧠 Learnings (4)
📚 Learning: 2025-12-09T21:20:52.425Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.425Z
Learning: Applies to src/**/*.{ts,tsx,js,jsx} : Source code lives in `src/`: core logic under `engine/`, `services/`, and `utils/`; Svelte UI in `src/gui`; shared types in `src/types`; settings entry in `src/quickAddSettingsTab.ts`

Applied to files:

  • src/gui/AIAssistantSettingsModal.ts
  • src/settings.ts
  • src/settingsStore.ts
  • src/quickAddSettingsTab.ts
  • src/migrations/Migrations.ts
  • src/main.ts
📚 Learning: 2025-12-09T21:20:52.425Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.425Z
Learning: Applies to src/**/*.{ts,tsx} : Structure production code so Obsidian dependencies are injected behind interfaces; unit tests target pure logic and swap in adapters or `tests/obsidian-stub.ts`

Applied to files:

  • src/gui/AIAssistantSettingsModal.ts
📚 Learning: 2025-12-09T21:20:52.425Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.425Z
Learning: Applies to src/main.ts : Preserve the hand-ordered imports in `src/main.ts`; disable auto-sorting there

Applied to files:

  • src/main.ts
📚 Learning: 2025-12-09T21:20:52.425Z
Learnt from: CR
Repo: chhoumann/quickadd PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-09T21:20:52.425Z
Learning: Applies to src/**/*.{ts,tsx} : Prefer type-only imports in TypeScript files

Applied to files:

  • src/main.ts
🧬 Code graph analysis (3)
src/settings.ts (2)
src/types/choices/IChoice.ts (1)
  • IChoice (3-10)
src/ai/Provider.ts (3)
  • Model (14-17)
  • AIProvider (3-12)
  • DefaultProviders (92-95)
src/utils/InputPromptDraftHandler.ts (2)
src/utils/InputPromptDraftStore.ts (2)
  • InputPromptDraftStore (15-76)
  • InputPromptDraftKey (3-8)
src/settingsStore.ts (1)
  • settingsStore (8-21)
src/quickAddSettingsTab.ts (2)
src/settingsStore.ts (1)
  • settingsStore (8-21)
src/utils/InputPromptDraftStore.ts (1)
  • InputPromptDraftStore (15-76)
🔇 Additional comments (18)
src/migrations/Migrations.ts (1)

2-2: LGTM!

The import path update correctly references the centralized src/settings module. Using import type aligns with the coding guidelines for TypeScript files.

src/main.ts (1)

4-6: LGTM!

The import reorganization correctly separates the QuickAddSettingsTab class from the centralized settings module. The type-only import for QuickAddSettings follows coding guidelines, and the hand-ordered imports are preserved as required by the biome-ignore directive.

src/settingsStore.ts (1)

2-3: LGTM!

The import paths correctly reference the centralized ./settings module. Type-only import for QuickAddSettings follows coding guidelines.

src/gui/AIAssistantSettingsModal.ts (1)

3-3: LGTM!

The import path update correctly references the centralized src/settings module for the QuickAddSettings type.

src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (4)

62-68: Good integration of draft persistence.

The draft handler initialization captures the prompt's identifying metadata (kind, header, placeholder, linkSourcePath), enabling per-prompt draft storage. Hydrating the initial value restores any previously saved draft, fulfilling the PR objective.


182-195: LGTM!

The draft management methods are well-structured:

  • onInputChanged tracks mutations via markChanged()
  • syncInputFromEl safely reads from DOM with null guards
  • persistDraft correctly passes didSubmit to clear drafts on submit

112-112: LGTM!

Routing onChange through onInputChanged properly tracks user modifications for draft persistence.


166-166: LGTM!

Reading directly from the DOM element with a fallback ensures the final input value is captured before the modal closes, addressing potential timing issues with the reactive onChange handler.

src/settings.ts (2)

5-46: LGTM! Clean interface structure.

The QuickAddSettings interface is well-organized with clear typing. The new persistInputPromptDrafts field at line 8 is appropriately placed near the related inputPrompt field.


48-84: Verify opt-out default for draft persistence.

Line 51 defaults persistInputPromptDrafts to true, meaning all users (including existing ones after upgrade) will have draft persistence enabled automatically. This is opt-out rather than opt-in.

Since drafts are session-only and the feature prevents data loss (per PR objectives), this default seems reasonable. However, confirm this aligns with the project's approach to new features that store user input.

src/quickAddSettingsTab.ts (2)

17-18: LGTM! Proper import usage.

Line 18 correctly uses a type-only import for QuickAddSettings, following the coding guidelines for TypeScript files.


348-366: LGTM! Well-implemented setting with proper cleanup.

The setting follows Obsidian patterns and includes appropriate cleanup behavior:

  • Line 361 clears all drafts when persistence is disabled, preventing stale data
  • Description clearly communicates session-only storage
  • Positioned logically in the Input group (line 53)
src/utils/InputPromptDraftHandler.ts (3)

7-18: LGTM! Well-designed constructor with flexible persistence control.

The constructor properly defaults shouldPersist to check settingsStore (line 17) while allowing override for testing or special cases. The singleton store pattern is appropriate here.


20-26: LGTM! Clean hydration logic.

The method correctly stores initialValue (line 21) for later comparison in persist() and uses nullish coalescing (line 25) to fall back appropriately.


32-48: LGTM! Robust persistence logic with proper edge case handling.

The method correctly handles multiple scenarios:

  • Line 36: Clears draft on submit (completed flow)
  • Line 40: Avoids persisting unchanged or reverted input (efficient)
  • Line 43: Clears empty/whitespace-only drafts (good cleanup)
  • Line 47: Persists meaningful changes

The logic prevents stale drafts while preserving useful ones.

src/gui/GenericInputPrompt/GenericInputPrompt.ts (3)

5-5: LGTM! Clean draft handler integration.

The draft handler is properly initialized with a comprehensive key (lines 62-67) including kind: "single" to differentiate prompt types. Line 68 hydrates the input before opening, ensuring any restored draft is immediately available.

Also applies to: 16-16, 62-68


114-114: LGTM! Proper change tracking through centralized handler.

Line 114 routes changes through onInputChanged (lines 178-181), which correctly marks the draft as changed (line 179) before updating internal state. The protected visibility allows subclass customization if needed.

Also applies to: 178-181


163-163: LGTM! Critical DOM synchronization before persistence.

The implementation correctly handles DOM synchronization:

  • Line 163: Captures final input value on submit with safe fallback
  • Lines 209-211: Syncs uncommitted DOM changes before persisting when cancelled
  • Line 212: Persists after sync with proper didSubmit flag

This ensures drafts capture the latest user input even if not explicitly committed via onChange.

Also applies to: 183-191, 209-212

Comment thread src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
@chhoumann chhoumann merged commit 62a67f4 into master Dec 19, 2025
4 checks passed
@chhoumann chhoumann deleted the 1021 branch December 19, 2025 15:11
github-actions Bot pushed a commit that referenced this pull request Jan 28, 2026
# [2.10.0](2.9.4...2.10.0) (2026-01-28)

### Bug Fixes

* add insert-after blank-line mode ([#1056](#1056)) ([231e908](231e908))
* backfill file opening defaults for legacy choices ([bfffd46](bfffd46))
* default update announcements to major ([#1042](#1042)) ([4e5659b](4e5659b))
* handle template overwrite with case-mismatched paths ([#1049](#1049)) ([0140556](0140556))
* harden suggester display items ([5460657](5460657))
* harden suggester filtering on Android ([4560f22](4560f22)), closes [#1078](#1078)
* normalize leading slashes in capture/template paths ([#1050](#1050)) ([1c7def1](1c7def1))
* normalize unicode in file suggestions ([#1046](#1046)) ([10c0402](10c0402))
* pin obsidian types to 1.11.4 for SecretStorage API ([ddbf6f6](ddbf6f6))
* prefill macro rename input ([#1043](#1043)) ([06c4a25](06c4a25))
* preserve blank lines for insert after ([#1054](#1054)) ([818c036](818c036))
* preserve variables for VALUE templating ([36d43ba](36d43ba))
* reduce bundle size below sync limit ([1e1a632](1e1a632))
* restore compatibility with Templater 2.18.0 ([716f2d9](716f2d9)), closes [#1085](#1085) [#1086](#1086)

### Features

* add back class to choice suggester ([#1047](#1047)) ([4c8cfe9](4c8cfe9))
* add capture selection-as-value controls ([#1055](#1055)) ([250768a](250768a))
* add inline insert-after capture mode ([b2e1ef5](b2e1ef5))
* add macro selection helper ([786b53c](786b53c)), closes [#483](#483)
* add native date picker prompt ([2811c5a](2811c5a))
* add per-token multiline VALUE inputs ([98fa7db](98fa7db)), closes [#339](#339)
* add versioned documentation with Docusaurus ([03c2d3e](03c2d3e))
* adopt obsidian 1.11 settings APIs ([#1041](#1041)) ([15c4b34](15c4b34))
* default multi placeholder to name ([fcd058f](fcd058f))
* enhance template folder chooser ([f1e2a9f](f1e2a9f)), closes [#1011](#1011) [#1012](#1012)
* improve prompt labeling for VALUE/MACRO and multi choices ([78fd184](78fd184))
* persist input prompt drafts on cancel/escape ([#1044](#1044)) ([62a67f4](62a67f4))
* store AI provider keys in SecretStorage ([4559013](4559013))
* support short-form date aliases ([e04a3f6](e04a3f6))
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 2.10.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Persist input prompt drafts on cancel/escape

1 participant