feat: F5.6d a drag is one change of the document; the others see it through the presence
Moving a device, moving or resizing a documentation item went into the shared document at every pointer move: 59 updates a second, each leaving about 18 bytes of history (M4 on test-filius). Now the editor keeps the drag while it lasts, shows it itself and tells the others through the awareness (moving, at most every 50 ms, the end at once), and writes it once when it is let go. A drag the browser cancels or a second finger turns into a pinch is written where it is; WebKit sends a second pointerdown for the first finger when another comes, which had lost the drag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -69,6 +69,7 @@ export interface CanvasProps {
|
||||
readonly onSelect?: (selection: Selection | null) => void;
|
||||
/** A device dragged: its button's new top left corner. */
|
||||
readonly onMoveDevice?: (id: string, x: number, y: number) => void;
|
||||
/** A drag of a device or an item over: let go, taken by the browser, or turned into a pinch by a second finger. */
|
||||
readonly onMoveEnd?: () => void;
|
||||
readonly onCableStart?: (from: { readonly id: string; readonly side: Side } | null) => void;
|
||||
readonly onCable?: (from: { readonly id: string; readonly side: Side }, to: { readonly id: string; readonly side: Side }) => void;
|
||||
@@ -392,9 +393,15 @@ export const Canvas = forwardRef<CanvasHandle, CanvasProps>(function Canvas(
|
||||
if (surface.current !== null && !surface.current.hasPointerCapture(pointerId)) surface.current.setPointerCapture(pointerId);
|
||||
};
|
||||
|
||||
/** Whether a gesture was on a device or an item: its end lets the editor write what it was dragging, if anything (a tap, a long press, the cable tool drag nothing). */
|
||||
const draggedSomething = (now: Gesture | null) => now?.kind === 'device' || now?.kind === 'doc';
|
||||
|
||||
const onPointerDown = (event: React.PointerEvent<SVGSVGElement>) => {
|
||||
const point = local(event.clientX, event.clientY);
|
||||
pointers.current.set(event.pointerId, point);
|
||||
// A press that takes the place of a drag ends it where it is: a second finger (a pinch), or WebKit's
|
||||
// second pointerdown for a finger that is already down, which it sends when another one comes.
|
||||
if (draggedSomething(gesture.current)) onMoveEnd?.();
|
||||
if (pointers.current.size === 2) {
|
||||
// A second finger: a pinch, whatever the first one did.
|
||||
clearLongPress();
|
||||
@@ -524,6 +531,8 @@ export const Canvas = forwardRef<CanvasHandle, CanvasProps>(function Canvas(
|
||||
gesture.current = remaining === undefined ? null : { kind: 'background', start: remaining, moved: true, last: remaining };
|
||||
if (now === null || now.kind === 'pinch' || event.type === 'pointercancel') {
|
||||
setBand(null);
|
||||
// The browser took the pointer: a drag ends where it is, as it would have stood in the document.
|
||||
if (draggedSomething(now)) onMoveEnd?.();
|
||||
return;
|
||||
}
|
||||
if (now.kind === 'doc') {
|
||||
|
||||
Reference in New Issue
Block a user