Skip to content

Fix/remember export folder#519

Closed
makaradam wants to merge 2 commits intosiddharthvaddem:mainfrom
makaradam:fix/remember-export-folder
Closed

Fix/remember export folder#519
makaradam wants to merge 2 commits intosiddharthvaddem:mainfrom
makaradam:fix/remember-export-folder

Conversation

@makaradam
Copy link
Copy Markdown

@makaradam makaradam commented May 2, 2026

Closes #503

The save dialog now opens in the last folder the user exported to, instead of always defaulting to Downloads.

What changed

  • Added exportFolder to UserPreferences so the last used folder persists across sessions
  • IPC handler passes it as defaultPath to Electron's save dialog
  • On successful export, the returned folder path is saved back to preferences
  • Used path.dirname in the Electron handler for correct edge case handling (root paths etc.)

Test plan

  • Export a video — note the folder it saves to
  • Close and reopen the app
  • Export again — save dialog should open in the same folder as last time
  • Export to a different folder — next export should remember the new folder

Summary by CodeRabbit

  • New Features
    • Users can now specify a custom export folder when saving videos
    • Export folder preferences are automatically saved and persist across sessions
    • Selected export directories are remembered and used as defaults for future exports
    • Custom folder support applies to both GIF and MP4 exports

makaradam added 2 commits May 2, 2026 10:34
The save dialog now opens in the last folder the user exported to,
instead of always defaulting to Downloads. The folder is persisted
in userPreferences (localStorage) and passed through the IPC layer
to the Electron save dialog as defaultPath.

Closes siddharthvaddem#503
Addresses code review feedback: the previous substring/lastIndexOf approach
would store empty string as export folder if saved to root directory.
path.dirname in the Electron handler handles edge cases correctly and
is returned as a new dir field in the IPC response.
@makaradam makaradam requested a review from siddharthvaddem as a code owner May 2, 2026 08:44
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

📝 Walkthrough

Walkthrough

Added "remember last export folder" feature by extending the export API to accept and return an optional folder path. Changes persist the export folder in user preferences, hydrate it on load, pass it through the IPC layer, and update UI state when the user selects a new location.

Changes

Export Folder Persistence Flow

Layer / File(s) Summary
Data Model
src/lib/userPreferences.ts
UserPreferences adds optional exportFolder?: string field. loadUserPreferences() reads it from localStorage (only if non-empty), saveUserPreferences() now persists it alongside other prefs.
Electron Type Definitions
electron/electron-env.d.ts
saveExportedVideo signature extended to accept optional exportFolder?: string param; return type now includes optional dir?: string field for the resolved output directory.
IPC Handler
electron/ipc/handlers.ts
Handler uses exportFolder ?? app.getPath("downloads") as the base directory for the save dialog instead of always defaulting to downloads. Success response now returns dir: path.dirname(normalizedPath) for the actual saved folder.
Preload Bridge
electron/preload.ts
electronAPI.saveExportedVideo now forwards the optional exportFolder param to the IPC "save-exported-video" invocation.
UI Integration & State
src/components/video-editor/VideoEditor.tsx
Added exportFolder state, hydrate from user prefs on mount, persist to prefs via auto-save effect. All three export paths (unsaved, GIF, MP4) now pass exportFolder to IPC call and update state from returned dir. Added exportFolder to handleExport dependency array.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

The logic is pretty straightforward—no wild branching or edge cases—but you've got a coherent pattern threaded through 5 different files across electron and react layers. The IPC handler's baseFolder selection and the consistent dir-extraction pattern in three export flows are solid, though you'll wanna spot-check that path.dirname() call in all contexts. localStorage validation in preferences loading looks good (non-empty string check). Overall kinda clean, just needs careful eyes on the interconnected flow.

Possibly related PRs

Poem

📁 The folder remembers, you don't have to—
Last path saved, next export knows where to go.
From prefs to electron, a journey so true,
exportFolder flows where the videos grow. 🎬

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix/remember export folder' clearly and concisely describes the main change—implementing folder persistence across sessions.
Description check ✅ Passed The description covers motivation, technical approach, and manual testing steps; however, it lacks formal sections from the template like 'Type of Change' and screenshot/video evidence.
Linked Issues check ✅ Passed The PR fully implements the feature from #503: persists last export folder, passes it as defaultPath to the save dialog, and updates preferences on successful export.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the export folder persistence feature; no unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
src/components/video-editor/VideoEditor.tsx (1)

1417-1427: 💤 Low value

Both export paths correctly wired; dep array is complete

exportFolder is passed to both GIF and MP4 saveExportedVideo calls and updated from saveResult.dir on success. The dep array at line 1629 ensures handleExport captures the latest folder after each export.

