Update TimelineControls.tsx

This commit is contained in:
Yiannis Christodoulou 2025-05-22 00:37:59 +03:00
parent c21a520a47
commit 4cdfdb8354

View File

@ -145,29 +145,20 @@ const TimelineControls = ({
const handleContinuousTimeAdjustment = (offsetSeconds: number) => { const handleContinuousTimeAdjustment = (offsetSeconds: number) => {
// Fixed adjustment amount - exactly 50ms each time // Fixed adjustment amount - exactly 50ms each time
const adjustmentValue = offsetSeconds; const adjustmentValue = offsetSeconds;
// Hold timer // Hold timer for continuous adjustment
let holdTimer: number | null = null; let holdTimer: NodeJS.Timeout | null = null;
let continuousTimer: NodeJS.Timeout | null = null;
// Store the last time value to correctly calculate the next increment // Store the last time value to correctly calculate the next increment
let lastTimeValue = clickedTime; let lastTimeValue = clickedTime;
// Function to perform time adjustment // Function to perform time adjustment
const adjustTime = () => { const adjustTime = () => {
// Always use the last time value for calculations to prevent stalling
const currentTime = lastTimeValue;
// Calculate new time based on fixed offset (positive or negative) // Calculate new time based on fixed offset (positive or negative)
const newTime = adjustmentValue < 0 const newTime = adjustmentValue < 0
? Math.max(0, currentTime + adjustmentValue) // For negative offsets (going back) ? Math.max(0, lastTimeValue + adjustmentValue) // For negative offsets (going back)
: Math.min(duration, currentTime + adjustmentValue); // For positive offsets (going forward) : Math.min(duration, lastTimeValue + adjustmentValue); // For positive offsets (going forward)
// Check if we've reached a boundary // Update our last time value for next adjustment
if ((adjustmentValue < 0 && newTime <= 0) ||
(adjustmentValue > 0 && newTime >= duration)) {
// If we hit a boundary, we'll still update the display but keep the same value
// Don't clear the timer - it allows for adjusting back from the boundary
}
// Update our last time value
lastTimeValue = newTime; lastTimeValue = newTime;
// Save the current playing state before seeking // Save the current playing state before seeking
@ -180,7 +171,7 @@ const TimelineControls = ({
setClickedTime(newTime); setClickedTime(newTime);
setDisplayTime(newTime); setDisplayTime(newTime);
// Update tooltip position and type during drag // Update tooltip position
if (timelineRef.current) { if (timelineRef.current) {
const rect = timelineRef.current.getBoundingClientRect(); const rect = timelineRef.current.getBoundingClientRect();
const positionPercent = (newTime / duration) * 100; const positionPercent = (newTime / duration) * 100;
@ -190,25 +181,19 @@ const TimelineControls = ({
y: rect.top - 10 y: rect.top - 10
}); });
// Create a temporary segment with the current drag position // Find if we're in a segment at the new time
const draggedSegment = { const segmentAtTime = clipSegments.find(
...segment, seg => newTime >= seg.startTime && newTime <= seg.endTime
startTime: isLeft ? newTime : segment.startTime, );
endTime: isLeft ? segment.endTime : newTime
};
// Check if the current marker position (currentTime) is within the dragged segment if (segmentAtTime) {
const isMarkerInSegment = currentTime >= draggedSegment.startTime && currentTime <= draggedSegment.endTime; // Show segment tooltip
setSelectedSegmentId(segmentAtTime.id);
if (isMarkerInSegment) {
// Show segment tooltip if marker is inside the segment
setSelectedSegmentId(segment.id);
setShowEmptySpaceTooltip(false); setShowEmptySpaceTooltip(false);
} else { } else {
// Show cutaway tooltip if marker is outside the segment // Show cutaway tooltip
setSelectedSegmentId(null); setSelectedSegmentId(null);
// Calculate available space for cutaway tooltip const availableSpace = calculateAvailableSpace(newTime);
const availableSpace = calculateAvailableSpace(currentTime);
setAvailableSegmentDuration(availableSpace); setAvailableSegmentDuration(availableSpace);
setShowEmptySpaceTooltip(true); setShowEmptySpaceTooltip(true);
} }
@ -221,7 +206,7 @@ const TimelineControls = ({
} }
}; };
// Return mouse event handlers // Return mouse event handlers with touch support
return { return {
onMouseDown: (e: React.MouseEvent) => { onMouseDown: (e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
@ -233,19 +218,22 @@ const TimelineControls = ({
// Perform initial adjustment // Perform initial adjustment
adjustTime(); adjustTime();
// Start continuous adjustment after a short delay // Start continuous adjustment after 1.5s hold
holdTimer = window.setTimeout(() => { holdTimer = setTimeout(() => {
// Start consistent intervals at a moderate pace (exactly 8 adjustments per second) // After 1.5s delay, start adjusting at a slower pace (every 200ms)
// This ensures it adds/subtracts exactly 50ms at a steady, countable pace continuousTimer = setInterval(adjustTime, 200);
holdTimer = window.setInterval(adjustTime, 125); }, 750);
}, 250);
// Add mouse up and leave handlers to document to ensure we catch the release // Add mouse up and leave handlers to document to ensure we catch the release
const clearTimers = () => { const clearTimers = () => {
if (holdTimer) { if (holdTimer) {
clearInterval(holdTimer); clearTimeout(holdTimer);
holdTimer = null; holdTimer = null;
} }
if (continuousTimer) {
clearInterval(continuousTimer);
continuousTimer = null;
}
document.removeEventListener('mouseup', clearTimers); document.removeEventListener('mouseup', clearTimers);
document.removeEventListener('mouseleave', clearTimers); document.removeEventListener('mouseleave', clearTimers);
}; };
@ -253,6 +241,39 @@ const TimelineControls = ({
document.addEventListener('mouseup', clearTimers); document.addEventListener('mouseup', clearTimers);
document.addEventListener('mouseleave', clearTimers); document.addEventListener('mouseleave', clearTimers);
}, },
onTouchStart: (e: React.TouchEvent) => {
e.stopPropagation();
e.preventDefault();21
// Update the initial last time value
lastTimeValue = clickedTime;
// Perform initial adjustment
adjustTime();
// Start continuous adjustment after 1.5s hold
holdTimer = setTimeout(() => {
// After 1.5s delay, start adjusting at a slower pace (every 200ms)
continuousTimer = setInterval(adjustTime, 200);
}, 750);
// Add touch end handler to ensure we catch the release
const clearTimers = () => {
if (holdTimer) {
clearTimeout(holdTimer);
holdTimer = null;
}
if (continuousTimer) {
clearInterval(continuousTimer);
continuousTimer = null;
}
document.removeEventListener('touchend', clearTimers);
document.removeEventListener('touchcancel', clearTimers);
};
document.addEventListener('touchend', clearTimers);
document.addEventListener('touchcancel', clearTimers);
},
onClick: (e: React.MouseEvent) => { onClick: (e: React.MouseEvent) => {
// This prevents the click event from firing twice // This prevents the click event from firing twice
e.stopPropagation(); e.stopPropagation();
@ -2483,6 +2504,14 @@ const TimelineControls = ({
className="tooltip-time-btn" className="tooltip-time-btn"
data-tooltip="Decrease by 50ms (hold for continuous adjustment)" data-tooltip="Decrease by 50ms (hold for continuous adjustment)"
{...handleContinuousTimeAdjustment(-0.05)} {...handleContinuousTimeAdjustment(-0.05)}
style={{
userSelect: 'none',
WebkitUserSelect: 'none',
WebkitTouchCallout: 'none',
touchAction: 'manipulation',
cursor: 'pointer',
WebkitTapHighlightColor: 'transparent'
}}
> >
-50ms -50ms
</button> </button>
@ -2491,6 +2520,14 @@ const TimelineControls = ({
className="tooltip-time-btn" className="tooltip-time-btn"
data-tooltip="Increase by 50ms (hold for continuous adjustment)" data-tooltip="Increase by 50ms (hold for continuous adjustment)"
{...handleContinuousTimeAdjustment(0.05)} {...handleContinuousTimeAdjustment(0.05)}
style={{
userSelect: 'none',
WebkitUserSelect: 'none',
WebkitTouchCallout: 'none',
touchAction: 'manipulation',
cursor: 'pointer',
WebkitTapHighlightColor: 'transparent'
}}
> >
+50ms +50ms
</button> </button>