Skip to content

feat: saved import presets for bulk fetch - #91

Merged
frostmute merged 6 commits into
mainfrom
feat/import-presets
Aug 11, 2026
Merged

feat: saved import presets for bulk fetch#91
frostmute merged 6 commits into
mainfrom
feat/import-presets

Conversation

@frostmute

@frostmute frostmute commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Summary

Adds saved import presets for the bulk fetch workflow. Users can capture the full fetch-modal configuration as a named preset and reuse it in one click — no more re-entering collections, tag filters, folders, and toggles on every import.

What's included

  • Presets section in the fetch modal (RaindropFetchModal): a dropdown listing saved presets plus a Save current as preset and Delete preset action. Selecting a preset applies all captured options and re-renders the modal.
  • Full option coverage: collections, tag filter + match type (AND/OR), content type filter, include subcollections, save destination, append tags, use-Raindrop-title-for-filename, fetch-only-new / update-existing, and both template overrides.
  • Per-preset command-palette entries: each preset registers a Fetch: {preset name} command, re-registered automatically when presets are created, updated, or deleted (via Plugin.removeCommand, available since Obsidian 1.7.2; plugin minAppVersion is 1.13.0).
  • Shared options mapping: importPresetToOptions() keeps the live modal fetch and command fetches in lockstep.
  • Backward compatible: existing saved settings without importPresets default to an empty list; modal defaults are unchanged.

Verification

  • npm run build (tsc + esbuild) — clean
  • npm run lint — clean
  • npx jest — 21 suites, 324 tests passing (new coverage for preset rendering/apply/snapshot, SavePresetModal, upsertPreset id stability, and command registration)

Notes

  • New setting field importPresets added to the settings schema (defaults to []).
  • No new dependencies; reuses existing modals.ts / main.ts / plugin-data patterns.

Open in Devin Review

Capture the full fetch-modal configuration (collections, tag filter +
match type, content types, subcollections, vault path, append tags,
filename, new-only/update, template overrides) as named presets stored
in plugin data. A Presets section at the top of the fetch modal loads,
saves, and deletes presets, and each preset gets its own command-palette
entry ("Fetch: {name}") that is re-registered as presets change.

Backward compatible: existing saved settings without importPresets
default to an empty list, and modal defaults are unchanged.

Generated with Codebuff 🤖
Co-Authored-By: Codebuff <noreply@codebuff.com>
Copilot AI lite review requested due to automatic review settings August 10, 2026 09:35

This comment was marked as resolved.

@chatgpt-codex-connector

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Reset modal fields to defaults when the preset selection is cleared, add an Import Presets management section (rename/delete) to the settings tab, and document the feature in CHANGELOG and product specs.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
devin-ai-integration[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@frostmute

Copy link
Copy Markdown
Owner Author

Re-review findings

Re-reviewed PR #91 through Devin’s latest commit a26b8b8.

Verification

  • PR checks: DeepScan and build passed
  • Build: passed
  • Lint: passed
  • Full test suite: 22 suites, 330 tests passed
  • Production dependency audit: 0 vulnerabilities
  • Full audit still reports existing development-toolchain vulnerabilities; this PR does not change dependencies

MEDIUM — failed save/rename operations leave stale in-memory state

  • src/modals.ts:423-426
  • src/settings.ts:827-828

The modal save flow assigns plugin.settings.importPresets = result.presets before saveSettings() completes, and the settings rename flow mutates preset.name before persistence succeeds. The dialog now remains open when persistence fails, but the failed change remains in memory. A later unrelated settings save can persist the supposedly failed operation, while the rendered settings and command registrations may be out of sync.

Please snapshot and restore the previous state when saveSettings() rejects, and add regression coverage for failed modal save and failed rename.

LOW — preset records are only shallowly validated

  • src/main.ts:193-195
  • src/settings.ts:871-878

loadSettings() verifies only that importPresets is an array. A malformed or manually edited entry with missing/non-string fields can make settings rendering throw when calling .trim(). Consider normalizing or filtering preset records during load.

LOW — focus is lost after preset selection

  • src/modals.ts:143

Selecting a preset rebuilds the full modal and loses the current focus position. Restoring focus to the preset dropdown would improve keyboard and screen-reader usability.

No CRITICAL or HIGH findings remain. The PR is otherwise safe from the reviewed security and performance perspectives. I recommend addressing the MEDIUM persistence rollback issue before merge.

… focus

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Re-review findings (commit a26b8b8)

All three addressed in 683dd46.

MEDIUM — stale in-memory state on failed save/rename: openSavePresetModal() now snapshots settings.importPresets and restores it (then rethrows so the dialog shows the error) when saveSettings() rejects; the settings rename handler restores preset.name and re-renders before rethrowing. Regression tests added for both in tests/integration/presetWorkflow.test.ts (saveData rejecting with "disk full").

LOW — shallow preset validation: added normalizeImportPresets() in src/modals.ts, used by loadSettings(). It coerces every field to its expected type with defaults, validates tagMatchType/filterType against allowed values, and drops entries missing a usable id/name, so rendering can't throw on .trim(). Unit tests cover malformed, non-array, and valid input.

LOW — focus lost after preset selection: the modal sets a refocusPresetDropdown flag before preset-triggered re-renders and focuses dropdown.selectEl on the rebuilt dropdown.

Build, lint, secret scan pass; 335 tests pass.

devin-ai-integration[bot]

This comment was marked as resolved.

@frostmute
frostmute merged commit 5010f0a into main Aug 11, 2026
2 checks passed
@frostmute
frostmute deleted the feat/import-presets branch August 11, 2026 00:32
@devactivity-app

Copy link
Copy Markdown

Pull Request Summary by devActivity

Metrics

Cycle Time: 14h 56m Coding Time: < 1 min Pickup Time: 3m Review Time: 14h 53m Comments: 3

Achievements

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.

2 participants