Skip to content

Commit a966428

Browse files
committed
Merge upstream and sync timeline/audio config
1 parent a6ae0e6 commit a966428

63 files changed

Lines changed: 2965 additions & 220 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

electron/electron-env.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ interface Window {
7777
fileName: string,
7878
) => Promise<{ success: boolean; path?: string; message?: string; canceled?: boolean }>;
7979
openVideoFilePicker: () => Promise<{ success: boolean; path?: string; canceled?: boolean }>;
80+
openAudioFilePicker: () => Promise<{
81+
success: boolean;
82+
path?: string;
83+
message?: string;
84+
error?: string;
85+
canceled?: boolean;
86+
}>;
8087
setCurrentVideoPath: (path: string) => Promise<{ success: boolean }>;
8188
setCurrentRecordingSession: (
8289
session: import("../src/lib/recordingSession").RecordingSession | null,

electron/ipc/handlers.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ const PROJECT_FILE_EXTENSION = "openscreen";
2525
const SHORTCUTS_FILE = path.join(app.getPath("userData"), "shortcuts.json");
2626
const RECORDING_SESSION_SUFFIX = ".session.json";
2727
const ALLOWED_IMPORT_VIDEO_EXTENSIONS = new Set([".webm", ".mp4", ".mov", ".avi", ".mkv"]);
28+
const ALLOWED_IMPORT_AUDIO_EXTENSIONS = new Set([
29+
".mp3",
30+
".wav",
31+
".m4a",
32+
".aac",
33+
".ogg",
34+
".flac",
35+
".webm",
36+
]);
2837

2938
/**
3039
* Paths explicitly approved by the user via file picker dialogs or project loads.
@@ -56,6 +65,10 @@ function hasAllowedImportVideoExtension(filePath: string): boolean {
5665
return ALLOWED_IMPORT_VIDEO_EXTENSIONS.has(path.extname(filePath).toLowerCase());
5766
}
5867

68+
function hasAllowedImportAudioExtension(filePath: string): boolean {
69+
return ALLOWED_IMPORT_AUDIO_EXTENSIONS.has(path.extname(filePath).toLowerCase());
70+
}
71+
5972
async function approveReadableVideoPath(
6073
filePath?: string | null,
6174
trustedDirs?: string[],
@@ -97,6 +110,33 @@ async function approveReadableVideoPath(
97110
return normalizedPath;
98111
}
99112

113+
async function approveReadableAudioPath(filePath?: string | null): Promise<string | null> {
114+
const normalizedPath = normalizeVideoSourcePath(filePath);
115+
if (!normalizedPath) {
116+
return null;
117+
}
118+
119+
if (isPathAllowed(normalizedPath)) {
120+
return normalizedPath;
121+
}
122+
123+
if (!hasAllowedImportAudioExtension(normalizedPath)) {
124+
return null;
125+
}
126+
127+
try {
128+
const stats = await fs.stat(normalizedPath);
129+
if (!stats.isFile()) {
130+
return null;
131+
}
132+
} catch {
133+
return null;
134+
}
135+
136+
approveFilePath(normalizedPath);
137+
return normalizedPath;
138+
}
139+
100140
function resolveRecordingOutputPath(fileName: string): string {
101141
const trimmed = fileName.trim();
102142
if (!trimmed) {
@@ -722,6 +762,47 @@ export function registerIpcHandlers(
722762
}
723763
});
724764

765+
ipcMain.handle("open-audio-file-picker", async () => {
766+
try {
767+
const result = await dialog.showOpenDialog({
768+
title: "Select audio",
769+
defaultPath: app.getPath("music"),
770+
filters: [
771+
{
772+
name: "Audio Files",
773+
extensions: ["mp3", "wav", "m4a", "aac", "ogg", "flac", "webm"],
774+
},
775+
{ name: "All Files", extensions: ["*"] },
776+
],
777+
properties: ["openFile"],
778+
});
779+
780+
if (result.canceled || result.filePaths.length === 0) {
781+
return { success: false, canceled: true };
782+
}
783+
784+
const approvedPath = await approveReadableAudioPath(result.filePaths[0]);
785+
if (!approvedPath) {
786+
return {
787+
success: false,
788+
message: "Selected file is not a supported audio file",
789+
};
790+
}
791+
792+
return {
793+
success: true,
794+
path: approvedPath,
795+
};
796+
} catch (error) {
797+
console.error("Failed to open audio file picker:", error);
798+
return {
799+
success: false,
800+
message: "Failed to open audio file picker",
801+
error: String(error),
802+
};
803+
}
804+
});
805+
725806
ipcMain.handle("reveal-in-folder", async (_, filePath: string) => {
726807
try {
727808
// shell.showItemInFolder doesn't return a value, it throws on error

electron/preload.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ contextBridge.exposeInMainWorld("electronAPI", {
6767
openVideoFilePicker: () => {
6868
return ipcRenderer.invoke("open-video-file-picker");
6969
},
70+
openAudioFilePicker: () => {
71+
return ipcRenderer.invoke("open-audio-file-picker");
72+
},
7073
setCurrentVideoPath: (path: string) => {
7174
return ipcRenderer.invoke("set-current-video-path", path);
7275
},

public/audio/hooks/annotation.mp3

47 KB
Binary file not shown.

public/audio/hooks/blur.wav

174 KB
Binary file not shown.

public/audio/hooks/speed.mp3

13.1 KB
Binary file not shown.

public/audio/hooks/trim.wav

1.26 MB
Binary file not shown.

public/audio/hooks/zoom.wav

768 KB
Binary file not shown.
80.7 KB
Binary file not shown.
128 KB
Binary file not shown.

0 commit comments

Comments
 (0)