Skip to content

Commit

Permalink
Improve stability (#4)
Browse files Browse the repository at this point in the history
* Hardened code to avoid bugs
  • Loading branch information
jrmi authored Feb 20, 2022
1 parent 61d6105 commit 14f3a58
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 222 deletions.
4 changes: 2 additions & 2 deletions src/board/ActionPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
BoardConfigAtom,
} from "./atoms";
import { useItemActions } from "./Items";
import { insideClass, hasClass } from "../utils";
import { insideClass, hasClass, getIdFromElem } from "../utils";

import Gesture from "./Gesture";

Expand Down Expand Up @@ -41,7 +41,7 @@ const ActionPane = ({ children }) => {

selectedItemRef.current.items = selectedItems;

const itemId = foundElement.dataset.id;
const itemId = getIdFromElem(foundElement);

if (!selectedItems.includes(itemId)) {
if (ctrlKey || metaKey) {
Expand Down
3 changes: 3 additions & 0 deletions src/board/Cursors/Cursor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const StyledCursor = styled.div`
flex-direction: row;
align-items: center;
z-index: 210;
pointer-events: none;
`;

const CursorName = styled.div`
Expand All @@ -22,6 +23,7 @@ const CursorName = styled.div`
margin-left: -0.5em;
margin-top: 1.7em;
whitespace: nowrap;
pointer-events: none;
background-color: ${({ color }) => color};
`;

Expand Down Expand Up @@ -70,6 +72,7 @@ const PositionnedCursor = ({ pos, ...rest }) => (
left: 0,
zIndex: 210,
position: "fixed",
pointerEvents: "none",
}}
>
<MemoizedCursor {...rest} />
Expand Down
208 changes: 103 additions & 105 deletions src/board/Gesture.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ const computeDistance = ([x1, y1], [x2, y2]) => {

const empty = () => {};

const protect =
(fn) =>
async (...args) => {
try {
await fn(...args);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
};

const Gesture = ({
children,
onDrag = empty,
Expand All @@ -65,16 +76,16 @@ const Gesture = ({
const queueRef = React.useRef([]);

// Queue event to avoid async mess
const queue = React.useCallback((callback) => {
const queue = React.useCallback((callback, args) => {
queueRef.current.push(async () => {
await callback();
await protect(callback)(args);
queueRef.current.shift();
if (queueRef.current.length !== 0) {
await queueRef.current[0]();
await protect(queueRef.current[0])();
}
});
if (queueRef.current.length === 1) {
queueRef.current[0]();
protect(queueRef.current[0])();
}
}, []);

Expand Down Expand Up @@ -104,17 +115,15 @@ const Gesture = ({
// If we are only moving the fingers in the same direction, a pan is needed.
// Ref: https://medium.com/@auchenberg/detecting-multi-touch-trackpad-gestures-in-javascript-a2505babb10e
if (isMacOS() && !ctrlKey) {
queue(() =>
onPan({
deltaX: -2 * deltaX,
deltaY: -2 * deltaY,
button: 1,
ctrlKey,
metaKey,
target,
event: e,
})
);
queue(onPan, {
deltaX: -2 * deltaX,
deltaY: -2 * deltaY,
button: 1,
ctrlKey,
metaKey,
target,
event: e,
});
} else {
// Quit if onZoom is not set
if (onZoom === undefined || !deltaY) return;
Expand All @@ -135,7 +144,7 @@ const Gesture = ({
scale *= 2;
}

queue(() => onZoom({ scale, clientX, clientY, event: e }));
queue(onZoom, { scale, clientX, clientY, event: e });
}
},
[onPan, onZoom, queue]
Expand Down Expand Up @@ -190,6 +199,7 @@ const Gesture = ({
prevDistance: distance,
});
} catch (e) {
// eslint-disable-next-line no-console
console.log("Error while getting other pointer. Ignoring", e);
// eslint-disable-next-line no-unused-expressions
stateRef.current.mainPointer === undefined;
Expand All @@ -216,22 +226,21 @@ const Gesture = ({
timeStart: Date.now(),
longTapTimeout: setTimeout(async () => {
stateRef.current.noTap = true;
queue(() =>
onLongTap({
clientX,
clientY,
altKey,
ctrlKey,
metaKey,
target,
})
);
queue(onLongTap, {
clientX,
clientY,
altKey,
ctrlKey,
metaKey,
target,
});
}, 750),
});

try {
target.setPointerCapture(pointerId);
} catch (e) {
// eslint-disable-next-line no-console
console.log("Fail to capture pointer", e);
}
},
Expand Down Expand Up @@ -307,46 +316,42 @@ const Gesture = ({
// Clear tap timeout
clearTimeout(stateRef.current.longTapTimeout);

queue(() =>
onDragStart({
deltaX: 0,
deltaY: 0,
startX: stateRef.current.startX,
startY: stateRef.current.startY,
distanceX: 0,
distanceY: 0,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
target: stateRef.current.target,
event: e,
})
);
}
// Create closure
const deltaX = clientX - stateRef.current.prevX;
const deltaY = clientY - stateRef.current.prevY;
const distanceX = clientX - stateRef.current.startX;
const distanceY = clientY - stateRef.current.startY;

// Drag event
queue(() =>
onDrag({
deltaX,
deltaY,
queue(onDragStart, {
deltaX: 0,
deltaY: 0,
startX: stateRef.current.startX,
startY: stateRef.current.startY,
distanceX,
distanceY,
distanceX: 0,
distanceY: 0,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
target: stateRef.current.target,
event: e,
})
);
});
}
// Create closure
const deltaX = clientX - stateRef.current.prevX;
const deltaY = clientY - stateRef.current.prevY;
const distanceX = clientX - stateRef.current.startX;
const distanceY = clientY - stateRef.current.startY;

// Drag event
queue(onDrag, {
deltaX,
deltaY,
startX: stateRef.current.startX,
startY: stateRef.current.startY,
distanceX,
distanceY,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
target: stateRef.current.target,
event: e,
});
} else {
if (!stateRef.current.gestureStart) {
wrapperRef.current.style.cursor = "move";
Expand All @@ -361,18 +366,16 @@ const Gesture = ({
const { target } = stateRef.current;

// Pan event
queue(() =>
onPan({
deltaX,
deltaY,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
target,
event: e,
})
);
queue(onPan, {
deltaX,
deltaY,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
target,
event: e,
});

if (
twoFingers &&
Expand All @@ -382,14 +385,12 @@ const Gesture = ({
const scale = stateRef.current.prevDistance - distance;

if (Math.abs(scale) > 0) {
queue(() =>
onZoom({
scale,
clientX,
clientY,
event: e,
})
);
queue(onZoom, {
scale,
clientX,
clientY,
event: e,
});
stateRef.current.prevDistance = distance;
}
}
Expand Down Expand Up @@ -432,6 +433,7 @@ const Gesture = ({
);
return;
} catch (error) {
// eslint-disable-next-line no-console
console.log("Fails to set pointer capture", error);
stateRef.current.mainPointer = undefined;
delete stateRef.current.pointers[
Expand All @@ -449,21 +451,19 @@ const Gesture = ({
if (stateRef.current.moving) {
// If we were moving, send drag end event
stateRef.current.moving = false;
queue(() =>
onDragEnd({
deltaX: clientX - stateRef.current.prevX,
deltaY: clientY - stateRef.current.prevY,
startX: stateRef.current.startX,
startY: stateRef.current.startY,
distanceX: clientX - stateRef.current.startX,
distanceY: clientY - stateRef.current.startY,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
event: e,
})
);
queue(onDragEnd, {
deltaX: clientX - stateRef.current.prevX,
deltaY: clientY - stateRef.current.prevY,
startX: stateRef.current.startX,
startY: stateRef.current.startY,
distanceX: clientX - stateRef.current.startX,
distanceY: clientY - stateRef.current.startY,
button: stateRef.current.currentButton,
altKey,
ctrlKey,
metaKey,
event: e,
});
wrapperRef.current.style.cursor = "auto";
} else {
const now = Date.now();
Expand All @@ -473,16 +473,14 @@ const Gesture = ({
}
// Send tap event only if time less than 300ms
else if (stateRef.current.timeStart - now < 300) {
queue(() =>
onTap({
clientX,
clientY,
altKey,
ctrlKey,
metaKey,
target,
})
);
queue(onTap, {
clientX,
clientY,
altKey,
ctrlKey,
metaKey,
target,
});
}
}
},
Expand All @@ -491,9 +489,9 @@ const Gesture = ({

const onDoubleTapHandler = React.useCallback(
(event) => {
onDoubleTap(event);
queue(onDoubleTap, event);
},
[onDoubleTap]
[onDoubleTap, queue]
);

return (
Expand Down
Loading

0 comments on commit 14f3a58

Please sign in to comment.