fix: collab room initialization (#4882)

This commit is contained in:
David Luzar 2022-03-06 15:59:56 +01:00 committed by GitHub
parent b26e4fcf99
commit 9392ec276d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 31 deletions

View File

@ -353,32 +353,17 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
this.isCollaborating = true; this.isCollaborating = true;
const { default: socketIOClient }: any = await import( const { default: socketIOClient } = await import(
/* webpackChunkName: "socketIoClient" */ "socket.io-client" /* webpackChunkName: "socketIoClient" */ "socket.io-client"
); );
this.portal.open(socketIOClient(SOCKET_SERVER), roomId, roomKey); this.portal.socket = this.portal.open(
socketIOClient(SOCKET_SERVER),
roomId,
roomKey,
);
if (existingRoomLinkData) { if (!existingRoomLinkData) {
this.excalidrawAPI.resetScene();
try {
const elements = await loadFromFirebase(
roomId,
roomKey,
this.portal.socket,
);
if (elements) {
scenePromise.resolve({
elements,
scrollToContent: true,
});
}
} catch (error: any) {
// log the error and move on. other peers will sync us the scene.
console.error(error);
}
} else {
const elements = this.excalidrawAPI.getSceneElements().map((element) => { const elements = this.excalidrawAPI.getSceneElements().map((element) => {
if (isImageElement(element) && element.status === "saved") { if (isImageElement(element) && element.status === "saved") {
return newElementWith(element, { status: "pending" }); return newElementWith(element, { status: "pending" });
@ -402,14 +387,17 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
} }
// fallback in case you're not alone in the room but still don't receive // fallback in case you're not alone in the room but still don't receive
// initial SCENE_UPDATE message // initial SCENE_INIT message
this.socketInitializationTimer = window.setTimeout(() => { this.socketInitializationTimer = window.setTimeout(() => {
this.initializeSocket(); this.initializeRoom({
roomLinkData: existingRoomLinkData,
fetchScene: true,
});
scenePromise.resolve(null); scenePromise.resolve(null);
}, INITIAL_SCENE_UPDATE_TIMEOUT); }, INITIAL_SCENE_UPDATE_TIMEOUT);
// All socket listeners are moving to Portal // All socket listeners are moving to Portal
this.portal.socket!.on( this.portal.socket.on(
"client-broadcast", "client-broadcast",
async (encryptedData: ArrayBuffer, iv: Uint8Array) => { async (encryptedData: ArrayBuffer, iv: Uint8Array) => {
if (!this.portal.roomKey) { if (!this.portal.roomKey) {
@ -427,7 +415,7 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
return; return;
case SCENE.INIT: { case SCENE.INIT: {
if (!this.portal.socketInitialized) { if (!this.portal.socketInitialized) {
this.initializeSocket(); this.initializeRoom({ fetchScene: false });
const remoteElements = decryptedData.payload.elements; const remoteElements = decryptedData.payload.elements;
const reconciledElements = this.reconcileElements(remoteElements); const reconciledElements = this.reconcileElements(remoteElements);
this.handleRemoteSceneUpdate(reconciledElements, { this.handleRemoteSceneUpdate(reconciledElements, {
@ -481,12 +469,15 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
}, },
); );
this.portal.socket!.on("first-in-room", () => { this.portal.socket.on("first-in-room", async () => {
if (this.portal.socket) { if (this.portal.socket) {
this.portal.socket.off("first-in-room"); this.portal.socket.off("first-in-room");
} }
this.initializeSocket(); const sceneData = await this.initializeRoom({
scenePromise.resolve(null); fetchScene: true,
roomLinkData: existingRoomLinkData,
});
scenePromise.resolve(sceneData);
}); });
this.initializeIdleDetector(); this.initializeIdleDetector();
@ -498,9 +489,45 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
return scenePromise; return scenePromise;
}; };
private initializeSocket = () => { private initializeRoom = async ({
this.portal.socketInitialized = true; fetchScene,
roomLinkData,
}:
| {
fetchScene: true;
roomLinkData: { roomId: string; roomKey: string } | null;
}
| { fetchScene: false; roomLinkData?: null }) => {
clearTimeout(this.socketInitializationTimer!); clearTimeout(this.socketInitializationTimer!);
if (fetchScene && roomLinkData && this.portal.socket) {
this.excalidrawAPI.resetScene();
try {
const elements = await loadFromFirebase(
roomLinkData.roomId,
roomLinkData.roomKey,
this.portal.socket,
);
if (elements) {
this.setLastBroadcastedOrReceivedSceneVersion(
getSceneVersion(elements),
);
return {
elements,
scrollToContent: true,
};
}
} catch (error: any) {
// log the error and move on. other peers will sync us the scene.
console.error(error);
} finally {
this.portal.socketInitialized = true;
}
} else {
this.portal.socketInitialized = true;
}
return null;
}; };
private reconcileElements = ( private reconcileElements = (

View File

@ -45,6 +45,8 @@ class Portal {
this.socket.on("room-user-change", (clients: string[]) => { this.socket.on("room-user-change", (clients: string[]) => {
this.collab.setCollaborators(clients); this.collab.setCollaborators(clients);
}); });
return socket;
} }
close() { close() {