gtauri viewer: mid-commit touch/key takes over the swipe (chained swipes)
A second swipe while the new image was still sliding in got dropped (pointerdown bailed while the commit tween was in flight). Now a touch — or arrow key — during a commit takes it over: the commit finishes instantly (roles swap at the settle positions, same dimension-adoption path as natural completion) and the input starts a fresh gesture on the landed image, so rapid successive swipes chain through multiple pictures. A plain tap during a commit simply settles it early. Verified on the emulator: two 100 ms flicks 120 ms apart (the second lands mid-commit) end on the exact same image — pixel-identical — as two deliberate slow swipes.
This commit is contained in:
parent
cd31b76889
commit
695e2417cc
71
harnesses/gtauri/frontend/dist/index.html
vendored
71
harnesses/gtauri/frontend/dist/index.html
vendored
|
|
@ -547,7 +547,8 @@ function tweenTo(tx, ty, ms, onDone) {
|
|||
/// the incoming one slides home while the outgoing one slides off
|
||||
/// screen; only then do the roles swap (returns false at the edges).
|
||||
function navigate(delta, vel) {
|
||||
if (tween && tween.commit) return false; // commit already in flight
|
||||
// Key nav during a commit takes it over the same way a touch does.
|
||||
if (tween && tween.commit) takeover();
|
||||
const i = ids.indexOf(viewerId);
|
||||
const ni = i + delta;
|
||||
if (i < 0 || ni < 0 || ni >= ids.length) return false;
|
||||
|
|
@ -585,38 +586,55 @@ function commitTo(ni, delta, vel) {
|
|||
applyTransform();
|
||||
navLayout();
|
||||
if (t < 1) {
|
||||
tween = { raf: requestAnimationFrame(step), commit: true };
|
||||
tween = { raf: requestAnimationFrame(step), commit: true, target: ni };
|
||||
} else {
|
||||
const id = ids[ni];
|
||||
tween = null;
|
||||
if (nav && nav.id === id && nav.ready) {
|
||||
// vimg2 (incoming) is exactly at 0: it becomes primary. Adopt
|
||||
// its dimensions NOW — otherwise the new pixels render in the
|
||||
// OLD image's width/height box (wrong aspect) until full-res
|
||||
// lands and fitViewer() fixes it (visible stretch → snap).
|
||||
const nw = nav.w, nh = nav.h, ns = nav.scale;
|
||||
vimg.src = vimg2.src; // cached + decoded → paints immediately
|
||||
base.w = nw; base.h = nh;
|
||||
vScale = ns;
|
||||
vimg.style.width = nw + "px";
|
||||
vimg.style.height = nh + "px";
|
||||
vTx = 0; vTy = 0;
|
||||
applyTransform();
|
||||
openViewer(id, true);
|
||||
// Hide the preview only once the primary has the bytes.
|
||||
vimg.onload = () => { if (viewerId === id) navHide(); };
|
||||
} else {
|
||||
// Preview never made it (keyboard nav / slow thumb): plain
|
||||
// open — the thumb round-trip sets the right dimensions.
|
||||
openViewer(id, false);
|
||||
}
|
||||
finishCommit(ni);
|
||||
}
|
||||
};
|
||||
tween = { raf: requestAnimationFrame(step), commit: true };
|
||||
tween = { raf: requestAnimationFrame(step), commit: true, target: ni };
|
||||
}
|
||||
|
||||
/// Swap the elements' roles at the settled positions: vimg2 (the
|
||||
/// incoming image) becomes primary at 0 with its own dimensions (see
|
||||
/// the aspect note there), vimg shows it next paint, the old image is
|
||||
/// gone. Called when the commit tween completes AND on mid-flight
|
||||
/// takeover — a new touch/key during a commit finishes it instantly
|
||||
/// so the new gesture acts on the landed image (swipes chain).
|
||||
function finishCommit(ni) {
|
||||
const id = ids[ni];
|
||||
if (nav && nav.id === id && nav.ready) {
|
||||
const nw = nav.w, nh = nav.h, ns = nav.scale;
|
||||
vimg.src = vimg2.src; // cached + decoded → paints immediately
|
||||
base.w = nw; base.h = nh;
|
||||
vScale = ns;
|
||||
vimg.style.width = nw + "px";
|
||||
vimg.style.height = nh + "px";
|
||||
vTx = 0; vTy = 0;
|
||||
applyTransform();
|
||||
openViewer(id, true);
|
||||
// Hide the preview only once the primary has the bytes.
|
||||
vimg.onload = () => { if (viewerId === id) navHide(); };
|
||||
} else {
|
||||
// Preview never made it (keyboard nav / slow thumb): plain open —
|
||||
// the thumb round-trip sets the right dimensions.
|
||||
openViewer(id, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Instantly settle an in-flight commit (touch/key takeover).
|
||||
function takeover() {
|
||||
const target = tween.target;
|
||||
cancelAnimationFrame(tween.raf);
|
||||
tween = null;
|
||||
finishCommit(target);
|
||||
}
|
||||
|
||||
viewer.addEventListener("pointerdown", (e) => {
|
||||
if (tween && tween.commit) return; // a swipe commit is in flight
|
||||
// A touch during a swipe commit takes it over: finish the commit
|
||||
// now and start this gesture on the landed image — a second swipe
|
||||
// while the new image is sliding in acts as another swipe.
|
||||
if (tween && tween.commit) takeover();
|
||||
viewer.setPointerCapture(e.pointerId);
|
||||
if (tween) { cancelAnimationFrame(tween.raf); tween = null; }
|
||||
pts.set(e.pointerId, { x: e.clientX, y: e.clientY });
|
||||
|
|
@ -716,7 +734,6 @@ const endPt = (e) => {
|
|||
viewer.addEventListener("pointerup", endPt);
|
||||
viewer.addEventListener("pointercancel", endPt);
|
||||
viewer.addEventListener("dblclick", () => {
|
||||
if (tween && tween.commit) return;
|
||||
vScale = fitScale();
|
||||
vTx = 0; vTy = 0; vApply();
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user