From 2caa0ba887d207fc67a40a47ae9d56b3982b9e61 Mon Sep 17 00:00:00 2001 From: YLaxmikanth Date: Wed, 3 Jun 2026 22:55:59 +0530 Subject: [PATCH] feat: improve editor layout and control organization --- src/components/VideoEditor.tsx | 272 ++++++++++---------------------- src/components/VideoPreview.tsx | 127 ++++++++------- 2 files changed, 148 insertions(+), 251 deletions(-) diff --git a/src/components/VideoEditor.tsx b/src/components/VideoEditor.tsx index e3563037..716b4c39 100644 --- a/src/components/VideoEditor.tsx +++ b/src/components/VideoEditor.tsx @@ -226,21 +226,20 @@ export default function VideoEditor() { const [copied, setCopied] = useState(false); const [shareCopied, setShareCopied] = useState(false); useEffect(() => { - if (!file) return; - - localStorage.setItem( - "editorState", - JSON.stringify({ - recipe, - overlayPosition, - overlaySize, - overlayOpacity, - }) - ); -}, [recipe, overlayPosition, overlaySize, overlayOpacity, file]); + if (!file) return; + + localStorage.setItem( + "editorState", + JSON.stringify({ + recipe, + overlayPosition, + overlaySize, + overlayOpacity, + }) + ); + }, [recipe, overlayPosition, overlaySize, overlayOpacity, file]); const [selectedTextId, setSelectedTextId] = useState(null); const [openSections, setOpenSections] = useState({ - resize: true, trim: false, rotation: false, text: false, @@ -248,32 +247,32 @@ export default function VideoEditor() { export: false, }); useEffect(() => { - const saved = localStorage.getItem("editorState"); + const saved = localStorage.getItem("editorState"); - if (!saved) return; + if (!saved) return; - try { - const parsed = JSON.parse(saved); + try { + const parsed = JSON.parse(saved); - if (parsed.recipe) { - updateRecipe(parsed.recipe); - } + if (parsed.recipe) { + updateRecipe(parsed.recipe); + } - if (parsed.overlayPosition) { - setOverlayPosition(parsed.overlayPosition); - } + if (parsed.overlayPosition) { + setOverlayPosition(parsed.overlayPosition); + } - if (parsed.overlaySize) { - setOverlaySize(parsed.overlaySize); - } + if (parsed.overlaySize) { + setOverlaySize(parsed.overlaySize); + } - if (parsed.overlayOpacity) { - setOverlayOpacity(parsed.overlayOpacity); + if (parsed.overlayOpacity) { + setOverlayOpacity(parsed.overlayOpacity); + } + } catch (err) { + console.error("Failed to restore editor state", err); } - } catch (err) { - console.error("Failed to restore editor state", err); - } -}, []); + }, [setOverlayOpacity, setOverlayPosition, setOverlaySize, updateRecipe]); const toggleSection = (key: keyof typeof openSections) => setOpenSections((prev) => ({ ...prev, [key]: !prev[key] })); @@ -380,7 +379,7 @@ return () => {
-
+
{
No login. No ads. 100% private - your video never leaves your device.
-
+
-
-
+
+
{!file && ( -
+

Upload a video to get started

Supports MP4, MOV, WebM and more

)} {file && ( -
+
{ onUpdateText={handleUpdateTextOverlay} /> -
+
{

)} {file && ( -
-
- } - title="Trim" - isOpen={openSections.trim} - onToggle={() => toggleSection("trim")} - delay={50} - > - +
+
+
+
+

Core edits

+

Trim, rotate, text, and audio controls.

+
+
+ } title="Trim" isOpen={openSections.trim} onToggle={() => toggleSection("trim")} delay={50}> + - - } - title="Rotation" - isOpen={openSections.rotation} - onToggle={() => toggleSection("rotation")} - delay={100} - > + } title="Rotation" isOpen={openSections.rotation} onToggle={() => toggleSection("rotation")} delay={100}> - - } - title="Text Overlay" - isOpen={openSections.text} - onToggle={() => toggleSection("text")} - delay={110} - > - + } title="Text Overlay" isOpen={openSections.text} onToggle={() => toggleSection("text")} delay={110}> + -
-
- } - title="Audio & Speed" - isOpen={openSections.audio} - onToggle={() => toggleSection("audio")} - delay={150} - > + } title="Audio & Speed" isOpen={openSections.audio} onToggle={() => toggleSection("audio")} delay={150}> -
} - title="Adjustments" - delay={175} - > +
+ +
+
+

Output setup

+

Choose the target format, frame, overlays, and export options.

+
+
} title="Resize & Aspect Ratio" delay={50}> + {recommendedPreset && ( +
+

+ We detected a {recommendedPreset.label.replace(/\s/g, "")} video → Recommended: {(recommendedPreset.platform.split("·")[0] ?? "").trim()} ({recommendedPreset.label.replace(/\s/g, "")}) +

+
+ )} +
+ + +
+
+
} title="Adjustments" delay={175}>
- {/* Brightness */}
-
- updateRecipe({ brightness: Number(e.target.value) })} - aria-label="Adjust brightness" - className="w-full accent-film-600" - /> + updateRecipe({ brightness: Number(e.target.value) })} aria-label="Adjust brightness" className="w-full accent-film-600" />
- {/* Contrast */}
-
- updateRecipe({ contrast: Number(e.target.value) })} - aria-label="Adjust contrast" - className="w-full accent-film-600" - /> + updateRecipe({ contrast: Number(e.target.value) })} aria-label="Adjust contrast" className="w-full accent-film-600" />
- {/* Saturation */}
-
- updateRecipe({ saturation: Number(e.target.value) })} - aria-label="Adjust saturation" - className="w-full accent-film-600" - /> + updateRecipe({ saturation: Number(e.target.value) })} aria-label="Adjust saturation" className="w-full accent-film-600" />
} title="Output format" delay={190}>
- } - title="Export" - isOpen={openSections.export} - onToggle={() => toggleSection("export")} - delay={200} - > - -
} title="Image overlay" delay={120}> { setOverlayOpacity={setOverlayOpacity} />
+ } title="Export" isOpen={openSections.export} onToggle={() => toggleSection("export")} delay={200}> + +
)} @@ -682,7 +603,7 @@ return () => {
{!file && ( @@ -695,29 +616,8 @@ return () => {

)} -
- } - title="Resize & Aspect Ratio" - isOpen={openSections.resize} - onToggle={() => toggleSection("resize")} - delay={50} - > - {recommendedPreset && ( -
-

- We detected a {recommendedPreset.label.replace(/\s/g, "")} video → Recommended: {(recommendedPreset.platform.split("·")[0] ?? "").trim()} ({recommendedPreset.label.replace(/\s/g, "")}) -

-
- )} -
- - -
-
- -
+
+
- )} - - {/* Grid overlay button */} - {recipe && !isLoading && ( - - )} - - {/* Compare button */} - {recipe && !isLoading && ( - - )} - - {/* Grab frame button */} - {!isLoading && ( - +
+
+ + + +
+ +
+ + + +
+
)}