Add SCENE_INIT broadcast type for new user (#1095)

This commit is contained in:
Sanghyeon Lee 2020-03-29 11:35:56 +09:00 committed by GitHub
parent 8e6d55cf75
commit 763735ac84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 103 additions and 86 deletions

View File

@ -502,7 +502,7 @@ export class App extends React.Component<any, AppState> {
getDrawingVersion(globalSceneState.getAllElements()) >
this.lastBroadcastedOrReceivedSceneVersion
) {
this.broadcastSceneUpdate();
this.broadcastScene("SCENE_UPDATE");
}
history.record(this.state, globalSceneState.getAllElements());
@ -708,28 +708,9 @@ export class App extends React.Component<any, AppState> {
// initial SCENE_UPDATE message
const initializationTimer = setTimeout(initialize, 5000);
this.socket = socketIOClient(SOCKET_SERVER);
this.roomID = roomMatch[1];
this.roomKey = roomMatch[2];
this.socket.on("init-room", () => {
this.socket && this.socket.emit("join-room", this.roomID);
});
this.socket.on(
"client-broadcast",
async (encryptedData: ArrayBuffer, iv: Uint8Array) => {
if (!this.roomKey) {
return;
}
const decryptedData = await decryptAESGEM(
encryptedData,
this.roomKey,
iv,
);
switch (decryptedData.type) {
case "INVALID_RESPONSE":
return;
case "SCENE_UPDATE": {
const updateScene = (
decryptedData: SocketUpdateDataSource["SCENE_INIT" | "SCENE_UPDATE"],
) => {
const { elements: remoteElements } = decryptedData.payload;
const restoredState = restore(remoteElements || [], null, {
scrollToContent: true,
@ -772,8 +753,7 @@ export class App extends React.Component<any, AppState> {
delete localElementMap[element.id];
} else if (
localElementMap.hasOwnProperty(element.id) &&
localElementMap[element.id].version ===
element.version &&
localElementMap[element.id].version === element.version &&
localElementMap[element.id].versionNonce !==
element.versionNonce
) {
@ -803,6 +783,7 @@ export class App extends React.Component<any, AppState> {
this.lastBroadcastedOrReceivedSceneVersion = getDrawingVersion(
globalSceneState.getAllElements(),
);
// We haven't yet implemented multiplayer undo functionality, so we clear the undo stack
// when we receive any messages from another peer. This UX can be pretty rough -- if you
// undo, a user makes a change, and then try to redo, your element(s) will be lost. However,
@ -811,8 +792,38 @@ export class App extends React.Component<any, AppState> {
if (this.socketInitialized === false) {
initialize();
}
};
this.socket = socketIOClient(SOCKET_SERVER);
this.roomID = roomMatch[1];
this.roomKey = roomMatch[2];
this.socket.on("init-room", () => {
this.socket && this.socket.emit("join-room", this.roomID);
});
this.socket.on(
"client-broadcast",
async (encryptedData: ArrayBuffer, iv: Uint8Array) => {
if (!this.roomKey) {
return;
}
const decryptedData = await decryptAESGEM(
encryptedData,
this.roomKey,
iv,
);
switch (decryptedData.type) {
case "INVALID_RESPONSE":
return;
case "SCENE_INIT": {
if (!this.socketInitialized) {
updateScene(decryptedData);
}
break;
}
case "SCENE_UPDATE":
updateScene(decryptedData);
break;
case "MOUSE_LOCATION": {
const { socketID, pointerCoords } = decryptedData.payload;
this.setState((state) => {
@ -852,7 +863,7 @@ export class App extends React.Component<any, AppState> {
});
});
this.socket.on("new-user", async (socketID: string) => {
this.broadcastSceneUpdate();
this.broadcastScene("SCENE_INIT");
});
this.setState({
@ -879,9 +890,9 @@ export class App extends React.Component<any, AppState> {
}
};
private broadcastSceneUpdate = () => {
const data: SocketUpdateDataSource["SCENE_UPDATE"] = {
type: "SCENE_UPDATE",
private broadcastScene = (sceneType: "SCENE_INIT" | "SCENE_UPDATE") => {
const data: SocketUpdateDataSource[typeof sceneType] = {
type: sceneType,
payload: {
elements: getSyncableElements(globalSceneState.getAllElements()),
},

View File

@ -32,6 +32,12 @@ export type EncryptedData = {
};
export type SocketUpdateDataSource = {
SCENE_INIT: {
type: "SCENE_INIT";
payload: {
elements: readonly ExcalidrawElement[];
};
};
SCENE_UPDATE: {
type: "SCENE_UPDATE";
payload: {