Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/components/video-editor/timeline/TimelineEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1397,14 +1397,31 @@ export default function TimelineEditor({
return [...zooms, ...trims, ...annotations, ...blurs, ...speeds];
}, [zoomRegions, trimRegions, annotationRegions, blurRegions, speedRegions, t]);

// Flat list of all non-annotation region spans for neighbour-clamping during drag/resize
// Spans that participate in overlap resolution (clampToNeighbours).
// Excludes annotation/blur deliberately — those are allowed to overlap and
// must NOT act as hard constraints when a zoom/trim/speed drag is being
// resolved.
const allRegionSpans = useMemo(() => {
const zooms = zoomRegions.map((r) => ({ id: r.id, start: r.startMs, end: r.endMs }));
const trims = trimRegions.map((r) => ({ id: r.id, start: r.startMs, end: r.endMs }));
const speeds = speedRegions.map((r) => ({ id: r.id, start: r.startMs, end: r.endMs }));
return [...zooms, ...trims, ...speeds];
}, [zoomRegions, trimRegions, speedRegions]);

// Additional snap targets that are NOT clamping constraints. Their edges
// pull during snap, but they don't push anyone away.
const softSnapSpans = useMemo(() => {
const annotations = annotationRegions.map((r) => ({
id: r.id,
start: r.startMs,
end: r.endMs,
}));
const blurs = blurRegions.map((r) => ({ id: r.id, start: r.startMs, end: r.endMs }));
return [...annotations, ...blurs];
}, [annotationRegions, blurRegions]);

const keyframeTimesMs = useMemo(() => keyframes.map((kf) => kf.time), [keyframes]);

const handleItemSpanChange = useCallback(
(id: string, span: Span) => {
// Check if it's a zoom, trim, speed, or annotation item
Expand Down Expand Up @@ -1579,6 +1596,9 @@ export default function TimelineEditor({
minVisibleRangeMs={timelineScale.minVisibleRangeMs}
onItemSpanChange={handleItemSpanChange}
allRegionSpans={allRegionSpans}
softSnapSpans={softSnapSpans}
currentTimeMs={currentTimeMs}
keyframeTimesMs={keyframeTimesMs}
>
<KeyframeMarkers
keyframes={keyframes}
Expand Down
Loading
Loading