fix(audio): Shift+grab opens the precision rail anchored at the playhead

The first grab implementation degraded Shift+grab to a quarter-speed
relative crawl — losing the ±5-minute rail the user expects when they
grab the handle with Shift held. The rail is back: Shift+grab anchors
railWindow at the CURRENT position (not the nearest chapter line, and
never teleports the playhead on pointerdown); plain grab stays relative
1:1. GRAB_FINE_SCALE is deleted as dead code, and the dialog guide
documents the restored gesture.
This commit is contained in:
John O'Keefe committed 2026-10-27 19:04:59 -04:00
1 parent b462c7fb44
commit e5d4744977
4 files changed
+38 -37

No files matched your search

+7 -10
View File
@@ -79,7 +79,9 @@ export function snapToChapterPx(
// thumb, in bar pixels, for it to count as grabbing the HANDLE rather
// than clicking the track. A grab never teleports the position — not
// to the click X (free-drag behavior) and not to a chapter line
// (Shift+click behavior) — it drags RELATIVE to where the handle is.
// (Shift+click behavior): a plain grab drags RELATIVE to where the
// handle is, and Shift+grab opens the precision rail anchored at the
// current position.
export const GRAB_SLOP_PX = 12;
// isHandleGrab reports whether a pointerdown at clientX lands on the
@@ -97,24 +99,19 @@ export function isHandleGrab(
return Math.abs(clientX - thumbX) <= slopPx;
}
// GRAB_FINE_SCALE is the Shift+grab travel factor: the same relative
// drag crawls at quarter speed for precise placement.
export const GRAB_FINE_SCALE = 0.25;
// applyGrab advances a HANDLE drag by one pointermove: incremental
// (like applyDrag, a scale change never teleports the cursor), but
// with a FIXED scale instead of a pull-away zoom — the mouse is always
// on the bar, so Shift is the precision control, not vertical offset.
// (like applyDrag, so the cursor never teleports), 1:1 with pointer
// travel. (Shift+grab uses the precision rail instead of a scaled
// drag — see scrubPointerDown.)
export function applyGrab(
position: number,
dxPx: number,
pxPerSecond: number,
duration: number,
scale = 1,
): number {
const clamped = Math.min(duration, Math.max(0, position));
if (pxPerSecond <= 0 || duration <= 0) return clamped;
return Math.min(duration, Math.max(0, clamped + (dxPx / pxPerSecond) * scale));
return Math.min(duration, Math.max(0, clamped + dxPx / pxPerSecond));
}
// ---- §9 touch precision: vertical pull-away = progressive zoom ----