fix(web): PDF adjust handles — create once, reposition only
User report (desktop): the endpoint handles wouldn't move. renderPdfAdjustHandles rebuilt the handle layer via innerHTML="" on every preview frame — the first drag move triggered a repaint that DESTROYED the dot being dragged. A removed element loses pointer capture, so real mouse/touch drags died silently after one pixel; the pointerup never reached the detached dot either, so nothing saved and the session preview reverted — the same mechanism behind the earlier "resets to the original selection" report. CDP tests masked it because synthetic events dispatched directly at the detached node still ran its listeners. The two dots are now created once per session and every later call only repositions them (style updates move nothing the listeners live on). Grip-era code had this reuse pattern; the endpoint rewrite regressed it. Real-touch verified on the emulator (adb-injected drag): the handle tracks, the release saves a multi-line extent with clean recomputed text (3 rects, PUT applied).
This commit is contained in:
1 parent
a3ecac3507
commit
93f020f2b5
1 file changed
+41
-34
+41
-34
@@ -1737,47 +1737,54 @@ document.addEventListener("alpine:init", () => {
|
||||
if (!first || !last) return;
|
||||
// Start dot at the first rect's LEFT-MIDDLE, end dot at the last
|
||||
// rect's RIGHT-MIDDLE — the range boundary points.
|
||||
const pts: Array<{ which: string; fx: number; fy: number }> = [
|
||||
const pts: Array<{ which: "start" | "end"; fx: number; fy: number }> = [
|
||||
{ which: "start", fx: first[0], fy: first[1] + first[3] / 2 },
|
||||
{ which: "end", fx: last[0] + last[2], fy: last[1] + last[3] / 2 },
|
||||
];
|
||||
for (const pt of pts) {
|
||||
// Create each dot ONCE per session; every later call only
|
||||
// REPOSITIONS the existing element. An innerHTML rebuild here
|
||||
// destroys the dot mid-drag — it loses pointer capture and the
|
||||
// drag dies silently ("handles not moving", user report).
|
||||
let dot = layer.querySelector<HTMLDivElement>(
|
||||
`.adjust-handle[data-which="${pt.which}"]`,
|
||||
);
|
||||
if (!dot) {
|
||||
dot = document.createElement("div");
|
||||
dot.className = "adjust-handle";
|
||||
dot.dataset.which = pt.which;
|
||||
const which = pt.which;
|
||||
// Pointer events (mouse + touch + pen); the page's own touch
|
||||
// handlers are not engaged because the dots live in the HOST
|
||||
// document, above the iframe.
|
||||
dot.addEventListener("pointerdown", (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
dot!.setPointerCapture(e.pointerId);
|
||||
} catch {}
|
||||
dot!.dataset.dragging = "1";
|
||||
});
|
||||
dot.addEventListener("pointermove", (e) => {
|
||||
if (!dot!.dataset.dragging) return;
|
||||
this.pdfAdjustHandleMove(which, e.clientX, e.clientY);
|
||||
});
|
||||
dot.addEventListener("pointerup", (e) => {
|
||||
if (!dot!.dataset.dragging) return;
|
||||
delete dot!.dataset.dragging;
|
||||
try {
|
||||
dot!.releasePointerCapture?.(e.pointerId);
|
||||
} catch {}
|
||||
this.pdfAdjustRelease();
|
||||
});
|
||||
dot.addEventListener("pointercancel", () => {
|
||||
if (!dot!.dataset.dragging) return;
|
||||
delete dot!.dataset.dragging;
|
||||
});
|
||||
layer.appendChild(dot);
|
||||
}
|
||||
const host = map.toHost(pt.fx, pt.fy);
|
||||
const dot = document.createElement("div");
|
||||
dot.className = "adjust-handle";
|
||||
dot.dataset.which = pt.which;
|
||||
dot.style.left = `${host.x - 13}px`;
|
||||
dot.style.top = `${host.y - 13}px`;
|
||||
// Pointer events (mouse + touch + pen); the page's own touch
|
||||
// handlers are not engaged because the dots live in the HOST
|
||||
// document, above the iframe.
|
||||
dot.addEventListener("pointerdown", (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
dot.setPointerCapture(e.pointerId);
|
||||
} catch {}
|
||||
dot.dataset.dragging = "1";
|
||||
});
|
||||
dot.addEventListener("pointermove", (e) => {
|
||||
if (!dot.dataset.dragging) return;
|
||||
this.pdfAdjustHandleMove(
|
||||
pt.which,
|
||||
e.clientX,
|
||||
e.clientY,
|
||||
);
|
||||
});
|
||||
dot.addEventListener("pointerup", (e) => {
|
||||
if (!dot.dataset.dragging) return;
|
||||
delete dot.dataset.dragging;
|
||||
try {
|
||||
dot.releasePointerCapture?.(e.pointerId);
|
||||
} catch {}
|
||||
this.pdfAdjustRelease();
|
||||
});
|
||||
dot.addEventListener("pointercancel", () => {
|
||||
delete dot.dataset.dragging;
|
||||
});
|
||||
layer.appendChild(dot);
|
||||
}
|
||||
},
|
||||
/** Endpoint drag: the finger (host px) re-anchors the grabbed end at
|
||||
|
||||
Reference in new issue
Block a user