diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx
index f9f2127e..5c788b6e 100644
--- a/src/components/FileUpload.tsx
+++ b/src/components/FileUpload.tsx
@@ -9,6 +9,7 @@ import { MAX_FILE_SIZE, WARNING_FILE_SIZE } from "@/lib/types";
interface Props {
onFileSelect: (file: File) => void;
+ onClear: () => void;
currentFile: File | null;
fileError: string;
duration: number;
@@ -16,6 +17,7 @@ interface Props {
export default function FileUpload({
onFileSelect,
+ onClear,
currentFile,
fileError,
duration,
@@ -125,6 +127,13 @@ export default function FileUpload({
if (file) handleFile(file);
};
+ const handleClear = () => {
+ setError("");
+ setWarning("");
+ if (inputRef.current) inputRef.current.value = "";
+ onClear();
+ };
+
// ── File info (shown after upload) ───────────────────
const FileInfo = () => (
@@ -158,14 +167,28 @@ export default function FileUpload({
-
+
+
+
+ |
+
+
+
diff --git a/src/components/VideoEditor.tsx b/src/components/VideoEditor.tsx
index 1e4e9f0d..b95481b5 100644
--- a/src/components/VideoEditor.tsx
+++ b/src/components/VideoEditor.tsx
@@ -1,6 +1,6 @@
"use client";
-import { useState, useRef, useEffect, useMemo } from "react";
+import { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { useVideoEditor } from "@/hooks/useVideoEditor";
import { TextOverlay } from "@/lib/types";
import FileUpload from "./FileUpload";
@@ -239,6 +239,22 @@ export default function VideoEditor() {
setOpenSections((prev) => ({ ...prev, [key]: !prev[key] }));
const downloadRef = useRef(null);
+ const handleClearUpload = useCallback(() => {
+ if (status === "loading-engine" || status === "exporting") {
+ cancelExport();
+ }
+ reset();
+ setSelectedTextId(null);
+ setOpenSections({
+ resize: true,
+ trim: false,
+ rotation: false,
+ text: false,
+ audio: false,
+ export: false,
+ });
+ }, [reset, cancelExport, status]);
+
/**
* Updates a text overlay property and syncs with recipe.
*/
@@ -370,7 +386,13 @@ export default function VideoEditor() {
-
+
{!file && (
diff --git a/src/hooks/useVideoEditor.ts b/src/hooks/useVideoEditor.ts
index a86c35f2..38cc6b86 100644
--- a/src/hooks/useVideoEditor.ts
+++ b/src/hooks/useVideoEditor.ts
@@ -640,18 +640,49 @@ export function useVideoEditor() {
const reset = useCallback(() => {
+ exportCancelledRef.current = true;
+ exportAbortControllerRef.current?.abort();
+ exportAbortControllerRef.current = null;
+ terminateFFmpeg();
+
if (result?.blobUrl) URL.revokeObjectURL(result.blobUrl);
+
setFile(null);
setVideoMetadata(null);
setDuration(0);
- setRecipe(DEFAULT_RECIPE);
+ setCurrentTime(0);
+ setFileError("");
+ setRecipe({
+ ...DEFAULT_RECIPE,
+ soundOnCompletion:
+ typeof window !== "undefined" &&
+ localStorage.getItem("soundOnCompletion") === "true",
+ });
setStatus("idle");
setProgress(0);
setResult(null);
setError(null);
setExportStartedAt(null);
+
+ setMusicFile(null);
+ setMusicVolume(70);
+ setOriginalAudioVolume(40);
+ setLoopMusic(false);
+ setOverlayFile(null);
+ setOverlayPosition("bottom-right");
+ setOverlaySize(150);
+ setOverlayOpacity(100);
+
+ const video = videoRef.current;
+ if (video) {
+ video.pause();
+ video.removeAttribute("src");
+ video.load();
+ }
+
try {
localStorage.removeItem(STORAGE_KEY);
+ localStorage.removeItem("reframe-settings");
} catch {
// ignore
}