|
@@ -13,6 +13,7 @@ import { decompressData } from "../../data/encode";
|
|
import { encryptData, decryptData } from "../../data/encryption";
|
|
import { encryptData, decryptData } from "../../data/encryption";
|
|
import { MIME_TYPES } from "../../constants";
|
|
import { MIME_TYPES } from "../../constants";
|
|
import { reconcileElements } from "../collab/reconciliation";
|
|
import { reconcileElements } from "../collab/reconciliation";
|
|
|
|
+import { getSyncableElements, SyncableExcalidrawElement } from ".";
|
|
|
|
|
|
// private
|
|
// private
|
|
// -----------------------------------------------------------------------------
|
|
// -----------------------------------------------------------------------------
|
|
@@ -127,7 +128,18 @@ const decryptElements = async (
|
|
return JSON.parse(decodedData);
|
|
return JSON.parse(decodedData);
|
|
};
|
|
};
|
|
|
|
|
|
-const firebaseSceneVersionCache = new WeakMap<SocketIOClient.Socket, number>();
|
|
|
|
|
|
+class FirebaseSceneVersionCache {
|
|
|
|
+ private static cache = new WeakMap<SocketIOClient.Socket, number>();
|
|
|
|
+ static get = (socket: SocketIOClient.Socket) => {
|
|
|
|
+ return FirebaseSceneVersionCache.cache.get(socket);
|
|
|
|
+ };
|
|
|
|
+ static set = (
|
|
|
|
+ socket: SocketIOClient.Socket,
|
|
|
|
+ elements: readonly SyncableExcalidrawElement[],
|
|
|
|
+ ) => {
|
|
|
|
+ FirebaseSceneVersionCache.cache.set(socket, getSceneVersion(elements));
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
|
|
export const isSavedToFirebase = (
|
|
export const isSavedToFirebase = (
|
|
portal: Portal,
|
|
portal: Portal,
|
|
@@ -136,7 +148,7 @@ export const isSavedToFirebase = (
|
|
if (portal.socket && portal.roomId && portal.roomKey) {
|
|
if (portal.socket && portal.roomId && portal.roomKey) {
|
|
const sceneVersion = getSceneVersion(elements);
|
|
const sceneVersion = getSceneVersion(elements);
|
|
|
|
|
|
- return firebaseSceneVersionCache.get(portal.socket) === sceneVersion;
|
|
|
|
|
|
+ return FirebaseSceneVersionCache.get(portal.socket) === sceneVersion;
|
|
}
|
|
}
|
|
// if no room exists, consider the room saved so that we don't unnecessarily
|
|
// if no room exists, consider the room saved so that we don't unnecessarily
|
|
// prevent unload (there's nothing we could do at that point anyway)
|
|
// prevent unload (there's nothing we could do at that point anyway)
|
|
@@ -181,7 +193,7 @@ export const saveFilesToFirebase = async ({
|
|
|
|
|
|
const createFirebaseSceneDocument = async (
|
|
const createFirebaseSceneDocument = async (
|
|
firebase: ResolutionType<typeof loadFirestore>,
|
|
firebase: ResolutionType<typeof loadFirestore>,
|
|
- elements: readonly ExcalidrawElement[],
|
|
|
|
|
|
+ elements: readonly SyncableExcalidrawElement[],
|
|
roomKey: string,
|
|
roomKey: string,
|
|
) => {
|
|
) => {
|
|
const sceneVersion = getSceneVersion(elements);
|
|
const sceneVersion = getSceneVersion(elements);
|
|
@@ -197,7 +209,7 @@ const createFirebaseSceneDocument = async (
|
|
|
|
|
|
export const saveToFirebase = async (
|
|
export const saveToFirebase = async (
|
|
portal: Portal,
|
|
portal: Portal,
|
|
- elements: readonly ExcalidrawElement[],
|
|
|
|
|
|
+ elements: readonly SyncableExcalidrawElement[],
|
|
appState: AppState,
|
|
appState: AppState,
|
|
) => {
|
|
) => {
|
|
const { roomId, roomKey, socket } = portal;
|
|
const { roomId, roomKey, socket } = portal;
|
|
@@ -229,18 +241,18 @@ export const saveToFirebase = async (
|
|
transaction.set(docRef, sceneDocument);
|
|
transaction.set(docRef, sceneDocument);
|
|
|
|
|
|
return {
|
|
return {
|
|
- sceneVersion: sceneDocument.sceneVersion,
|
|
|
|
|
|
+ elements,
|
|
reconciledElements: null,
|
|
reconciledElements: null,
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
const prevDocData = snapshot.data() as FirebaseStoredScene;
|
|
const prevDocData = snapshot.data() as FirebaseStoredScene;
|
|
- const prevElements = await decryptElements(prevDocData, roomKey);
|
|
|
|
|
|
+ const prevElements = getSyncableElements(
|
|
|
|
+ await decryptElements(prevDocData, roomKey),
|
|
|
|
+ );
|
|
|
|
|
|
- const reconciledElements = reconcileElements(
|
|
|
|
- elements,
|
|
|
|
- prevElements,
|
|
|
|
- appState,
|
|
|
|
|
|
+ const reconciledElements = getSyncableElements(
|
|
|
|
+ reconcileElements(elements, prevElements, appState),
|
|
);
|
|
);
|
|
|
|
|
|
const sceneDocument = await createFirebaseSceneDocument(
|
|
const sceneDocument = await createFirebaseSceneDocument(
|
|
@@ -251,14 +263,14 @@ export const saveToFirebase = async (
|
|
|
|
|
|
transaction.update(docRef, sceneDocument);
|
|
transaction.update(docRef, sceneDocument);
|
|
return {
|
|
return {
|
|
|
|
+ elements,
|
|
reconciledElements,
|
|
reconciledElements,
|
|
- sceneVersion: sceneDocument.sceneVersion,
|
|
|
|
};
|
|
};
|
|
});
|
|
});
|
|
|
|
|
|
- firebaseSceneVersionCache.set(socket, savedData.sceneVersion);
|
|
|
|
|
|
+ FirebaseSceneVersionCache.set(socket, savedData.elements);
|
|
|
|
|
|
- return savedData;
|
|
|
|
|
|
+ return { reconciledElements: savedData.reconciledElements };
|
|
};
|
|
};
|
|
|
|
|
|
export const loadFromFirebase = async (
|
|
export const loadFromFirebase = async (
|
|
@@ -275,10 +287,12 @@ export const loadFromFirebase = async (
|
|
return null;
|
|
return null;
|
|
}
|
|
}
|
|
const storedScene = doc.data() as FirebaseStoredScene;
|
|
const storedScene = doc.data() as FirebaseStoredScene;
|
|
- const elements = await decryptElements(storedScene, roomKey);
|
|
|
|
|
|
+ const elements = getSyncableElements(
|
|
|
|
+ await decryptElements(storedScene, roomKey),
|
|
|
|
+ );
|
|
|
|
|
|
if (socket) {
|
|
if (socket) {
|
|
- firebaseSceneVersionCache.set(socket, getSceneVersion(elements));
|
|
|
|
|
|
+ FirebaseSceneVersionCache.set(socket, elements);
|
|
}
|
|
}
|
|
|
|
|
|
return restoreElements(elements, null);
|
|
return restoreElements(elements, null);
|