mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-11 09:58:53 -05:00
feat: In Preview mode, you can jump in timeline to review the edits
In Preview mode, you can jump in timeline to review the edits, without having to listen to the full video.
This commit is contained in:
parent
c989b1515e
commit
321287d009
@ -1201,20 +1201,51 @@ const TimelineControls = ({
|
|||||||
setActiveSegment(segmentAtClickedTime);
|
setActiveSegment(segmentAtClickedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resume playback in two cases:
|
// Resume playback based on the current mode
|
||||||
// 1. If it was playing before (regular playback)
|
if (videoRef.current) {
|
||||||
// 2. If we're in preview mode (regardless of previous playing state)
|
// Special handling for segments playback mode
|
||||||
if ((wasPlaying || isPreviewMode) && videoRef.current) {
|
if (isPlayingSegments && wasPlaying) {
|
||||||
logger.debug("Resuming playback after timeline click");
|
// Update the current segment index if we clicked into a segment
|
||||||
videoRef.current.play()
|
if (segmentAtClickedTime) {
|
||||||
.then(() => {
|
const orderedSegments = [...clipSegments].sort((a, b) => a.startTime - b.startTime);
|
||||||
setIsPlayingSegment(true);
|
const targetSegmentIndex = orderedSegments.findIndex(seg => seg.id === segmentAtClickedTime.id);
|
||||||
logger.debug("Resumed playback after seeking");
|
|
||||||
})
|
if (targetSegmentIndex !== -1) {
|
||||||
.catch(err => {
|
// Dispatch a custom event to update the current segment index
|
||||||
console.error("Error resuming playback:", err);
|
const updateSegmentIndexEvent = new CustomEvent('update-segment-index', {
|
||||||
setIsPlayingSegment(false);
|
detail: { segmentIndex: targetSegmentIndex }
|
||||||
});
|
});
|
||||||
|
document.dispatchEvent(updateSegmentIndexEvent);
|
||||||
|
logger.debug(`Segments playback mode: updating segment index to ${targetSegmentIndex} for timeline click in segment ${segmentAtClickedTime.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Segments playback mode: resuming playback after timeline click");
|
||||||
|
videoRef.current.play()
|
||||||
|
.then(() => {
|
||||||
|
setIsPlayingSegment(true);
|
||||||
|
logger.debug("Resumed segments playback after timeline seeking");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error resuming segments playback:", err);
|
||||||
|
setIsPlayingSegment(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Resume playback in two cases (but not during segments playback):
|
||||||
|
// 1. If it was playing before (regular playback)
|
||||||
|
// 2. If we're in preview mode (regardless of previous playing state)
|
||||||
|
else if ((wasPlaying || isPreviewMode) && !isPlayingSegments) {
|
||||||
|
logger.debug("Resuming playback after timeline click");
|
||||||
|
videoRef.current.play()
|
||||||
|
.then(() => {
|
||||||
|
setIsPlayingSegment(true);
|
||||||
|
logger.debug("Resumed playback after seeking");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error resuming playback:", err);
|
||||||
|
setIsPlayingSegment(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only process tooltip display if clicked on the timeline background or thumbnails, not on other UI elements
|
// Only process tooltip display if clicked on the timeline background or thumbnails, not on other UI elements
|
||||||
@ -1678,34 +1709,63 @@ const TimelineControls = ({
|
|||||||
// Seek to this position (this will update the video's current time)
|
// Seek to this position (this will update the video's current time)
|
||||||
onSeek(boundedTime);
|
onSeek(boundedTime);
|
||||||
|
|
||||||
// If video was playing before OR we're in preview mode, ensure it continues playing
|
// Handle playback continuation based on the current mode
|
||||||
if ((wasPlaying || isPreviewMode) && videoRef.current) {
|
if (videoRef.current) {
|
||||||
// Set current segment as active segment for boundary checking
|
// Special handling for segments playback mode
|
||||||
setActiveSegment(segment);
|
if (isPlayingSegments && wasPlaying) {
|
||||||
// Reset the continuePastBoundary flag when clicking on a segment to ensure boundaries work
|
// Update the current segment index for segments playback mode
|
||||||
setContinuePastBoundary(false);
|
const orderedSegments = [...clipSegments].sort((a, b) => a.startTime - b.startTime);
|
||||||
// Continue playing from the new position
|
const targetSegmentIndex = orderedSegments.findIndex(seg => seg.id === segmentId);
|
||||||
videoRef.current.play()
|
|
||||||
.then(() => {
|
|
||||||
setIsPlayingSegment(true);
|
|
||||||
logger.debug("Continued preview playback after segment click");
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error("Error resuming playback after segment click:", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always continue playback in preview mode, even if video was paused when clicking
|
if (targetSegmentIndex !== -1) {
|
||||||
if (isPreviewMode && videoRef.current) {
|
// Dispatch a custom event to update the current segment index
|
||||||
setActiveSegment(segment);
|
const updateSegmentIndexEvent = new CustomEvent('update-segment-index', {
|
||||||
videoRef.current.play()
|
detail: { segmentIndex: targetSegmentIndex }
|
||||||
.then(() => {
|
});
|
||||||
setIsPlayingSegment(true);
|
document.dispatchEvent(updateSegmentIndexEvent);
|
||||||
logger.debug("Continued preview playback after segment click");
|
logger.debug(`Segments playback mode: updating segment index to ${targetSegmentIndex} for segment ${segmentId}`);
|
||||||
})
|
}
|
||||||
.catch(err => {
|
|
||||||
console.error("Error continuing preview playback:", err);
|
// In segments playback mode, we want to continue the segments playback from the new position
|
||||||
});
|
// The segments playback will naturally handle continuing to the next segments
|
||||||
|
logger.debug("Segments playback mode: continuing playback from new position");
|
||||||
|
videoRef.current.play()
|
||||||
|
.then(() => {
|
||||||
|
setIsPlayingSegment(true);
|
||||||
|
logger.debug("Continued segments playback after segment click");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error continuing segments playback after segment click:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// If video was playing before OR we're in preview mode, ensure it continues playing (but not in segments mode)
|
||||||
|
else if ((wasPlaying || isPreviewMode) && !isPlayingSegments) {
|
||||||
|
// Set current segment as active segment for boundary checking
|
||||||
|
setActiveSegment(segment);
|
||||||
|
// Reset the continuePastBoundary flag when clicking on a segment to ensure boundaries work
|
||||||
|
setContinuePastBoundary(false);
|
||||||
|
// Continue playing from the new position
|
||||||
|
videoRef.current.play()
|
||||||
|
.then(() => {
|
||||||
|
setIsPlayingSegment(true);
|
||||||
|
logger.debug("Continued preview playback after segment click");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error resuming playback after segment click:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Always continue playback in preview mode, even if video was paused when clicking (but not in segments mode)
|
||||||
|
else if (isPreviewMode && !isPlayingSegments) {
|
||||||
|
setActiveSegment(segment);
|
||||||
|
videoRef.current.play()
|
||||||
|
.then(() => {
|
||||||
|
setIsPlayingSegment(true);
|
||||||
|
logger.debug("Continued preview playback after segment click");
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Error continuing preview playback:", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate tooltip position directly above click point
|
// Calculate tooltip position directly above click point
|
||||||
|
|||||||
@ -1035,6 +1035,23 @@ const useVideoTrimmer = () => {
|
|||||||
};
|
};
|
||||||
}, [isPlayingSegments, currentSegmentIndex, clipSegments]);
|
}, [isPlayingSegments, currentSegmentIndex, clipSegments]);
|
||||||
|
|
||||||
|
// Effect to handle manual segment index updates during segments playback
|
||||||
|
useEffect(() => {
|
||||||
|
const handleSegmentIndexUpdate = (event: CustomEvent) => {
|
||||||
|
const { segmentIndex } = event.detail;
|
||||||
|
if (isPlayingSegments && segmentIndex !== currentSegmentIndex) {
|
||||||
|
logger.debug(`Updating current segment index from ${currentSegmentIndex} to ${segmentIndex}`);
|
||||||
|
setCurrentSegmentIndex(segmentIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('update-segment-index', handleSegmentIndexUpdate as EventListener);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('update-segment-index', handleSegmentIndexUpdate as EventListener);
|
||||||
|
};
|
||||||
|
}, [isPlayingSegments, currentSegmentIndex]);
|
||||||
|
|
||||||
// Handle play segments
|
// Handle play segments
|
||||||
const handlePlaySegments = () => {
|
const handlePlaySegments = () => {
|
||||||
const video = videoRef.current;
|
const video = videoRef.current;
|
||||||
|
|||||||
@ -852,30 +852,23 @@
|
|||||||
background-color: inherit !important;
|
background-color: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Segments playback mode styles */
|
/* Segments playback mode styles - minimal functional styling */
|
||||||
.segments-playback-mode {
|
|
||||||
}
|
|
||||||
|
|
||||||
.segments-playback-mode .timeline-container,
|
|
||||||
.segments-playback-mode .clip-segment,
|
|
||||||
.segments-playback-mode .clip-segment-handle,
|
|
||||||
.segments-playback-mode .timeline-marker-head,
|
|
||||||
.segments-playback-mode .timeline-marker-drag,
|
|
||||||
.segments-playback-mode .trim-handle {
|
|
||||||
}
|
|
||||||
|
|
||||||
.segments-playback-mode .tooltip-action-btn {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.segments-playback-mode .tooltip-time-btn {
|
.segments-playback-mode .tooltip-time-btn {
|
||||||
opacity: 0.5;
|
opacity: 1;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.segments-playback-mode .clip-segment:hover {
|
.segments-playback-mode .tooltip-action-btn.set-in,
|
||||||
box-shadow: none;
|
.segments-playback-mode .tooltip-action-btn.set-out,
|
||||||
border-color: rgba(0, 0, 0, 0.15);
|
.segments-playback-mode .tooltip-action-btn.play-from-start {
|
||||||
background-color: inherit !important;
|
opacity: 0.5;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segments-playback-mode .tooltip-action-btn.play,
|
||||||
|
.segments-playback-mode .tooltip-action-btn.pause {
|
||||||
|
opacity: 1;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show segments playback message */
|
/* Show segments playback message */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user