Update
This commit is contained in:
@@ -8,6 +8,8 @@ import useVideoExport from './video-export';
|
||||
import VideoPreview from './video-preview';
|
||||
|
||||
const VideoEditor = ({ width, height }) => {
|
||||
const [showConsoleLogs] = useState(true);
|
||||
|
||||
const [dimensions] = useState({
|
||||
width: width,
|
||||
height: height,
|
||||
@@ -15,6 +17,9 @@ const VideoEditor = ({ width, height }) => {
|
||||
|
||||
const [timelineElements, setTimelineElements] = useState([]);
|
||||
|
||||
// 🔧 FIX: Add ref to solve closure issue
|
||||
const timelineElementsRef = useRef([]);
|
||||
|
||||
const lastUpdateRef = useRef(0);
|
||||
const emitter = useMitt();
|
||||
|
||||
@@ -32,10 +37,28 @@ const VideoEditor = ({ width, height }) => {
|
||||
|
||||
const { setVideoIsPlaying } = useVideoEditorStore();
|
||||
|
||||
// 🔧 FIX: Keep ref synced with state
|
||||
useEffect(() => {
|
||||
setTimeout(() => setTimelineElements(sampleTimelineElements), 1000);
|
||||
timelineElementsRef.current = timelineElements;
|
||||
}, [timelineElements]);
|
||||
|
||||
// ✅ FIX 1: Use useEffect to automatically setup videos when timeline loads
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setTimelineElements(sampleTimelineElements);
|
||||
showConsoleLogs && console.log('Loaded sample timeline');
|
||||
|
||||
setTimeout(() => {
|
||||
setupVideos();
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
}, []);
|
||||
|
||||
// ✅ FIX 3: Auto-update status when videos load
|
||||
useEffect(() => {
|
||||
setupVideoStatus();
|
||||
}, [timelineElements, loadedVideos]);
|
||||
|
||||
useEffect(() => {
|
||||
setVideoIsPlaying(isPlaying);
|
||||
}, [isPlaying, setVideoIsPlaying]);
|
||||
@@ -49,11 +72,27 @@ const VideoEditor = ({ width, height }) => {
|
||||
totalDuration,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const setupVideos = () => {
|
||||
showConsoleLogs && console.log('setupVideos');
|
||||
|
||||
// 🔧 FIX: Read from ref instead of state to get latest data
|
||||
const elements = timelineElementsRef.current;
|
||||
|
||||
if (elements.length === 0) {
|
||||
console.log('No timeline elements to setup videos for');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Setting up videos for', elements.length, 'timeline elements');
|
||||
|
||||
const videoEls = {};
|
||||
const videoElementsData = timelineElements.filter((el) => el.type === 'video');
|
||||
const videoElementsData = elements.filter((el) => el.type === 'video');
|
||||
|
||||
console.log('Found', videoElementsData.length, 'video elements');
|
||||
|
||||
videoElementsData.forEach((element) => {
|
||||
console.log('Creating video element for:', element.id);
|
||||
|
||||
const video = document.createElement('video');
|
||||
video.crossOrigin = 'anonymous';
|
||||
video.muted = true;
|
||||
@@ -77,6 +116,8 @@ const VideoEditor = ({ width, height }) => {
|
||||
posterImg.src = element.poster;
|
||||
|
||||
posterImg.onload = () => {
|
||||
console.log('Poster loaded for:', element.id);
|
||||
|
||||
const maxWidth = dimensions.width;
|
||||
const maxHeight = dimensions.height;
|
||||
const posterWidth = posterImg.naturalWidth;
|
||||
@@ -117,11 +158,14 @@ const VideoEditor = ({ width, height }) => {
|
||||
setLoadedVideos((prev) => {
|
||||
const newSet = new Set(prev);
|
||||
newSet.add(element.id);
|
||||
console.log('Video loaded:', element.id, 'Total loaded:', newSet.size);
|
||||
return newSet;
|
||||
});
|
||||
};
|
||||
|
||||
video.addEventListener('loadedmetadata', () => {
|
||||
console.log('Video metadata loaded for:', element.id);
|
||||
|
||||
setTimelineElements((prev) =>
|
||||
prev.map((el) => {
|
||||
if (el.id === element.id && el.type === 'video') {
|
||||
@@ -147,17 +191,27 @@ const VideoEditor = ({ width, height }) => {
|
||||
videoEls[element.id] = video;
|
||||
});
|
||||
|
||||
console.log('Setting video elements:', Object.keys(videoEls));
|
||||
setVideoElements(videoEls);
|
||||
};
|
||||
|
||||
return () => {
|
||||
Object.values(videoEls).forEach((video) => {
|
||||
const cleanupVideos = (videosToCleanup) => {
|
||||
if (!videosToCleanup) return;
|
||||
|
||||
const videoArray = Array.isArray(videosToCleanup) ? videosToCleanup : Object.values(videosToCleanup);
|
||||
|
||||
videoArray.forEach((video) => {
|
||||
if (video && video.src) {
|
||||
if (!video.paused) video.pause();
|
||||
video.src = '';
|
||||
video.load();
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
video.removeEventListener('loadedmetadata', video._metadataHandler);
|
||||
video.removeEventListener('error', video._errorHandler);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const setupVideoStatus = () => {
|
||||
const videoCount = timelineElements.filter((el) => el.type === 'video').length;
|
||||
if (loadedVideos.size === videoCount && videoCount > 0) {
|
||||
setStatus('Ready to play');
|
||||
@@ -166,7 +220,7 @@ const VideoEditor = ({ width, height }) => {
|
||||
} else {
|
||||
setStatus('Ready to play');
|
||||
}
|
||||
}, [loadedVideos, timelineElements]);
|
||||
};
|
||||
|
||||
// FIXED: Removed currentTime dependency to prevent excessive recreation
|
||||
const handlePause = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user