gifFrameRate/gifLoop/gifSizePreset are correctly absent from handleExport's dep array — they flow in via the settings parameter from handleOpenExportDialog, not from the closure directly.

One nit: the if (saveResult.dir) setExportFolder(saveResult.dir) guard appears identically in three places (lines 1319, 1427, 1572). Extracting it into a tiny inline helper would make future changes to the post-save behavior a one-line edit rather than three — totally optional, but kinda nice to have.

♻️ Optional — extract post-save folder update
+ const handleExportFolderUpdate = useCallback((dir?: string) => {
+   if (dir) setExportFolder(dir);
+ }, []);

Then replace all three occurrences of:

- if (saveResult.dir) setExportFolder(saveResult.dir);
+ handleExportFolderUpdate(saveResult.dir);

Also applies to: 1562-1572, 1608-1634

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/video-editor/VideoEditor.tsx` around lines 1417 - 1427, The
post-save folder-update guard "if (saveResult.dir)
setExportFolder(saveResult.dir)" is duplicated in multiple places (within the
GIF/MP4 saveResult handling). Create a small inline helper function (e.g.,
applySaveResultDir or updateExportFolderFromSave) that accepts saveResult,
checks saveResult.dir, and calls setExportFolder(saveResult.dir) when present,
then replace each duplicated guard in the handlers that call
window.electronAPI.saveExportedVideo with a single call to that helper;
reference the existing setExportFolder and saveResult symbols so the change is
localized and behavior remains identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@electron/ipc/handlers.ts`:
- Line 835: The assignment to baseFolder uses nullish coalescing (const
baseFolder = exportFolder ?? app.getPath("downloads")) which doesn't guard
against an empty string and can make path.join("", fileName) resolve relative;
change the check to treat empty string as falsy (e.g., use || or an explicit
empty-string check) so that when exportFolder is "" the fallback
app.getPath("downloads") is used; update the line referencing exportFolder and
baseFolder (and any subsequent path.join usage) to rely on the corrected
baseFolder value.

---

Nitpick comments:
In `@src/components/video-editor/VideoEditor.tsx`:
- Around line 1417-1427: The post-save folder-update guard "if (saveResult.dir)
setExportFolder(saveResult.dir)" is duplicated in multiple places (within the
GIF/MP4 saveResult handling). Create a small inline helper function (e.g.,
applySaveResultDir or updateExportFolderFromSave) that accepts saveResult,
checks saveResult.dir, and calls setExportFolder(saveResult.dir) when present,
then replace each duplicated guard in the handlers that call
window.electronAPI.saveExportedVideo with a single call to that helper;
reference the existing setExportFolder and saveResult symbols so the change is
localized and behavior remains identical.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e4a36174-133c-4227-9307-50b67742279d

📥 Commits

Reviewing files that changed from the base of the PR and between 884021c and 54ec231.

📒 Files selected for processing (5)
  • electron/electron-env.d.ts
  • electron/ipc/handlers.ts
  • electron/preload.ts
  • src/components/video-editor/VideoEditor.tsx
  • src/lib/userPreferences.ts

Comment thread electron/ipc/handlers.ts
message: "Export canceled",
};
}
const baseFolder = exportFolder ?? app.getPath("downloads");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

?? won't protect against empty string exportFolder

nullish coalescing only catches null/undefined — an empty "" sneaks right through. path.join("", fileName) resolves to a relative path, so the save dialog would open at the process CWD instead of Downloads on that edge case.

The userPreferences.ts validation already guards against "" in storage, but the IPC boundary itself has no such check. Swapping to || closes the gap for zero cost.

🛡️ Proposed fix
- const baseFolder = exportFolder ?? app.getPath("downloads");
+ const baseFolder = exportFolder || app.getPath("downloads");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const baseFolder = exportFolder ?? app.getPath("downloads");
const baseFolder = exportFolder || app.getPath("downloads");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@electron/ipc/handlers.ts` at line 835, The assignment to baseFolder uses
nullish coalescing (const baseFolder = exportFolder ?? app.getPath("downloads"))
which doesn't guard against an empty string and can make path.join("", fileName)
resolve relative; change the check to treat empty string as falsy (e.g., use ||
or an explicit empty-string check) so that when exportFolder is "" the fallback
app.getPath("downloads") is used; update the line referencing exportFolder and
baseFolder (and any subsequent path.join usage) to rely on the corrected
baseFolder value.

@makaradam
Copy link
Copy Markdown
Author

Already resolved by other user: #512

@makaradam makaradam closed this May 2, 2026
@makaradam makaradam deleted the fix/remember-export-folder branch May 2, 2026 11:23
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.

[Feature]: remember last exporting folder

1 participant