From c02f276303e00f4d8c66d8d1c804c4af9c719afb Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 9 Jul 2025 21:03:56 +0200 Subject: refactor: fresh properties panel --- .../web/src/components/editor/timeline-element.tsx | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'apps/web/src/components/editor/timeline-element.tsx') diff --git a/apps/web/src/components/editor/timeline-element.tsx b/apps/web/src/components/editor/timeline-element.tsx index 1e1674bf..c1c8b12b 100644 --- a/apps/web/src/components/editor/timeline-element.tsx +++ b/apps/web/src/components/editor/timeline-element.tsx @@ -12,6 +12,7 @@ import { ChevronLeft, Type, Copy, + RefreshCw, } from "lucide-react"; import { useMediaStore } from "@/stores/media-store"; import { useTimelineStore } from "@/stores/timeline-store"; @@ -61,6 +62,7 @@ export function TimelineElement({ splitAndKeepRight, separateAudio, addElementToTrack, + replaceElementMedia, } = useTimelineStore(); const { currentTime } = usePlaybackStore(); @@ -213,6 +215,37 @@ export function TimelineElement({ removeElementFromTrack(track.id, element.id); }; + const handleReplaceClip = () => { + if (element.type !== "media") { + toast.error("Replace is only available for media clips"); + return; + } + + // Create a file input to select replacement media + const input = document.createElement("input"); + input.type = "file"; + input.accept = "video/*,audio/*,image/*"; + input.onchange = async (e) => { + const file = (e.target as HTMLInputElement).files?.[0]; + if (!file) return; + + try { + const success = await replaceElementMedia(track.id, element.id, file); + if (success) { + toast.success("Clip replaced successfully"); + } else { + toast.error("Failed to replace clip"); + } + } catch (error) { + toast.error("Failed to replace clip"); + console.log( + JSON.stringify({ error: "Failed to replace clip", details: error }) + ); + } + }; + input.click(); + }; + const renderElementContent = () => { if (element.type === "text") { return ( @@ -350,6 +383,12 @@ export function TimelineElement({ Duplicate {element.type === "text" ? "text" : "clip"} + {element.type === "media" && ( + + + Replace clip + + )}