Skip to content

Commit 9024eaa

Browse files
Merge pull request #307 from Ayush765-spec/main
Added the new recording button so that user does not exit the entire application
2 parents c5882b0 + 013312b commit 9024eaa

7 files changed

Lines changed: 100 additions & 1 deletion

File tree

electron/electron-env.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ interface Window {
2626
electronAPI: {
2727
getSources: (opts: Electron.SourcesOptions) => Promise<ProcessedDesktopSource[]>;
2828
switchToEditor: () => Promise<void>;
29+
switchToHud: () => Promise<void>;
30+
startNewRecording: () => Promise<{ success: boolean; error?: string }>;
2931
openSourceSelector: () => Promise<void>;
3032
selectSource: (source: ProcessedDesktopSource) => Promise<ProcessedDesktopSource | null>;
3133
getSelectedSource: () => Promise<ProcessedDesktopSource | null>;

electron/ipc/handlers.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,24 @@ export function registerIpcHandlers(
355355
getMainWindow: () => BrowserWindow | null,
356356
getSourceSelectorWindow: () => BrowserWindow | null,
357357
onRecordingStateChange?: (recording: boolean, sourceName: string) => void,
358+
switchToHud?: () => void,
358359
) {
360+
ipcMain.handle("switch-to-hud", () => {
361+
if (switchToHud) switchToHud();
362+
});
363+
ipcMain.handle("start-new-recording", async () => {
364+
try {
365+
setCurrentRecordingSessionState(null);
366+
if (switchToHud) {
367+
switchToHud();
368+
}
369+
return { success: true };
370+
} catch (error) {
371+
console.error("Failed to start new recording:", error);
372+
return { success: false, error: String(error) };
373+
}
374+
});
375+
359376
ipcMain.handle("get-sources", async (_, opts) => {
360377
const sources = await desktopCapturer.getSources(opts);
361378
return sources.map((source) => ({

electron/main.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,16 @@ app.whenReady().then(async () => {
371371
// Ensure recordings directory exists
372372
await ensureRecordingsDir();
373373

374+
function switchToHudWrapper() {
375+
if (mainWindow) {
376+
isForceClosing = true;
377+
mainWindow.close();
378+
isForceClosing = false;
379+
mainWindow = null;
380+
}
381+
showMainWindow();
382+
}
383+
374384
registerIpcHandlers(
375385
createEditorWindowWrapper,
376386
createSourceSelectorWindowWrapper,
@@ -384,6 +394,7 @@ app.whenReady().then(async () => {
384394
showMainWindow();
385395
}
386396
},
397+
switchToHudWrapper,
387398
);
388399
createWindow();
389400
});

electron/preload.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ contextBridge.exposeInMainWorld("electronAPI", {
1818
switchToEditor: () => {
1919
return ipcRenderer.invoke("switch-to-editor");
2020
},
21+
switchToHud: () => {
22+
return ipcRenderer.invoke("switch-to-hud");
23+
},
24+
startNewRecording: () => {
25+
return ipcRenderer.invoke("start-new-recording");
26+
},
2127
openSourceSelector: () => {
2228
return ipcRenderer.invoke("open-source-selector");
2329
},

src/components/video-editor/VideoEditor.tsx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
import type { Span } from "dnd-timeline";
2-
import { FolderOpen, Languages, Save } from "lucide-react";
2+
import { FolderOpen, Languages, Save, Video } from "lucide-react";
33
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
44
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
55
import { toast } from "sonner";
6+
import {
7+
Dialog,
8+
DialogContent,
9+
DialogDescription,
10+
DialogFooter,
11+
DialogHeader,
12+
DialogTitle,
13+
} from "@/components/ui/dialog";
614
import { useI18n, useScopedT } from "@/contexts/I18nContext";
715
import { useShortcuts } from "@/contexts/ShortcutsContext";
816
import { INITIAL_EDITOR_STATE, useEditorHistory } from "@/hooks/useEditorHistory";
@@ -117,6 +125,7 @@ export default function VideoEditor() {
117125
const [exportProgress, setExportProgress] = useState<ExportProgress | null>(null);
118126
const [exportError, setExportError] = useState<string | null>(null);
119127
const [showExportDialog, setShowExportDialog] = useState(false);
128+
const [showNewRecordingDialog, setShowNewRecordingDialog] = useState(false);
120129
const [exportQuality, setExportQuality] = useState<ExportQuality>("good");
121130
const [exportFormat, setExportFormat] = useState<ExportFormat>("mp4");
122131
const [gifFrameRate, setGifFrameRate] = useState<GifFrameRate>(15);
@@ -501,6 +510,16 @@ export default function VideoEditor() {
501510
await saveProject(true);
502511
}, [saveProject]);
503512

513+
const handleNewRecordingConfirm = useCallback(async () => {
514+
const result = await window.electronAPI.startNewRecording();
515+
if (result.success) {
516+
setShowNewRecordingDialog(false);
517+
} else {
518+
console.error("Failed to start new recording:", result.error);
519+
setError("Failed to start new recording: " + (result.error || "Unknown error"));
520+
}
521+
}, []);
522+
504523
const handleLoadProject = useCallback(async () => {
505524
const result = await window.electronAPI.loadProjectFile();
506525

@@ -1482,6 +1501,34 @@ export default function VideoEditor() {
14821501

14831502
return (
14841503
<div className="flex flex-col h-screen bg-[#09090b] text-slate-200 overflow-hidden selection:bg-[#34B27B]/30">
1504+
<Dialog open={showNewRecordingDialog} onOpenChange={setShowNewRecordingDialog}>
1505+
<DialogContent
1506+
className="sm:max-w-[425px]"
1507+
style={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
1508+
>
1509+
<DialogHeader>
1510+
<DialogTitle>{t("newRecording.title")}</DialogTitle>
1511+
<DialogDescription>{t("newRecording.description")}</DialogDescription>
1512+
</DialogHeader>
1513+
<DialogFooter>
1514+
<button
1515+
type="button"
1516+
onClick={() => setShowNewRecordingDialog(false)}
1517+
className="px-4 py-2 rounded-md bg-white/10 text-white hover:bg-white/20 text-sm font-medium transition-colors"
1518+
>
1519+
{t("newRecording.cancel")}
1520+
</button>
1521+
<button
1522+
type="button"
1523+
onClick={handleNewRecordingConfirm}
1524+
className="px-4 py-2 rounded-md bg-[#34B27B] text-white hover:bg-[#34B27B]/90 text-sm font-medium transition-colors"
1525+
>
1526+
{t("newRecording.confirm")}
1527+
</button>
1528+
</DialogFooter>
1529+
</DialogContent>
1530+
</Dialog>
1531+
14851532
<div
14861533
className="h-10 flex-shrink-0 bg-[#09090b]/80 backdrop-blur-md border-b border-white/5 flex items-center justify-between px-6 z-50"
14871534
style={{ WebkitAppRegion: "drag" } as React.CSSProperties}
@@ -1507,6 +1554,14 @@ export default function VideoEditor() {
15071554
))}
15081555
</select>
15091556
</div>
1557+
<button
1558+
type="button"
1559+
onClick={() => setShowNewRecordingDialog(true)}
1560+
className="flex items-center gap-1 px-2 py-1 rounded-md text-white/50 hover:text-white/90 hover:bg-white/10 transition-all duration-150 text-[11px] font-medium"
1561+
>
1562+
<Video size={14} />
1563+
{t("newRecording.title")}
1564+
</button>
15101565
<button
15111566
type="button"
15121567
onClick={handleLoadProject}

src/i18n/locales/en/editor.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
{
2+
"newRecording": {
3+
"title": "Return to Recorder",
4+
"description": "Your current session has been saved.",
5+
"cancel": "Cancel",
6+
"confirm": "Confirm"
7+
},
28
"errors": {
39
"noVideoLoaded": "No video loaded",
410
"videoNotReady": "Video not ready",

src/vite-env.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ interface Window {
1919
electronAPI: {
2020
getSources: (opts: Electron.SourcesOptions) => Promise<ProcessedDesktopSource[]>;
2121
switchToEditor: () => Promise<void>;
22+
switchToHud: () => Promise<void>;
23+
startNewRecording: () => Promise<{ success: boolean; error?: string }>;
2224
openSourceSelector: () => Promise<void>;
2325
selectSource: (source: ProcessedDesktopSource) => Promise<ProcessedDesktopSource | null>;
2426
getSelectedSource: () => Promise<ProcessedDesktopSource | null>;

0 commit comments

Comments
 (0)