follow scroll location POC
This commit is contained in:
parent
a80ac4c748
commit
9152ce24f2
@ -9,7 +9,9 @@ export const actionGoToCollaborator = register({
|
||||
viewMode: true,
|
||||
trackEvent: { category: "collab" },
|
||||
perform: (_elements, appState, value) => {
|
||||
const point = value as Collaborator["pointer"];
|
||||
const _value = value as Collaborator & { clientId: string };
|
||||
const point = _value.pointer;
|
||||
|
||||
if (!point) {
|
||||
return { appState, commitToHistory: false };
|
||||
}
|
||||
@ -17,6 +19,8 @@ export const actionGoToCollaborator = register({
|
||||
return {
|
||||
appState: {
|
||||
...appState,
|
||||
// ˇˇ or maybe an atom? 🤔
|
||||
userToFollow: _value.clientId,
|
||||
...centerScrollOn({
|
||||
scenePoint: point,
|
||||
viewportDimensions: {
|
||||
@ -39,7 +43,7 @@ export const actionGoToCollaborator = register({
|
||||
return (
|
||||
<Avatar
|
||||
color={background}
|
||||
onClick={() => updateData(collaborator.pointer)}
|
||||
onClick={() => updateData({ ...collaborator, clientId })}
|
||||
name={collaborator.username || ""}
|
||||
src={collaborator.avatarUrl}
|
||||
/>
|
||||
|
@ -98,6 +98,7 @@ export const getDefaultAppState = (): Omit<
|
||||
pendingImageElementId: null,
|
||||
showHyperlinkPopup: false,
|
||||
selectedLinearElement: null,
|
||||
userToFollow: null,
|
||||
};
|
||||
};
|
||||
|
||||
@ -204,6 +205,7 @@ const APP_STATE_STORAGE_CONF = (<
|
||||
pendingImageElementId: { browser: false, export: false, server: false },
|
||||
showHyperlinkPopup: { browser: false, export: false, server: false },
|
||||
selectedLinearElement: { browser: true, export: false, server: false },
|
||||
userToFollow: { browser: false, export: false, server: false },
|
||||
});
|
||||
|
||||
const _clearAppStateForStorage = <
|
||||
|
@ -1500,6 +1500,8 @@ class App extends React.Component<AppProps, AppState> {
|
||||
this.refreshDeviceState(this.excalidrawContainerRef.current);
|
||||
}
|
||||
|
||||
// TODO follow-participant
|
||||
// add zoom change
|
||||
if (
|
||||
prevState.scrollX !== this.state.scrollX ||
|
||||
prevState.scrollY !== this.state.scrollY
|
||||
|
@ -89,6 +89,7 @@ export interface CollabAPI {
|
||||
/** function so that we can access the latest value from stale callbacks */
|
||||
isCollaborating: () => boolean;
|
||||
onPointerUpdate: CollabInstance["onPointerUpdate"];
|
||||
onScrollChange: CollabInstance["onScrollChange"];
|
||||
startCollaboration: CollabInstance["startCollaboration"];
|
||||
stopCollaboration: CollabInstance["stopCollaboration"];
|
||||
syncElements: CollabInstance["syncElements"];
|
||||
@ -162,6 +163,7 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
const collabAPI: CollabAPI = {
|
||||
isCollaborating: this.isCollaborating,
|
||||
onPointerUpdate: this.onPointerUpdate,
|
||||
onScrollChange: this.onScrollChange,
|
||||
startCollaboration: this.startCollaboration,
|
||||
syncElements: this.syncElements,
|
||||
fetchImageFilesFromFirebase: this.fetchImageFilesFromFirebase,
|
||||
@ -506,6 +508,8 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
break;
|
||||
}
|
||||
case WS_SCENE_EVENT_TYPES.UPDATE:
|
||||
console.log("received update", decryptedData);
|
||||
console.log(this.excalidrawAPI.getAppState());
|
||||
this.handleRemoteSceneUpdate(
|
||||
this.reconcileElements(decryptedData.payload.elements),
|
||||
);
|
||||
@ -513,6 +517,9 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
case "MOUSE_LOCATION": {
|
||||
const { pointer, button, username, selectedElementIds } =
|
||||
decryptedData.payload;
|
||||
|
||||
// console.log({ decryptedData });
|
||||
|
||||
const socketId: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["socketId"] =
|
||||
decryptedData.payload.socketId ||
|
||||
// @ts-ignore legacy, see #2094 (#2097)
|
||||
@ -530,6 +537,35 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
});
|
||||
break;
|
||||
}
|
||||
// TODO follow-participant
|
||||
// case "SCROLL_LOCATION"
|
||||
// case "ZOOM_VALUE"
|
||||
// if following someone, update scroll and zoom
|
||||
|
||||
case "SCROLL_LOCATION":
|
||||
const {
|
||||
scroll: { x, y },
|
||||
} = decryptedData.payload;
|
||||
|
||||
const socketId: SocketUpdateDataSource["SCROLL_LOCATION"]["payload"]["socketId"] =
|
||||
decryptedData.payload.socketId;
|
||||
|
||||
console.log({ decryptedData });
|
||||
|
||||
const appState = this.excalidrawAPI.getAppState();
|
||||
console.log({ appState });
|
||||
|
||||
if (appState.userToFollow === socketId) {
|
||||
this.excalidrawAPI.updateScene({
|
||||
appState: {
|
||||
scrollX: x,
|
||||
scrollY: y,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "IDLE_STATUS": {
|
||||
const { userState, socketId, username } = decryptedData.payload;
|
||||
const collaborators = new Map(this.collaborators);
|
||||
@ -756,6 +792,7 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
|
||||
pointersMap: Gesture["pointers"];
|
||||
}) => {
|
||||
// console.log({ payload });
|
||||
payload.pointersMap.size < 2 &&
|
||||
this.portal.socket &&
|
||||
this.portal.broadcastMouseLocation(payload);
|
||||
@ -763,6 +800,21 @@ class Collab extends PureComponent<Props, CollabState> {
|
||||
CURSOR_SYNC_TIMEOUT,
|
||||
);
|
||||
|
||||
// TODO follow-participant
|
||||
// - onScrollChange
|
||||
// -- broadCastScrollLocation
|
||||
// - onZoomChange
|
||||
// -- broadCastZoomValue
|
||||
|
||||
onScrollChange = throttle(
|
||||
(payload: {
|
||||
scrollX: SocketUpdateDataSource["SCROLL_LOCATION"]["payload"]["scroll"]["x"];
|
||||
scrollY: SocketUpdateDataSource["SCROLL_LOCATION"]["payload"]["scroll"]["y"];
|
||||
}) => {
|
||||
this.portal.socket && this.portal.broadcastScrollLocation(payload);
|
||||
},
|
||||
);
|
||||
|
||||
onIdleStateChange = (userState: UserIdleState) => {
|
||||
this.portal.broadcastIdleChange(userState);
|
||||
};
|
||||
|
@ -213,6 +213,36 @@ class Portal {
|
||||
username: this.collab.state.username,
|
||||
},
|
||||
};
|
||||
|
||||
// console.log("broadcastMouseLocation data", data);
|
||||
|
||||
return this._broadcastSocketData(
|
||||
data as SocketUpdateData,
|
||||
true, // volatile
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO follow-participant
|
||||
// - broadCastScrollLocation
|
||||
// - broadCastZoomValue
|
||||
|
||||
broadcastScrollLocation = (payload: {
|
||||
scrollX: SocketUpdateDataSource["SCROLL_LOCATION"]["payload"]["scroll"]["x"];
|
||||
scrollY: SocketUpdateDataSource["SCROLL_LOCATION"]["payload"]["scroll"]["y"];
|
||||
}) => {
|
||||
if (this.socket?.id) {
|
||||
const data: SocketUpdateDataSource["SCROLL_LOCATION"] = {
|
||||
type: "SCROLL_LOCATION",
|
||||
payload: {
|
||||
socketId: this.socket.id,
|
||||
scroll: { x: payload.scrollX, y: payload.scrollY },
|
||||
username: this.collab.state.username,
|
||||
},
|
||||
};
|
||||
|
||||
console.log("broadcastScrollLocation data", data);
|
||||
|
||||
return this._broadcastSocketData(
|
||||
data as SocketUpdateData,
|
||||
true, // volatile
|
||||
|
@ -113,6 +113,14 @@ export type SocketUpdateDataSource = {
|
||||
username: string;
|
||||
};
|
||||
};
|
||||
SCROLL_LOCATION: {
|
||||
type: "SCROLL_LOCATION";
|
||||
payload: {
|
||||
socketId: string;
|
||||
scroll: { x: number; y: number };
|
||||
username: string;
|
||||
};
|
||||
};
|
||||
IDLE_STATUS: {
|
||||
type: "IDLE_STATUS";
|
||||
payload: {
|
||||
|
@ -649,6 +649,13 @@ const ExcalidrawWrapper = () => {
|
||||
})}
|
||||
>
|
||||
<Excalidraw
|
||||
// TODO follow-participant
|
||||
// add onZoomChange
|
||||
onScrollChange={(x, y) => {
|
||||
// console.log({ x, y });
|
||||
|
||||
collabAPI?.onScrollChange({ scrollX: x, scrollY: y });
|
||||
}}
|
||||
ref={excalidrawRefCallback}
|
||||
onChange={onChange}
|
||||
initialData={initialStatePromiseRef.current.promise}
|
||||
|
@ -223,6 +223,7 @@ export type AppState = {
|
||||
pendingImageElementId: ExcalidrawImageElement["id"] | null;
|
||||
showHyperlinkPopup: false | "info" | "editor";
|
||||
selectedLinearElement: LinearElementEditor | null;
|
||||
userToFollow: string | null;
|
||||
};
|
||||
|
||||
export type UIAppState = Omit<
|
||||
|
Loading…
x
Reference in New Issue
Block a user