feat(desktop): attach dialogs remember the last-used directory - #93076
feat(desktop): attach dialogs remember the last-used directory#93076ClintonEmok wants to merge 2 commits into
Conversation
The native open dialogs started from scratch on every attach — a user pulling a dozen screenshots from the same folder re-navigated there for each one (NousResearch#92925). The main process now records the parent directory of each successful pick in userData/picker-state.json (machine-side fact, Electron's authority) and offers it as defaultPath when the caller has no opinion of its own. Precedence ladder: explicit defaultPath (composer cwd, NousResearch#91074's Downloads default) > remembered last dir when it still exists > OS default. Pure helpers in electron/picker-state.ts, covered by unit tests for the precedence policy, the remember rule, and the corrupt-file fallback. Fixes NousResearch#92925
Clean, well-tested module: pure precedence function, atomic tmp+rename persistence, corrupt-snapshot fail-closed, and good negative tests. Two things to resolve:
Minor: The precedence tests (explicit wins / remembered ignored when gone / OS default) cover exactly the right matrix. |
The electron/main.ts import block must keep ./picker-state ahead of ./wsl-clipboard-image per perfectionist/sort-imports; the CI run on this PR failed JS & TS checks on exactly that.
|
Both review points addressed:
|
What does this PR do?
The native open dialogs (composer Files/Images/Folder, plugin source, etc.) started from scratch on every attach — a user pulling a dozen screenshots from the same folder re-navigated there for each one (#92925).
The main process now records the parent directory of each successful pick and offers it as the dialog's
defaultPathwhen the caller has no opinion of its own. Precedence ladder:defaultPathfrom the caller (the composer passes its cwd; [Feature]: Desktop — attach file dialog should default to Downloads when the session has no workspace #91074's Downloads default applies when detached) — it expresses current intentundefined→ OS defaultElectron is authoritative for machine-side facts, so the memory lives in the main process (
userData/picker-state.json), not in renderer state.Related Issue
Fixes #92925
(Complements #91074 rather than duplicating it: that PR is the initial default, this remembers what the user actually chose, which beats any static default after the first attach.)
Type of Change
Changes Made
apps/desktop/electron/picker-state.ts(new) — pure helpers:nextPickerDefaultPath(precedence policy),dirToRemember(parent-of-first-pick rule), atomic read/write ofpicker-state.json; corrupt file reads as "nothing remembered"apps/desktop/electron/main.ts—hermes:selectPathsconsults the remembered directory when no explicit default was given, and records the pick on success; canceled dialogs change nothingapps/desktop/electron/picker-state.test.ts— 8 cases covering the precedence ladder, the remember rule, round-trip persistence, and corrupt-state fallbackHow to Test
cd apps/desktop && npx vitest run electron/picker-state.test.ts— 8 passeddefaultPath: the next attach dialog opens in the folder you just usedChecklist
Code
fix(scope):,feat(scope):, etc.)npx vitest run --project electron: 1606 passed; tsc clean)Documentation & Housekeeping
cli-config.yaml.exampleif I added/changed config keys — or N/A (state lives in userData, not config.yaml)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A