Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 39 additions & 93 deletions src/mainview/App.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,34 @@
import { useLayoutEffect, useRef, useState } from "react";
import { useVideoEditor } from "./hooks/useVideoEditor";
import { Header } from "./components/Header";
import { DownloadPage } from "./components/DownloadPage";
import { LandingPage } from "./components/LandingPage";
import { EditorPage } from "./components/EditorPage";
import { OUTPUT_FORMATS } from "./constants";
import { VideoEditorProvider } from "./context/VideoEditorContext";

const App = () => {
const editorState = useVideoEditor();
const {
videoSrc,
position,
setPosition,
isPlaying,
setIsPlaying,
start,
setStart,
end,
setEnd,
videoDuration,
reencode,
setReencode,
outputFormat,
setOutputFormat,
bitrate,
setBitrate,
clipDuration,
outputWidth,
setOutputWidth,
outputHeight,
setOutputHeight,
originalWidth,
originalHeight,
lockAspectRatio,
setLockAspectRatio,
originalFps,
outputFps,
setOutputFps,
useNativeExport,
hasHwAccSupport,
hwAcc,
setHwAcc,
exporting,
exportProgress,
exportError,
exportSuccess,
currentPage,
setCurrentPage,
handleFileSelect,
handleNativeBrowse,
handleChangeVideo,
exportVideo,
isConverting,
} = useVideoEditor();
} = editorState;

const cardRef = useRef<HTMLDivElement>(null);
const [cardHeight, setCardHeight] = useState<number | undefined>(undefined);

useLayoutEffect(() => {
const element = cardRef.current;
if (element) {
const newHeight = element.offsetHeight;
if (newHeight !== cardHeight) {
setCardHeight(newHeight);
}
}
});
Comment on lines +23 to +31

