play segments functionality

This commit is contained in:
Yiannis Christodoulou 2025-05-22 03:50:30 +03:00
parent 39fcf3c97c
commit 3453ec279b
4 changed files with 87 additions and 9 deletions

View File

@ -285,6 +285,7 @@ const App = () => {
isPlaying={isPlaying}
setIsPlaying={setIsPlaying}
onPlayPause={handlePlay}
isPlayingSegments={isPlayingSegments}
/>
{/* Clip Segments */}

View File

@ -103,8 +103,8 @@ const EditingTools = ({
)}
</button>
{/* Standard Play button (only shown when not in preview mode) */}
{!isPreviewMode && (
{/* Standard Play button (only shown when not in preview mode or segments playback) */}
{!isPreviewMode && !isPlayingSegments && (
<button
className="button play-button"
onClick={handlePlay}
@ -134,6 +134,18 @@ const EditingTools = ({
</button>
)}
{/* Segments Playback message (replaces play button during segments playback) */}
{isPlayingSegments && (
<div className="segments-playback-message">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="16" x2="12" y2="12" />
<line x1="12" y1="8" x2="12" y2="8" />
</svg>
Segments Playback
</div>
)}
{/* Preview mode message (replaces play button) */}
{isPreviewMode && (
<div className="preview-mode-message">

View File

@ -49,6 +49,7 @@ interface TimelineControlsProps {
isPlaying: boolean;
setIsPlaying: (playing: boolean) => void;
onPlayPause: () => void; // Add this prop
isPlayingSegments?: boolean;
}
// Function to calculate and constrain tooltip position to keep it on screen
@ -95,7 +96,8 @@ const TimelineControls = ({
isIOSUninitialized = false,
isPlaying,
setIsPlaying,
onPlayPause // Add this prop
onPlayPause, // Add this prop
isPlayingSegments = false,
}: TimelineControlsProps) => {
const timelineRef = useRef<HTMLDivElement>(null);
const leftHandleRef = useRef<HTMLDivElement>(null);
@ -1108,11 +1110,13 @@ const TimelineControls = ({
// Handle timeline click to seek and show a tooltip
const handleTimelineClick = (e: React.MouseEvent<HTMLDivElement>) => {
// Prevent interaction if segments are playing
if (isPlayingSegments) return;
if (!timelineRef.current || !scrollContainerRef.current) return;
// If on mobile device and video hasn't been initialized, don't handle timeline clicks
if (isIOSUninitialized) {
// Don't do anything on timeline click if mobile device hasn't been initialized
return;
}
@ -1238,6 +1242,9 @@ const TimelineControls = ({
// Handle segment resize - works with both mouse and touch events
const handleSegmentResize = (segmentId: number, isLeft: boolean) => (e: React.MouseEvent | React.TouchEvent) => {
// Prevent interaction if segments are playing
if (isPlayingSegments) return;
e.preventDefault();
e.stopPropagation(); // Prevent triggering parent's events
@ -1571,6 +1578,9 @@ const TimelineControls = ({
// Handle segment click to show the tooltip
const handleSegmentClick = (segmentId: number) => (e: React.MouseEvent) => {
// Prevent interaction if segments are playing
if (isPlayingSegments) return;
// Don't show tooltip if clicked on handle
if ((e.target as HTMLElement).classList.contains('clip-segment-handle')) {
return;
@ -2235,7 +2245,7 @@ const TimelineControls = ({
}, [showSuccessModal, redirectUrl, onSave]);
return (
<div className={`timeline-container-card ${isPreviewMode ? 'preview-mode' : ''}`}>
<div className={`timeline-container-card ${isPlayingSegments ? 'segments-playback-mode' : ''}`}>
{/* Current Timecode with Milliseconds */}
<div className="timeline-header">
<div className="timeline-title">
@ -2250,10 +2260,11 @@ const TimelineControls = ({
{/* Timeline Container with Scrollable Wrapper */}
<div
ref={scrollContainerRef}
className="timeline-scroll-container"
className={`timeline-scroll-container ${isPlayingSegments ? 'segments-playback-mode' : ''}`}
style={{
overflow: zoomLevel > 1 ? 'auto' : 'hidden'
}}>
}}
>
<div
ref={timelineRef}
className="timeline-container"
@ -2342,7 +2353,7 @@ const TimelineControls = ({
{/* Segment Tooltip */}
{selectedSegmentId !== null && (
<div
className={`segment-tooltip two-row-tooltip ${isPreviewMode ? 'preview-mode' : ''}`}
className={`segment-tooltip two-row-tooltip ${isPlayingSegments ? 'segments-playback-mode' : ''}`}
style={{
position: 'absolute',
...constrainTooltipPosition(currentTimePercent)
@ -2639,7 +2650,7 @@ const TimelineControls = ({
{/* Empty space tooltip - positioned absolutely within timeline container */}
{showEmptySpaceTooltip && selectedSegmentId === null && (
<div
className={`empty-space-tooltip two-row-tooltip ${isPreviewMode ? 'preview-mode' : ''}`}
className={`empty-space-tooltip two-row-tooltip ${isPlayingSegments ? 'segments-playback-mode' : ''}`}
style={{
position: 'absolute',
...constrainTooltipPosition(currentTimePercent)

View File

@ -850,4 +850,58 @@
box-shadow: none;
border-color: rgba(0, 0, 0, 0.15);
background-color: inherit !important;
}
/* Segments playback mode styles */
.segments-playback-mode {
pointer-events: none;
cursor: not-allowed;
}
.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 {
pointer-events: none;
cursor: not-allowed;
}
.segments-playback-mode .tooltip-action-btn {
opacity: 0.5;
pointer-events: none;
cursor: not-allowed;
}
.segments-playback-mode .tooltip-time-btn {
opacity: 0.5;
pointer-events: none;
cursor: not-allowed;
}
.segments-playback-mode .clip-segment:hover {
box-shadow: none;
border-color: rgba(0, 0, 0, 0.15);
background-color: inherit !important;
}
/* Show segments playback message */
.segments-playback-message {
display: flex;
align-items: center;
background-color: rgba(59, 130, 246, 0.1);
color: #3b82f6;
padding: 6px 12px;
border-radius: 4px;
font-weight: 600;
font-size: 0.875rem;
animation: pulse 2s infinite;
}
.segments-playback-message svg {
height: 1.25rem;
width: 1.25rem;
margin-right: 0.5rem;
color: #3b82f6;
}