fix(userscript): snap and save the FAB when a drag is cancelled

pointercancel fires when the OS claims the gesture mid-drag — likely on
the screen edge where the widened hit strip lives, which is also where
Android's swipe-back gesture starts. Bare reset() left the tab stranded
wherever the finger last was, unsnapped and unsaved, until a resize or
reload. Share the pointerup snap block with pointercancel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 20:18:01 +07:00
parent c679ecfea1
commit 8633ee9804
+17 -8
View File
@@ -1019,6 +1019,16 @@
fab.style.bottom = "auto";
});
function snapToEdge() {
const w = fab.offsetWidth, h = fab.offsetHeight;
const r = fab.getBoundingClientRect();
const side = r.left + w / 2 < window.innerWidth / 2 ? "left" : "right";
const y = clamp(r.top, FAB_MARGIN, window.innerHeight - h - FAB_MARGIN);
fab.style.transition = "left .2s ease, right .2s ease, top .2s ease";
applyFabPos(fab, side, y);
saveFabPos(side, y / window.innerHeight);
}
fab.addEventListener("pointerup", (e) => {
if (!down) return;
const didDrag = moved, didScroll = scrolling;
@@ -1029,16 +1039,15 @@
}
if (!didDrag) return; // tap — let the click handler toggle the panel
fab.dataset.dragged = "1"; // suppress the click that trails this drag
const w = fab.offsetWidth, h = fab.offsetHeight;
const r = fab.getBoundingClientRect();
const side = r.left + w / 2 < window.innerWidth / 2 ? "left" : "right";
const y = clamp(r.top, FAB_MARGIN, window.innerHeight - h - FAB_MARGIN);
fab.style.transition = "left .2s ease, right .2s ease, top .2s ease";
applyFabPos(fab, side, y);
saveFabPos(side, y / window.innerHeight);
snapToEdge();
});
fab.addEventListener("pointercancel", reset);
fab.addEventListener("pointercancel", () => {
if (!down) return;
const didDrag = moved;
reset();
if (didDrag) snapToEdge(); // OS claimed the gesture mid-drag — don't strand the FAB
});
}
// ============================================================