return (
<div className="flex flex-col bg-mocha-base min-h-screen text-mocha-text relative overflow-hidden">
Expand All @@ -70,65 +48,33 @@ const App = () => {
{currentPage === "download" || !videoSrc ? (
<div className="flex-1 flex flex-col items-center justify-center p-6 relative z-10 w-full">
<div
className={`bg-mocha-surface0/60 backdrop-blur-md rounded-2xl border border-mocha-surface0 shadow-2xl w-full transition-all relative overflow-hidden ${
currentPage === "download"
? "max-w-3xl p-6 md:p-10"
: "max-w-2xl p-8 md:p-12"
className={`bg-mocha-surface0/60 backdrop-blur-md rounded-2xl border border-mocha-surface0 shadow-2xl w-full transition-all ease-in-out relative overflow-hidden ${
currentPage === "download" ? "max-w-3xl" : "max-w-2xl"
}`}
style={{ height: cardHeight ? `${cardHeight}px` : "auto" }}
>
{currentPage === "download" ? (
<DownloadPage onNavigateEditor={() => setCurrentPage("editor")} />
) : (
<LandingPage
onFileSelect={handleFileSelect}
onNativeBrowse={handleNativeBrowse}
onNavigateDownload={() => setCurrentPage("download")}
/>
)}
<div
ref={cardRef}
className={`w-full transition-all duration-500 ease-in-out ${
currentPage === "download" ? "p-6 md:p-10" : "p-8 md:p-12"
}`}
>
{currentPage === "download" ? (
<DownloadPage onNavigateEditor={() => setCurrentPage("editor")} />
) : (
<LandingPage
onFileSelect={handleFileSelect}
onNativeBrowse={handleNativeBrowse}
onNavigateDownload={() => setCurrentPage("download")}
/>
)}
</div>
</div>
</div>
) : (
<EditorPage
videoSrc={videoSrc}
position={position}
setPosition={setPosition}
isPlaying={isPlaying}
setIsPlaying={setIsPlaying}
start={start}
setStart={setStart}
end={end}
setEnd={setEnd}
videoDuration={videoDuration}
reencode={reencode}
setReencode={setReencode}
outputFormat={outputFormat}
setOutputFormat={setOutputFormat}
outputFormats={OUTPUT_FORMATS}
isConverting={isConverting}
bitrate={bitrate}
setBitrate={setBitrate}
clipDuration={clipDuration}
outputWidth={outputWidth}
setOutputWidth={setOutputWidth}
outputHeight={outputHeight}
setOutputHeight={setOutputHeight}
originalWidth={originalWidth}
originalHeight={originalHeight}
lockAspectRatio={lockAspectRatio}
setLockAspectRatio={setLockAspectRatio}
originalFps={originalFps}
outputFps={outputFps}
setOutputFps={setOutputFps}
useNativeExport={useNativeExport}
hasHwAccSupport={hasHwAccSupport}
hwAcc={hwAcc}
setHwAcc={setHwAcc}
exporting={exporting}
exportProgress={exportProgress}
exportError={exportError}
exportSuccess={exportSuccess}
onExport={exportVideo}
/>
<VideoEditorProvider value={editorState}>
<EditorPage />
</VideoEditorProvider>
)}
</div>
);
Expand Down
152 changes: 5 additions & 147 deletions src/mainview/components/EditorPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,166 +3,24 @@ import { Timeline } from "./Timeline";
import { EncoderSettings } from "./EncoderSettings";
import { ExportPanel } from "./ExportPanel";

interface OutputFormat {
readonly label: string;
readonly ext: string;
readonly mime: string;
}

interface EditorPageProps {
// Video & playback
videoSrc: string;
position: number;
setPosition: (value: number) => void;
isPlaying: boolean;
setIsPlaying: (value: boolean) => void;
start: number;
setStart: (value: number) => void;
end: number;
setEnd: (value: number) => void;
videoDuration: number;

// Encoder settings
reencode: boolean;
setReencode: (value: boolean) => void;
outputFormat: string;
setOutputFormat: (value: string) => void;
outputFormats: readonly OutputFormat[];
isConverting: boolean;
bitrate: number;
setBitrate: (value: number) => void;
clipDuration: number;
outputWidth: number;
setOutputWidth: (value: number) => void;
outputHeight: number;
setOutputHeight: (value: number) => void;
originalWidth: number;
originalHeight: number;
lockAspectRatio: boolean;
setLockAspectRatio: (value: boolean) => void;
originalFps: number | null;
outputFps: number | null;
setOutputFps: (value: number | null) => void;
useNativeExport: boolean;
hasHwAccSupport: boolean;
hwAcc: boolean;
setHwAcc: (value: boolean) => void;

// Export
exporting: boolean;
exportProgress: number;
exportError: string | null;
exportSuccess: string | null;
onExport: () => void;
}

export const EditorPage = ({
videoSrc,
position,
setPosition,
isPlaying,
setIsPlaying,
start,
setStart,
end,
setEnd,
videoDuration,
reencode,
setReencode,
outputFormat,
setOutputFormat,
outputFormats,
isConverting,
bitrate,
setBitrate,
clipDuration,
outputWidth,
setOutputWidth,
outputHeight,
setOutputHeight,
originalWidth,
originalHeight,
lockAspectRatio,
setLockAspectRatio,
originalFps,
outputFps,
setOutputFps,
useNativeExport,
hasHwAccSupport,
hwAcc,
setHwAcc,
exporting,
exportProgress,
exportError,
exportSuccess,
onExport,
}: EditorPageProps) => (
export const EditorPage = () => (
<main className="flex-1 p-6 flex flex-col lg:flex-row gap-6 max-w-7xl w-full mx-auto relative z-10">
{/* Left column: Player + Timeline */}
<div className="flex-1 flex flex-col gap-6">
<Player
videoSrc={videoSrc}
positionState={{ position, setPosition }}
isPlayingState={{ isPlaying, setIsPlaying }}
startState={{ start, setStart }}
endState={{ end, setEnd }}
videoDuration={videoDuration}
/>
<Player />

<div className="bg-mocha-surface0 rounded-xl p-5 border border-mocha-surface0 shadow-lg">
<h3 className="text-xs font-semibold uppercase tracking-wider text-mocha-subtext0 mb-4 select-none">
Timeline & Trim Controls
</h3>
<Timeline
startState={{ start, setStart }}
endState={{ end, setEnd }}
positionState={{ position, setPosition }}
videoDuration={videoDuration}
/>
<Timeline />
</div>
</div>

{/* Right column: Encoder & Export Settings Sidebar */}
<div className="w-full lg:w-80 flex flex-col gap-6">
<EncoderSettings
reencode={reencode}
setReencode={setReencode}
outputFormat={outputFormat}
setOutputFormat={setOutputFormat}
outputFormats={outputFormats}
isConverting={isConverting}
bitrate={bitrate}
setBitrate={setBitrate}
clipDuration={clipDuration}
outputWidth={outputWidth}
setOutputWidth={setOutputWidth}
outputHeight={outputHeight}
setOutputHeight={setOutputHeight}
originalWidth={originalWidth}
originalHeight={originalHeight}
lockAspectRatio={lockAspectRatio}
setLockAspectRatio={setLockAspectRatio}
originalFps={originalFps}
outputFps={outputFps}
setOutputFps={setOutputFps}
useNativeExport={useNativeExport}
hasHwAccSupport={hasHwAccSupport}
hwAcc={hwAcc}
setHwAcc={setHwAcc}
/>

<ExportPanel
start={start}
end={end}
videoDuration={videoDuration}
outputFormat={outputFormat}
exporting={exporting}
exportProgress={exportProgress}
exportError={exportError}
exportSuccess={exportSuccess}
useNativeExport={useNativeExport}
onExport={onExport}
/>
<EncoderSettings />
<ExportPanel />
</div>
</main>
);
Loading
Loading