Merge pull request #307 from Ayush765-spec/main
Added the new recording button so that user does not exit the entire application
This commit is contained in:
Vendored
+2
@@ -26,6 +26,8 @@ interface Window {
|
||||
electronAPI: {
|
||||
getSources: (opts: Electron.SourcesOptions) => Promise<ProcessedDesktopSource[]>;
|
||||
switchToEditor: () => Promise<void>;
|
||||
switchToHud: () => Promise<void>;
|
||||
startNewRecording: () => Promise<{ success: boolean; error?: string }>;
|
||||
openSourceSelector: () => Promise<void>;
|
||||
selectSource: (source: ProcessedDesktopSource) => Promise<ProcessedDesktopSource | null>;
|
||||
getSelectedSource: () => Promise<ProcessedDesktopSource | null>;
|
||||
|
||||
@@ -355,7 +355,24 @@ export function registerIpcHandlers(
|
||||
getMainWindow: () => BrowserWindow | null,
|
||||
getSourceSelectorWindow: () => BrowserWindow | null,
|
||||
onRecordingStateChange?: (recording: boolean, sourceName: string) => void,
|
||||
switchToHud?: () => void,
|
||||
) {
|
||||
ipcMain.handle("switch-to-hud", () => {
|
||||
if (switchToHud) switchToHud();
|
||||
});
|
||||
ipcMain.handle("start-new-recording", async () => {
|
||||
try {
|
||||
setCurrentRecordingSessionState(null);
|
||||
if (switchToHud) {
|
||||
switchToHud();
|
||||
}
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error("Failed to start new recording:", error);
|
||||
return { success: false, error: String(error) };
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle("get-sources", async (_, opts) => {
|
||||
const sources = await desktopCapturer.getSources(opts);
|
||||
return sources.map((source) => ({
|
||||
|
||||
@@ -371,6 +371,16 @@ app.whenReady().then(async () => {
|
||||
// Ensure recordings directory exists
|
||||
await ensureRecordingsDir();
|
||||
|
||||
function switchToHudWrapper() {
|
||||
if (mainWindow) {
|
||||
isForceClosing = true;
|
||||
mainWindow.close();
|
||||
isForceClosing = false;
|
||||
mainWindow = null;
|
||||
}
|
||||
showMainWindow();
|
||||
}
|
||||
|
||||
registerIpcHandlers(
|
||||
createEditorWindowWrapper,
|
||||
createSourceSelectorWindowWrapper,
|
||||
@@ -384,6 +394,7 @@ app.whenReady().then(async () => {
|
||||
showMainWindow();
|
||||
}
|
||||
},
|
||||
switchToHudWrapper,
|
||||
);
|
||||
createWindow();
|
||||
});
|
||||
|
||||
@@ -18,6 +18,12 @@ contextBridge.exposeInMainWorld("electronAPI", {
|
||||
switchToEditor: () => {
|
||||
return ipcRenderer.invoke("switch-to-editor");
|
||||
},
|
||||
switchToHud: () => {
|
||||
return ipcRenderer.invoke("switch-to-hud");
|
||||
},
|
||||
startNewRecording: () => {
|
||||
return ipcRenderer.invoke("start-new-recording");
|
||||
},
|
||||
openSourceSelector: () => {
|
||||
return ipcRenderer.invoke("open-source-selector");
|
||||
},
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import type { Span } from "dnd-timeline";
|
||||
import { FolderOpen, Languages, Save } from "lucide-react";
|
||||
import { FolderOpen, Languages, Save, Video } from "lucide-react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { useI18n, useScopedT } from "@/contexts/I18nContext";
|
||||
import { useShortcuts } from "@/contexts/ShortcutsContext";
|
||||
import { INITIAL_EDITOR_STATE, useEditorHistory } from "@/hooks/useEditorHistory";
|
||||
@@ -117,6 +125,7 @@ export default function VideoEditor() {
|
||||
const [exportProgress, setExportProgress] = useState<ExportProgress | null>(null);
|
||||
const [exportError, setExportError] = useState<string | null>(null);
|
||||
const [showExportDialog, setShowExportDialog] = useState(false);
|
||||
const [showNewRecordingDialog, setShowNewRecordingDialog] = useState(false);
|
||||
const [exportQuality, setExportQuality] = useState<ExportQuality>("good");
|
||||
const [exportFormat, setExportFormat] = useState<ExportFormat>("mp4");
|
||||
const [gifFrameRate, setGifFrameRate] = useState<GifFrameRate>(15);
|
||||
@@ -501,6 +510,16 @@ export default function VideoEditor() {
|
||||
await saveProject(true);
|
||||
}, [saveProject]);
|
||||
|
||||
const handleNewRecordingConfirm = useCallback(async () => {
|
||||
const result = await window.electronAPI.startNewRecording();
|
||||
if (result.success) {
|
||||
setShowNewRecordingDialog(false);
|
||||
} else {
|
||||
console.error("Failed to start new recording:", result.error);
|
||||
setError("Failed to start new recording: " + (result.error || "Unknown error"));
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleLoadProject = useCallback(async () => {
|
||||
const result = await window.electronAPI.loadProjectFile();
|
||||
|
||||
@@ -1482,6 +1501,34 @@ export default function VideoEditor() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen bg-[#09090b] text-slate-200 overflow-hidden selection:bg-[#34B27B]/30">
|
||||
<Dialog open={showNewRecordingDialog} onOpenChange={setShowNewRecordingDialog}>
|
||||
<DialogContent
|
||||
className="sm:max-w-[425px]"
|
||||
style={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t("newRecording.title")}</DialogTitle>
|
||||
<DialogDescription>{t("newRecording.description")}</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowNewRecordingDialog(false)}
|
||||
className="px-4 py-2 rounded-md bg-white/10 text-white hover:bg-white/20 text-sm font-medium transition-colors"
|
||||
>
|
||||
{t("newRecording.cancel")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleNewRecordingConfirm}
|
||||
className="px-4 py-2 rounded-md bg-[#34B27B] text-white hover:bg-[#34B27B]/90 text-sm font-medium transition-colors"
|
||||
>
|
||||
{t("newRecording.confirm")}
|
||||
</button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<div
|
||||
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"
|
||||
style={{ WebkitAppRegion: "drag" } as React.CSSProperties}
|
||||
@@ -1507,6 +1554,14 @@ export default function VideoEditor() {
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setShowNewRecordingDialog(true)}
|
||||
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"
|
||||
>
|
||||
<Video size={14} />
|
||||
{t("newRecording.title")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleLoadProject}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"newRecording": {
|
||||
"title": "Return to Recorder",
|
||||
"description": "Your current session has been saved.",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm"
|
||||
},
|
||||
"errors": {
|
||||
"noVideoLoaded": "No video loaded",
|
||||
"videoNotReady": "Video not ready",
|
||||
|
||||
Vendored
+2
@@ -19,6 +19,8 @@ interface Window {
|
||||
electronAPI: {
|
||||
getSources: (opts: Electron.SourcesOptions) => Promise<ProcessedDesktopSource[]>;
|
||||
switchToEditor: () => Promise<void>;
|
||||
switchToHud: () => Promise<void>;
|
||||
startNewRecording: () => Promise<{ success: boolean; error?: string }>;
|
||||
openSourceSelector: () => Promise<void>;
|
||||
selectSource: (source: ProcessedDesktopSource) => Promise<ProcessedDesktopSource | null>;
|
||||
getSelectedSource: () => Promise<ProcessedDesktopSource | null>;
|
||||
|
||||
Reference in New Issue
Block a user