From 112f02fe032de8a970cd9d022032bd959f5cbb9f Mon Sep 17 00:00:00 2001 From: moncef Date: Tue, 7 Apr 2026 00:30:23 +0100 Subject: [PATCH 1/4] feat: implement video editor timeline components with interactive zoom, trim, and speed region controls. --- src/components/video-editor/SettingsPanel.tsx | 47 ++++++++- src/components/video-editor/VideoEditor.tsx | 31 +++++- src/components/video-editor/timeline/Item.tsx | 99 ++++++++++++++++++- .../video-editor/timeline/TimelineEditor.tsx | 12 +++ src/components/video-editor/types.ts | 2 + .../videoPlayback/zoomRegionUtils.ts | 33 ++++--- src/i18n/locales/en/settings.json | 7 ++ src/i18n/locales/es/settings.json | 7 ++ src/i18n/locales/zh-CN/settings.json | 7 ++ 9 files changed, 230 insertions(+), 15 deletions(-) diff --git a/src/components/video-editor/SettingsPanel.tsx b/src/components/video-editor/SettingsPanel.tsx index 7e556b8..34adddd 100644 --- a/src/components/video-editor/SettingsPanel.tsx +++ b/src/components/video-editor/SettingsPanel.tsx @@ -150,6 +150,9 @@ interface SettingsPanelProps { onWebcamLayoutPresetChange?: (preset: WebcamLayoutPreset) => void; webcamMaskShape?: import("./types").WebcamMaskShape; onWebcamMaskShapeChange?: (shape: import("./types").WebcamMaskShape) => void; + selectedZoomInDuration?: number; + selectedZoomOutDuration?: number; + onZoomDurationChange?: (zoomIn: number, zoomOut: number) => void; } export default SettingsPanel; @@ -163,6 +166,14 @@ const ZOOM_DEPTH_OPTIONS: Array<{ depth: ZoomDepth; label: string }> = [ { depth: 6, label: "5×" }, ]; +// TODO: make this configurable +const ZOOM_SPEED_OPTIONS = [ + { label: "Instant", zoomIn: 0, zoomOut: 0 }, + { label: "Fast", zoomIn: 500, zoomOut: 350 }, + { label: "Smooth", zoomIn: 1522, zoomOut: 1015 }, + { label: "Lazy", zoomIn: 3000, zoomOut: 2000 }, +]; + export function SettingsPanel({ selected, onWallpaperChange, @@ -223,6 +234,9 @@ export function SettingsPanel({ onWebcamLayoutPresetChange, webcamMaskShape = "rectangle", onWebcamMaskShapeChange, + selectedZoomInDuration, + selectedZoomOutDuration, + onZoomDurationChange, }: SettingsPanelProps) { const t = useScopedT("settings"); const [wallpaperPaths, setWallpaperPaths] = useState([]); @@ -547,6 +561,37 @@ export function SettingsPanel({ )} )} + + {zoomEnabled && ( +
+ + {t("zoom.speed.title") || "Zoom Speed"} + +
+ {ZOOM_SPEED_OPTIONS.map((opt) => { + const isActive = + selectedZoomInDuration === opt.zoomIn && + selectedZoomOutDuration === opt.zoomOut; + return ( + + ); + })} +
+
+ )} {zoomEnabled && (