feat: timeline zooms to clip region on cut-clip from Player mode
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -62,6 +62,9 @@
|
|||||||
// Caption state for PlayerControls
|
// Caption state for PlayerControls
|
||||||
let captionsEnabled = $state(true);
|
let captionsEnabled = $state(true);
|
||||||
|
|
||||||
|
// Pending timeline zoom for cut-clip feature
|
||||||
|
let pendingTimelineZoom = $state<{ start: number; end: number } | null>(null);
|
||||||
|
|
||||||
const CONTROLS_HIDE_DELAY = 2500;
|
const CONTROLS_HIDE_DELAY = 2500;
|
||||||
const TOOLBAR_PROXIMITY = 50;
|
const TOOLBAR_PROXIMITY = 50;
|
||||||
|
|
||||||
@@ -191,6 +194,7 @@
|
|||||||
const range = computeQuickClipRange(session.currentTime, session.duration, position);
|
const range = computeQuickClipRange(session.currentTime, session.duration, position);
|
||||||
if (!range) return;
|
if (!range) return;
|
||||||
addClip(range.start, range.end);
|
addClip(range.start, range.end);
|
||||||
|
pendingTimelineZoom = { start: range.start, end: range.end };
|
||||||
setAppMode('clipper');
|
setAppMode('clipper');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +466,10 @@
|
|||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
<div class="timeline-pane" style="height: {timelineHeight}px">
|
<div class="timeline-pane" style="height: {timelineHeight}px">
|
||||||
<Timeline />
|
<Timeline
|
||||||
|
zoomRegion={pendingTimelineZoom}
|
||||||
|
onZoomApplied={() => { pendingTimelineZoom = null; }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
|
|
||||||
type ClipDragTarget = { clipId: string; edge: 'start' | 'end' };
|
type ClipDragTarget = { clipId: string; edge: 'start' | 'end' };
|
||||||
|
|
||||||
|
let {
|
||||||
|
zoomRegion,
|
||||||
|
onZoomApplied,
|
||||||
|
}: {
|
||||||
|
zoomRegion?: { start: number; end: number } | null;
|
||||||
|
onZoomApplied?: () => void;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
let canvas = $state<HTMLCanvasElement | null>(null);
|
let canvas = $state<HTMLCanvasElement | null>(null);
|
||||||
let minimapCanvas = $state<HTMLCanvasElement | null>(null);
|
let minimapCanvas = $state<HTMLCanvasElement | null>(null);
|
||||||
let containerEl = $state<HTMLDivElement | null>(null);
|
let containerEl = $state<HTMLDivElement | null>(null);
|
||||||
@@ -189,6 +197,19 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (zoomRegion && session.duration > 0) {
|
||||||
|
const clipLen = zoomRegion.end - zoomRegion.start;
|
||||||
|
const pad = Math.max(clipLen * 0.2, 2);
|
||||||
|
const vs = Math.max(0, zoomRegion.start - pad);
|
||||||
|
const ve = Math.min(session.duration, zoomRegion.end + pad);
|
||||||
|
timelineState.visibleStart = vs;
|
||||||
|
timelineState.visibleEnd = ve;
|
||||||
|
timelineState.zoom = session.duration / (ve - vs);
|
||||||
|
onZoomApplied?.();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (!containerEl) return;
|
if (!containerEl) return;
|
||||||
const observer = new ResizeObserver((entries) => {
|
const observer = new ResizeObserver((entries) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user