mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 23:00:03 +00:00
fix(studio): clamp the timeline scrub to 0 instead of dropping it
Dragging the playhead to the start of the composition needed a very slow drag. The scrub surface begins GUTTER + TRACKS_LEFT_PAD px right of the viewport edge, and both scrub paths bailed out when the pointer sat left of that origin rather than clamping. So the last 80px of the drag toward zero silently did nothing: the playhead stuck at whatever the last in-range sample reported, and only a drag slow enough to sample inside the thin sliver before the origin ever reached 0. Both paths now share getTimelineScrubTime, which clamps to [0, duration]. One owner, so the live-feedback path and the committed-seek path cannot disagree about the edge again.
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
GUTTER,
|
||||
TRACKS_LEFT_PAD,
|
||||
getTimelineRowTop,
|
||||
getTimelineScrubTime,
|
||||
getTimelineRowFromY,
|
||||
getTimelineCanvasHeight,
|
||||
resolveTimelineAssetDrop,
|
||||
@@ -105,3 +106,46 @@ describe("track-area breathing pad y-math", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("getTimelineScrubTime", () => {
|
||||
const at = (clientX: number, duration = 10) =>
|
||||
getTimelineScrubTime({
|
||||
clientX,
|
||||
viewportLeft: 0,
|
||||
scrollLeft: 0,
|
||||
pixelsPerSecond: 100,
|
||||
duration,
|
||||
});
|
||||
const origin = GUTTER + TRACKS_LEFT_PAD;
|
||||
|
||||
it("maps the content origin to t=0", () => {
|
||||
expect(at(origin)).toBe(0);
|
||||
expect(at(origin + 250)).toBe(2.5);
|
||||
});
|
||||
|
||||
// The bug: a pointer left of the origin used to abort the scrub instead of
|
||||
// clamping, so dragging the playhead to the start only worked if a sample
|
||||
// happened to land in the few px before t=0.
|
||||
it("clamps a pointer left of the origin to 0 instead of dropping the scrub", () => {
|
||||
expect(at(origin - 1)).toBe(0);
|
||||
expect(at(origin - 500)).toBe(0);
|
||||
expect(at(0)).toBe(0);
|
||||
});
|
||||
|
||||
it("clamps past the end to the duration", () => {
|
||||
expect(at(origin + 5000)).toBe(10);
|
||||
});
|
||||
|
||||
it("returns 0 for a degenerate zoom or duration", () => {
|
||||
expect(
|
||||
getTimelineScrubTime({
|
||||
clientX: 500,
|
||||
viewportLeft: 0,
|
||||
scrollLeft: 0,
|
||||
pixelsPerSecond: 0,
|
||||
duration: 10,
|
||||
}),
|
||||
).toBe(0);
|
||||
expect(at(origin + 250, Number.NaN)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user