From 8ab96e5d009735c33a53b73b826ad3434f149224 Mon Sep 17 00:00:00 2001 From: ct Date: Mon, 16 Jun 2025 13:37:57 +0800 Subject: [PATCH] Update --- .../editor/partials/canvas/video-editor.jsx | 99 ++++++++++++++++--- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/resources/js/modules/editor/partials/canvas/video-editor.jsx b/resources/js/modules/editor/partials/canvas/video-editor.jsx index 01fd660..4f58596 100644 --- a/resources/js/modules/editor/partials/canvas/video-editor.jsx +++ b/resources/js/modules/editor/partials/canvas/video-editor.jsx @@ -1,9 +1,9 @@ -// TODO: I moved the sample timeline data to a dedicated file, and delayed the loading to 1 sec with useEffect. as such, alot of the ogics are broken. I need to make sure the delayed timeline should work like normal +// Updated video-editor.jsx to use selected meme and background import { useMitt } from '@/plugins/MittContext'; +import useMediaStore from '@/stores/MediaStore'; // Add this import import useVideoEditorStore from '@/stores/VideoEditorStore'; import { useCallback, useEffect, useRef, useState } from 'react'; -import sampleTimelineElements from './sample-timeline-data'; import useVideoExport from './video-export'; import VideoPreview from './video-preview'; @@ -23,6 +23,9 @@ const VideoEditor = ({ width, height }) => { const lastUpdateRef = useRef(0); const emitter = useMitt(); + // Add MediaStore to get selected items + const { selectedMeme, selectedBackground } = useMediaStore(); + const [currentTime, setCurrentTime] = useState(0); const [isPlaying, setIsPlaying] = useState(false); const [videoElements, setVideoElements] = useState({}); @@ -44,10 +47,56 @@ const VideoEditor = ({ width, height }) => { timelineElementsRef.current = timelineElements; }, [timelineElements]); - // ✅ FIX 1: Use useEffect to automatically setup videos when timeline loads - useEffect(() => { - initTimeline(); - }, []); + // ✅ NEW: Create timeline from selected items + const createTimelineFromSelections = useCallback(() => { + const elements = []; + + // If we have a selected meme, use its duration, otherwise default to 5 seconds + const memeDuration = selectedMeme?.duration ? parseFloat(selectedMeme.duration) : 5; + + // Add background video if selected (base layer) + if (selectedBackground) { + elements.push({ + id: `bg_${selectedBackground.ids}`, + type: 'video', + source_webm: selectedBackground.media_url, // Assuming it's webm + source_mov: selectedBackground.media_url, // You might need different URLs + poster: selectedBackground.media_url, + name: 'Background', + startTime: 0, + layer: 0, + inPoint: 0, + duration: memeDuration, // Match meme duration + x: 0, + y: 0, + width: dimensions.width, + height: dimensions.height, + }); + } + + // Add meme video if selected (overlay layer) + if (selectedMeme) { + elements.push({ + id: `meme_${selectedMeme.ids}`, + type: 'video', + source_webm: selectedMeme.webm_url, + source_mov: selectedMeme.mov_url, + poster: selectedMeme.webp_url, + name: selectedMeme.name, + startTime: 0, + layer: 1, + inPoint: 0, + duration: memeDuration, + x: 50, // Offset slightly for overlay effect + y: 50, + width: dimensions.width - 100, + height: dimensions.height - 100, + }); + } + + showConsoleLogs && console.log('Created timeline from selections:', elements); + return elements; + }, [selectedMeme, selectedBackground, dimensions]); const timelineUpdateResolverRef = useRef(null); @@ -60,20 +109,29 @@ const VideoEditor = ({ width, height }) => { // Add this useEffect to resolve the promise when timeline updates useEffect(() => { - if (timelineUpdateResolverRef.current && timelineElements.length > 0) { + if (timelineUpdateResolverRef.current && timelineElements.length >= 0) { + // Changed from > 0 to >= 0 timelineUpdateResolverRef.current(); timelineUpdateResolverRef.current = null; } }, [timelineElements]); - const initTimeline = () => { + // ✅ UPDATED: Use selections instead of sample data + const initTimeline = useCallback(() => { cleanupVideos(videoElements); - setTimelineElementsAsync(sampleTimelineElements).then(() => { - showConsoleLogs && console.log('Loaded sample timeline'); + const newElements = createTimelineFromSelections(); + setTimelineElementsAsync(newElements).then(() => { + showConsoleLogs && console.log('Loaded timeline from selections'); setupVideos(); }); - }; + }, [createTimelineFromSelections, videoElements]); + + // ✅ NEW: Watch for changes in selected items and update timeline + useEffect(() => { + initTimeline(); + }, [selectedMeme, selectedBackground]); // Re-run when selections change + // ✅ FIX 3: Auto-update status when videos load useEffect(() => { setupVideoStatus(); @@ -83,7 +141,8 @@ const VideoEditor = ({ width, height }) => { setVideoIsPlaying(isPlaying); }, [isPlaying, setVideoIsPlaying]); - const totalDuration = Math.max(...timelineElements.map((el) => el.startTime + el.duration)); + // ✅ UPDATED: Calculate duration from actual timeline + const totalDuration = timelineElements.length > 0 ? Math.max(...timelineElements.map((el) => el.startTime + el.duration)) : 5; // Default fallback // Use the FFmpeg hook const { isExporting, exportProgress, exportStatus, ffmpegCommand, copyFFmpegCommand, exportVideo } = useVideoExport({ @@ -155,8 +214,19 @@ const VideoEditor = ({ width, height }) => { scaledHeight = posterHeight * scale; } - const centeredX = (maxWidth - scaledWidth) / 2; - const centeredY = (maxHeight - scaledHeight) / 2; + // ✅ UPDATED: Different positioning for background vs meme + let centeredX, centeredY; + if (element.id.startsWith('bg_')) { + // Background should fill the canvas + centeredX = 0; + centeredY = 0; + scaledWidth = maxWidth; + scaledHeight = maxHeight; + } else { + // Meme should be centered + centeredX = (maxWidth - scaledWidth) / 2; + centeredY = (maxHeight - scaledHeight) / 2; + } setTimelineElements((prev) => prev.map((el) => { @@ -215,6 +285,7 @@ const VideoEditor = ({ width, height }) => { setVideoElements(videoEls); }; + // Rest of the component remains the same... const cleanupVideos = (videosToCleanup) => { if (!videosToCleanup) return;