mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Broadcast mouse activity (#1175)
* broadcast mouse activity * move to same MOUSE_LOCATION event * remove key up handler * update tests * Fix border * refactor * rename activity to button Co-authored-by: Panayiotis Lipiridis <lipiridis@gmail.com>
This commit is contained in:
parent
23540eba4c
commit
b97520400a
7 changed files with 116 additions and 14 deletions
|
@ -441,6 +441,10 @@ export class App extends React.Component<any, AppState> {
|
|||
if (this.state.isCollaborating && !this.socket) {
|
||||
this.initializeSocketClient({ showLoadingState: true });
|
||||
}
|
||||
|
||||
const cursorButton: {
|
||||
[id: string]: string | undefined;
|
||||
} = {};
|
||||
const pointerViewportCoords: SceneState["remotePointerViewportCoords"] = {};
|
||||
const remoteSelectedElementIds: SceneState["remoteSelectedElementIds"] = {};
|
||||
this.state.collaborators.forEach((user, socketID) => {
|
||||
|
@ -464,6 +468,7 @@ export class App extends React.Component<any, AppState> {
|
|||
this.canvas,
|
||||
window.devicePixelRatio,
|
||||
);
|
||||
cursorButton[socketID] = user.button;
|
||||
});
|
||||
const { atLeastOneVisibleElement, scrollBars } = renderScene(
|
||||
globalSceneState.getAllElements().filter((element) => {
|
||||
|
@ -486,6 +491,7 @@ export class App extends React.Component<any, AppState> {
|
|||
viewBackgroundColor: this.state.viewBackgroundColor,
|
||||
zoom: this.state.zoom,
|
||||
remotePointerViewportCoords: pointerViewportCoords,
|
||||
remotePointerButton: cursorButton,
|
||||
remoteSelectedElementIds: remoteSelectedElementIds,
|
||||
shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
|
||||
},
|
||||
|
@ -871,6 +877,7 @@ export class App extends React.Component<any, AppState> {
|
|||
const {
|
||||
socketID,
|
||||
pointerCoords,
|
||||
button,
|
||||
selectedElementIds,
|
||||
} = decryptedData.payload;
|
||||
this.setState((state) => {
|
||||
|
@ -879,6 +886,7 @@ export class App extends React.Component<any, AppState> {
|
|||
}
|
||||
const user = state.collaborators.get(socketID)!;
|
||||
user.pointer = pointerCoords;
|
||||
user.button = button;
|
||||
user.selectedElementIds = selectedElementIds;
|
||||
state.collaborators.set(socketID, user);
|
||||
return state;
|
||||
|
@ -923,6 +931,7 @@ export class App extends React.Component<any, AppState> {
|
|||
|
||||
private broadcastMouseLocation = (payload: {
|
||||
pointerCoords: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointerCoords"];
|
||||
button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
|
||||
}) => {
|
||||
if (this.socket?.id) {
|
||||
const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
|
||||
|
@ -930,6 +939,7 @@ export class App extends React.Component<any, AppState> {
|
|||
payload: {
|
||||
socketID: this.socket.id,
|
||||
pointerCoords: payload.pointerCoords,
|
||||
button: payload.button || "up",
|
||||
selectedElementIds: this.state.selectedElementIds,
|
||||
},
|
||||
};
|
||||
|
@ -1345,13 +1355,8 @@ export class App extends React.Component<any, AppState> {
|
|||
private handleCanvasPointerMove = (
|
||||
event: React.PointerEvent<HTMLCanvasElement>,
|
||||
) => {
|
||||
const pointerCoords = viewportCoordsToSceneCoords(
|
||||
event,
|
||||
this.state,
|
||||
this.canvas,
|
||||
window.devicePixelRatio,
|
||||
);
|
||||
this.savePointer(pointerCoords);
|
||||
this.savePointer(event.clientX, event.clientY, this.state.cursorButton);
|
||||
|
||||
if (gesture.pointers.has(event.pointerId)) {
|
||||
gesture.pointers.set(event.pointerId, {
|
||||
x: event.clientX,
|
||||
|
@ -1502,7 +1507,11 @@ export class App extends React.Component<any, AppState> {
|
|||
return;
|
||||
}
|
||||
|
||||
this.setState({ lastPointerDownWith: event.pointerType });
|
||||
this.setState({
|
||||
lastPointerDownWith: event.pointerType,
|
||||
cursorButton: "down",
|
||||
});
|
||||
this.savePointer(event.clientX, event.clientY, "down");
|
||||
|
||||
// pan canvas on wheel button drag or space+drag
|
||||
if (
|
||||
|
@ -1535,6 +1544,10 @@ export class App extends React.Component<any, AppState> {
|
|||
if (!isHoldingSpace) {
|
||||
setCursorForShape(this.state.elementType);
|
||||
}
|
||||
this.setState({
|
||||
cursorButton: "up",
|
||||
});
|
||||
this.savePointer(event.clientX, event.clientY, "up");
|
||||
window.removeEventListener("pointermove", onPointerMove);
|
||||
window.removeEventListener("pointerup", teardown);
|
||||
window.removeEventListener("blur", teardown);
|
||||
|
@ -1635,6 +1648,10 @@ export class App extends React.Component<any, AppState> {
|
|||
isDraggingScrollBar = false;
|
||||
setCursorForShape(this.state.elementType);
|
||||
lastPointerUp = null;
|
||||
this.setState({
|
||||
cursorButton: "up",
|
||||
});
|
||||
this.savePointer(event.clientX, event.clientY, "up");
|
||||
window.removeEventListener("pointermove", onPointerMove);
|
||||
window.removeEventListener("pointerup", onPointerUp);
|
||||
});
|
||||
|
@ -2398,7 +2415,7 @@ export class App extends React.Component<any, AppState> {
|
|||
}
|
||||
});
|
||||
|
||||
const onPointerUp = withBatchedUpdates((event: PointerEvent) => {
|
||||
const onPointerUp = withBatchedUpdates((childEvent: PointerEvent) => {
|
||||
const {
|
||||
draggingElement,
|
||||
resizingElement,
|
||||
|
@ -2412,11 +2429,15 @@ export class App extends React.Component<any, AppState> {
|
|||
isRotating: false,
|
||||
resizingElement: null,
|
||||
selectionElement: null,
|
||||
cursorButton: "up",
|
||||
editingElement: multiElement ? this.state.editingElement : null,
|
||||
});
|
||||
|
||||
this.savePointer(childEvent.clientX, childEvent.clientY, "up");
|
||||
|
||||
resizeArrowFn = null;
|
||||
lastPointerUp = null;
|
||||
|
||||
window.removeEventListener("pointermove", onPointerMove);
|
||||
window.removeEventListener("pointerup", onPointerUp);
|
||||
|
||||
|
@ -2426,7 +2447,7 @@ export class App extends React.Component<any, AppState> {
|
|||
}
|
||||
if (!draggingOccurred && draggingElement && !multiElement) {
|
||||
const { x, y } = viewportCoordsToSceneCoords(
|
||||
event,
|
||||
childEvent,
|
||||
this.state,
|
||||
this.canvas,
|
||||
window.devicePixelRatio,
|
||||
|
@ -2503,7 +2524,7 @@ export class App extends React.Component<any, AppState> {
|
|||
// was added to selection (on pointerdown phase) we need to keep
|
||||
// selection unchanged
|
||||
if (hitElement && !draggingOccurred && !hitElementWasAddedToSelection) {
|
||||
if (event.shiftKey) {
|
||||
if (childEvent.shiftKey) {
|
||||
this.setState((prevState) => ({
|
||||
selectedElementIds: {
|
||||
...prevState.selectedElementIds,
|
||||
|
@ -2735,12 +2756,26 @@ export class App extends React.Component<any, AppState> {
|
|||
}
|
||||
}
|
||||
|
||||
private savePointer = (pointerCoords: { x: number; y: number }) => {
|
||||
private savePointer = (x: number, y: number, button: "up" | "down") => {
|
||||
if (!x || !y) {
|
||||
return;
|
||||
}
|
||||
const pointerCoords = viewportCoordsToSceneCoords(
|
||||
{ clientX: x, clientY: y },
|
||||
this.state,
|
||||
this.canvas,
|
||||
window.devicePixelRatio,
|
||||
);
|
||||
|
||||
if (isNaN(pointerCoords.x) || isNaN(pointerCoords.y)) {
|
||||
// sometimes the pointer goes off screen
|
||||
return;
|
||||
}
|
||||
this.socket && this.broadcastMouseLocation({ pointerCoords });
|
||||
this.socket &&
|
||||
this.broadcastMouseLocation({
|
||||
pointerCoords,
|
||||
button,
|
||||
});
|
||||
};
|
||||
|
||||
private resetShouldCacheIgnoreZoomDebounced = debounce(() => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue