diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx index 74bf5f9..132d6c0 100644 --- a/apps/web/src/components/editor/preview-panel.tsx +++ b/apps/web/src/components/editor/preview-panel.tsx @@ -36,7 +36,7 @@ export function PreviewPanel() { const aspectRatio = activeMediaItem?.aspectRatio || 16 / 9; const renderContent = () => { - if (!activeMediaItem || !activeClip) { + if (!activeClip) { return (
{tracks.length === 0 ? "Drop media to start editing" : "No clip at current time"} @@ -44,8 +44,26 @@ export function PreviewPanel() { ); } - // Calculate the relative time within the clip (accounting for trim) - const relativeTime = Math.max(0, currentTime - activeClip.startTime + activeClip.trimStart); + // Handle test clips without media items + if (!activeMediaItem && activeClip.mediaId === "test") { + return ( +
+
+
🎬
+

{activeClip.name}

+

Test clip for playback

+
+
+ ); + } + + if (!activeMediaItem) { + return ( +
+ Media not found +
+ ); + } if (activeMediaItem.type === "video") { return ( @@ -53,7 +71,10 @@ export function PreviewPanel() { src={activeMediaItem.url} poster={activeMediaItem.thumbnailUrl} className="w-full h-full" - startTime={relativeTime} + clipStartTime={activeClip.startTime} + trimStart={activeClip.trimStart} + trimEnd={activeClip.trimEnd} + clipDuration={activeClip.duration} key={`${activeClip.id}-${activeClip.trimStart}-${activeClip.trimEnd}`} /> ); diff --git a/apps/web/src/components/editor/timeline.tsx b/apps/web/src/components/editor/timeline.tsx index d1bb3aa..1d2df66 100644 --- a/apps/web/src/components/editor/timeline.tsx +++ b/apps/web/src/components/editor/timeline.tsx @@ -13,6 +13,8 @@ import { MoreVertical, Volume2, VolumeX, + Pause, + Play, } from "lucide-react"; import { Tooltip, @@ -31,10 +33,10 @@ export function Timeline() { // Timeline shows all tracks (video, audio, effects) and their clips. // You can drag media here to add it to your project. // Clips can be trimmed, deleted, and moved. - const { tracks, addTrack, addClipToTrack, removeTrack, toggleTrackMute, removeClipFromTrack, moveClipToTrack } = + const { tracks, addTrack, addClipToTrack, removeTrack, toggleTrackMute, removeClipFromTrack, moveClipToTrack, getTotalDuration } = useTimelineStore(); const { mediaItems, addMediaItem } = useMediaStore(); - const { currentTime, duration, seek } = usePlaybackStore(); + const { currentTime, duration, seek, setDuration, isPlaying, play, pause, toggle } = usePlaybackStore(); const [isDragOver, setIsDragOver] = useState(false); const [isProcessing, setIsProcessing] = useState(false); const [zoomLevel, setZoomLevel] = useState(1); @@ -50,6 +52,12 @@ export function Timeline() { y: number; } | null>(null); + // Update timeline duration when tracks change + useEffect(() => { + const totalDuration = getTotalDuration(); + setDuration(Math.max(totalDuration, 10)); // Minimum 10 seconds for empty timeline + }, [tracks, setDuration, getTotalDuration]); + // Close context menu on click elsewhere useEffect(() => { const handleClick = () => setContextMenu(null); @@ -208,6 +216,59 @@ export function Timeline() { {/* Toolbar */}
+ {/* Play/Pause Button */} + + + + + {isPlaying ? "Pause (Space)" : "Play (Space)"} + + +
+ + {/* Time Display */} +
+ {Math.floor(currentTime * 10) / 10}s / {Math.floor(duration * 10) / 10}s +
+ +
+ + {/* Test Clip Button - for debugging */} + {tracks.length === 0 && ( + + + + + Add a test clip to try playback + + )} + +
+