file dialog choose location

This commit is contained in:
Siddharth
2025-11-25 15:37:03 -07:00
parent f887d09865
commit 48253cc31d
7 changed files with 52 additions and 18 deletions
+18 -5
View File
@@ -1,4 +1,4 @@
import { BrowserWindow, screen, ipcMain, desktopCapturer, shell, app, nativeImage, Tray, Menu } from "electron";
import { BrowserWindow, screen, ipcMain, desktopCapturer, shell, app, dialog, nativeImage, Tray, Menu } from "electron";
import { fileURLToPath } from "node:url";
import path from "node:path";
import fs from "node:fs/promises";
@@ -202,12 +202,25 @@ function registerIpcHandlers(createEditorWindow2, createSourceSelectorWindow2, g
});
ipcMain.handle("save-exported-video", async (_, videoData, fileName) => {
try {
const downloadsPath = app.getPath("downloads");
const videoPath = path.join(downloadsPath, fileName);
await fs.writeFile(videoPath, Buffer.from(videoData));
const result = await dialog.showSaveDialog({
title: "Save Exported Video",
defaultPath: path.join(app.getPath("downloads"), fileName),
filters: [
{ name: "MP4 Video", extensions: ["mp4"] }
],
properties: ["createDirectory", "showOverwriteConfirmation"]
});
if (result.canceled || !result.filePath) {
return {
success: false,
cancelled: true,
message: "Export cancelled"
};
}
await fs.writeFile(result.filePath, Buffer.from(videoData));
return {
success: true,
path: videoPath,
path: result.filePath,
message: "Video exported successfully"
};
} catch (error) {
+1 -1
View File
@@ -35,7 +35,7 @@ interface Window {
setRecordingState: (recording: boolean) => Promise<void>
onStopRecordingFromTray: (callback: () => void) => () => void
openExternalUrl: (url: string) => Promise<{ success: boolean; error?: string }>
saveExportedVideo: (videoData: ArrayBuffer, fileName: string) => Promise<{ success: boolean; path?: string; message?: string }>
saveExportedVideo: (videoData: ArrayBuffer, fileName: string) => Promise<{ success: boolean; path?: string; message?: string; cancelled?: boolean }>
}
}
+26 -8
View File
@@ -1,4 +1,4 @@
import { ipcMain, desktopCapturer, BrowserWindow, shell, app } from 'electron'
import { ipcMain, desktopCapturer, BrowserWindow, shell, app, dialog } from 'electron'
import fs from 'node:fs/promises'
import path from 'node:path'
@@ -128,22 +128,40 @@ export function registerIpcHandlers(
ipcMain.handle('save-exported-video', async (_, videoData: ArrayBuffer, fileName: string) => {
try {
const downloadsPath = app.getPath('downloads')
const videoPath = path.join(downloadsPath, fileName)
await fs.writeFile(videoPath, Buffer.from(videoData))
// Show save dialog to let user choose location and filename
const result = await dialog.showSaveDialog({
title: 'Save Exported Video',
defaultPath: path.join(app.getPath('downloads'), fileName),
filters: [
{ name: 'MP4 Video', extensions: ['mp4'] }
],
properties: ['createDirectory', 'showOverwriteConfirmation']
});
// User cancelled the dialog
if (result.canceled || !result.filePath) {
return {
success: false,
cancelled: true,
message: 'Export cancelled'
};
}
// Write the file to the chosen location
await fs.writeFile(result.filePath, Buffer.from(videoData));
return {
success: true,
path: videoPath,
path: result.filePath,
message: 'Video exported successfully'
}
};
} catch (error) {
console.error('Failed to save exported video:', error)
console.error('Failed to save exported video:', error);
return {
success: false,
message: 'Failed to save exported video',
error: String(error)
}
};
}
})
}
+4 -2
View File
@@ -248,8 +248,10 @@ export default function VideoEditor() {
const saveResult = await window.electronAPI.saveExportedVideo(arrayBuffer, fileName);
if (saveResult.success) {
toast.success('Video exported successfully!');
if (saveResult.cancelled) {
toast.info('Export cancelled');
} else if (saveResult.success) {
toast.success(`Video exported successfully to ${saveResult.path}`);
} else {
setExportError(saveResult.message || 'Failed to save video');
toast.error(saveResult.message || 'Failed to save video');
@@ -724,7 +724,7 @@ const VideoPlayback = forwardRef<VideoPlaybackRef, VideoPlaybackProps>(({
className="absolute inset-0 bg-cover bg-center"
style={{
...backgroundStyle,
filter: showBlur ? 'blur(3px)' : 'none',
filter: showBlur ? 'blur(2px)' : 'none',
}}
/>
<div
+1 -1
View File
@@ -435,7 +435,7 @@ export class FrameRenderer {
if (this.config.showBlur) {
ctx.save();
ctx.filter = 'blur(3px)';
ctx.filter = 'blur(6px)'; // Canvas blur is weaker than CSS
ctx.drawImage(bgCanvas, 0, 0, w, h);
ctx.restore();
} else {
+1
View File
@@ -36,6 +36,7 @@ interface Window {
success: boolean
path?: string
message?: string
cancelled?: boolean
}>
}
}