Pārlūkot izejas kodu

move broadcastScene and broadcastMouseLocation to portal (#2262)

vanilla_orig
Aakansha Doshi 5 gadus atpakaļ
vecāks
revīzija
6db5647048
Revīzijas autora e-pasta adrese nav piesaistīta nevienam kontam
2 mainītis faili ar 108 papildinājumiem un 88 dzēšanām
  1. 23
    86
      src/components/App.tsx
  2. 85
    2
      src/components/Portal.tsx

+ 23
- 86
src/components/App.tsx Parādīt failu

@@ -3,7 +3,6 @@ import React from "react";
3 3
 import rough from "roughjs/bin/rough";
4 4
 import { RoughCanvas } from "roughjs/bin/canvas";
5 5
 import { simplify, Point } from "points-on-curve";
6
-import { SocketUpdateData } from "../types";
7 6
 
8 7
 import {
9 8
   newElement,
@@ -279,9 +278,8 @@ export type ExcalidrawImperativeAPI =
279 278
 class App extends React.Component<ExcalidrawProps, AppState> {
280 279
   canvas: HTMLCanvasElement | null = null;
281 280
   rc: RoughCanvas | null = null;
282
-  portal: Portal = new Portal(this);
283
-  lastBroadcastedOrReceivedSceneVersion: number = -1;
284
-  broadcastedElementVersions: Map<string, number> = new Map();
281
+  portal: Portal;
282
+  private lastBroadcastedOrReceivedSceneVersion: number = -1;
285 283
   unmounted: boolean = false;
286 284
   actionManager: ActionManager;
287 285
   private excalidrawRef: any;
@@ -312,6 +310,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
312 310
       };
313 311
     }
314 312
     this.scene = new Scene();
313
+    this.portal = new Portal(this);
314
+
315 315
     this.excalidrawRef = React.createRef();
316 316
     this.actionManager = new ActionManager(
317 317
       this.syncActionResult,
@@ -396,6 +396,18 @@ class App extends React.Component<ExcalidrawProps, AppState> {
396 396
     );
397 397
   }
398 398
 
399
+  public setLastBroadcastedOrReceivedSceneVersion = (version: number) => {
400
+    this.lastBroadcastedOrReceivedSceneVersion = version;
401
+  };
402
+
403
+  public getLastBroadcastedOrReceivedSceneVersion = () => {
404
+    return this.lastBroadcastedOrReceivedSceneVersion;
405
+  };
406
+
407
+  public getSceneElementsIncludingDeleted = () => {
408
+    return this.scene.getElementsIncludingDeleted();
409
+  };
410
+
399 411
   private syncActionResult = withBatchedUpdates(
400 412
     (actionResult: ActionResult) => {
401 413
       if (this.unmounted || actionResult === false) {
@@ -823,7 +835,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
823 835
   });
824 836
 
825 837
   queueBroadcastAllElements = throttle(() => {
826
-    this.broadcastScene(SCENE.UPDATE, /* syncAll */ true);
838
+    this.portal.broadcastScene(SCENE.UPDATE, /* syncAll */ true);
827 839
   }, SYNC_FULL_SCENE_INTERVAL_MS);
828 840
 
829 841
   componentDidUpdate(prevProps: ExcalidrawProps, prevState: AppState) {
@@ -949,7 +961,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
949 961
       getSceneVersion(this.scene.getElementsIncludingDeleted()) >
950 962
       this.lastBroadcastedOrReceivedSceneVersion
951 963
     ) {
952
-      this.broadcastScene(SCENE.UPDATE, /* syncAll */ false);
964
+      this.portal.broadcastScene(SCENE.UPDATE, /* syncAll */ false);
953 965
       this.queueBroadcastAllElements();
954 966
     }
955 967
 
@@ -1363,7 +1375,10 @@ class App extends React.Component<ExcalidrawProps, AppState> {
1363 1375
       // we just received!
1364 1376
       // Note: this needs to be set before replaceAllElements as it
1365 1377
       // syncronously calls render.
1366
-      this.lastBroadcastedOrReceivedSceneVersion = getSceneVersion(newElements);
1378
+
1379
+      this.setLastBroadcastedOrReceivedSceneVersion(
1380
+        getSceneVersion(newElements),
1381
+      );
1367 1382
 
1368 1383
       this.scene.replaceAllElements(newElements);
1369 1384
     }
@@ -1511,28 +1526,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
1511 1526
     });
1512 1527
   }
1513 1528
 
1514
-  private broadcastMouseLocation = (payload: {
1515
-    pointer: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointer"];
1516
-    button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
1517
-  }) => {
1518
-    if (this.portal.socket?.id) {
1519
-      const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
1520
-        type: "MOUSE_LOCATION",
1521
-        payload: {
1522
-          socketId: this.portal.socket.id,
1523
-          pointer: payload.pointer,
1524
-          button: payload.button || "up",
1525
-          selectedElementIds: this.state.selectedElementIds,
1526
-          username: this.state.username,
1527
-        },
1528
-      };
1529
-      return this.portal._broadcastSocketData(
1530
-        data as SocketUpdateData,
1531
-        true, // volatile
1532
-      );
1533
-    }
1534
-  };
1535
-
1536 1529
   saveCollabRoomToFirebase = async (
1537 1530
     syncableElements: ExcalidrawElement[] = getSyncableElements(
1538 1531
       this.scene.getElementsIncludingDeleted(),
@@ -1545,62 +1538,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
1545 1538
     }
1546 1539
   };
1547 1540
 
1548
-  // maybe should move to Portal
1549
-  broadcastScene = async (
1550
-    sceneType: SCENE.INIT | SCENE.UPDATE,
1551
-    syncAll: boolean,
1552
-  ) => {
1553
-    if (sceneType === SCENE.INIT && !syncAll) {
1554
-      throw new Error("syncAll must be true when sending SCENE.INIT");
1555
-    }
1556
-
1557
-    let syncableElements = getSyncableElements(
1558
-      this.scene.getElementsIncludingDeleted(),
1559
-    );
1560
-
1561
-    if (!syncAll) {
1562
-      // sync out only the elements we think we need to to save bandwidth.
1563
-      // periodically we'll resync the whole thing to make sure no one diverges
1564
-      // due to a dropped message (server goes down etc).
1565
-      syncableElements = syncableElements.filter(
1566
-        (syncableElement) =>
1567
-          !this.broadcastedElementVersions.has(syncableElement.id) ||
1568
-          syncableElement.version >
1569
-            this.broadcastedElementVersions.get(syncableElement.id)!,
1570
-      );
1571
-    }
1572
-
1573
-    const data: SocketUpdateDataSource[typeof sceneType] = {
1574
-      type: sceneType,
1575
-      payload: {
1576
-        elements: syncableElements,
1577
-      },
1578
-    };
1579
-    this.lastBroadcastedOrReceivedSceneVersion = Math.max(
1580
-      this.lastBroadcastedOrReceivedSceneVersion,
1581
-      getSceneVersion(this.scene.getElementsIncludingDeleted()),
1582
-    );
1583
-    for (const syncableElement of syncableElements) {
1584
-      this.broadcastedElementVersions.set(
1585
-        syncableElement.id,
1586
-        syncableElement.version,
1587
-      );
1588
-    }
1589
-
1590
-    const broadcastPromise = this.portal._broadcastSocketData(
1591
-      data as SocketUpdateData,
1592
-    );
1593
-
1594
-    if (syncAll && this.state.isCollaborating) {
1595
-      await Promise.all([
1596
-        broadcastPromise,
1597
-        this.saveCollabRoomToFirebase(syncableElements),
1598
-      ]);
1599
-    } else {
1600
-      await broadcastPromise;
1601
-    }
1602
-  };
1603
-
1604 1541
   private onSceneUpdated = () => {
1605 1542
     this.setState({});
1606 1543
   };
@@ -4078,7 +4015,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
4078 4015
     this.portal.socket &&
4079 4016
       // do not broadcast when more than 1 pointer since that shows flickering on the other side
4080 4017
       gesture.pointers.size < 2 &&
4081
-      this.broadcastMouseLocation({
4018
+      this.portal.broadcastMouseLocation({
4082 4019
         pointer,
4083 4020
         button,
4084 4021
       });

+ 85
- 2
src/components/Portal.tsx Parādīt failu

@@ -1,8 +1,9 @@
1
-import { encryptAESGEM } from "../data";
1
+import { encryptAESGEM, SocketUpdateDataSource } from "../data";
2 2
 
3 3
 import { SocketUpdateData } from "../types";
4 4
 import { BROADCAST, SCENE } from "../constants";
5 5
 import App from "./App";
6
+import { getSceneVersion, getSyncableElements } from "../element";
6 7
 
7 8
 class Portal {
8 9
   app: App;
@@ -10,6 +11,7 @@ class Portal {
10 11
   socketInitialized: boolean = false; // we don't want the socket to emit any updates until it is fully initialized
11 12
   roomID: string | null = null;
12 13
   roomKey: string | null = null;
14
+  broadcastedElementVersions: Map<string, number> = new Map();
13 15
 
14 16
   constructor(app: App) {
15 17
     this.app = app;
@@ -27,7 +29,7 @@ class Portal {
27 29
       }
28 30
     });
29 31
     this.socket.on("new-user", async (_socketId: string) => {
30
-      this.app.broadcastScene(SCENE.INIT, /* syncAll */ true);
32
+      this.broadcastScene(SCENE.INIT, /* syncAll */ true);
31 33
     });
32 34
     this.socket.on("room-user-change", (clients: string[]) => {
33 35
       this.app.setCollaborators(clients);
@@ -69,5 +71,86 @@ class Portal {
69 71
       );
70 72
     }
71 73
   }
74
+
75
+  broadcastScene = async (
76
+    sceneType: SCENE.INIT | SCENE.UPDATE,
77
+    syncAll: boolean,
78
+  ) => {
79
+    if (sceneType === SCENE.INIT && !syncAll) {
80
+      throw new Error("syncAll must be true when sending SCENE.INIT");
81
+    }
82
+
83
+    let syncableElements = getSyncableElements(
84
+      this.app.getSceneElementsIncludingDeleted(),
85
+    );
86
+
87
+    if (!syncAll) {
88
+      // sync out only the elements we think we need to to save bandwidth.
89
+      // periodically we'll resync the whole thing to make sure no one diverges
90
+      // due to a dropped message (server goes down etc).
91
+      syncableElements = syncableElements.filter(
92
+        (syncableElement) =>
93
+          !this.broadcastedElementVersions.has(syncableElement.id) ||
94
+          syncableElement.version >
95
+            this.broadcastedElementVersions.get(syncableElement.id)!,
96
+      );
97
+    }
98
+
99
+    const data: SocketUpdateDataSource[typeof sceneType] = {
100
+      type: sceneType,
101
+      payload: {
102
+        elements: syncableElements,
103
+      },
104
+    };
105
+    const currentVersion = this.app.getLastBroadcastedOrReceivedSceneVersion();
106
+    const newVersion = Math.max(
107
+      currentVersion,
108
+      getSceneVersion(this.app.getSceneElementsIncludingDeleted()),
109
+    );
110
+    this.app.setLastBroadcastedOrReceivedSceneVersion(newVersion);
111
+
112
+    for (const syncableElement of syncableElements) {
113
+      this.broadcastedElementVersions.set(
114
+        syncableElement.id,
115
+        syncableElement.version,
116
+      );
117
+    }
118
+
119
+    const broadcastPromise = this._broadcastSocketData(
120
+      data as SocketUpdateData,
121
+    );
122
+
123
+    if (syncAll && this.app.state.isCollaborating) {
124
+      await Promise.all([
125
+        broadcastPromise,
126
+        this.app.saveCollabRoomToFirebase(syncableElements),
127
+      ]);
128
+    } else {
129
+      await broadcastPromise;
130
+    }
131
+  };
132
+
133
+  broadcastMouseLocation = (payload: {
134
+    pointer: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["pointer"];
135
+    button: SocketUpdateDataSource["MOUSE_LOCATION"]["payload"]["button"];
136
+  }) => {
137
+    if (this.socket?.id) {
138
+      const data: SocketUpdateDataSource["MOUSE_LOCATION"] = {
139
+        type: "MOUSE_LOCATION",
140
+        payload: {
141
+          socketId: this.socket.id,
142
+          pointer: payload.pointer,
143
+          button: payload.button || "up",
144
+          selectedElementIds: this.app.state.selectedElementIds,
145
+          username: this.app.state.username,
146
+        },
147
+      };
148
+      return this._broadcastSocketData(
149
+        data as SocketUpdateData,
150
+        true, // volatile
151
+      );
152
+    }
153
+  };
72 154
 }
155
+
73 156
 export default Portal;

Notiek ielāde…
Atcelt
Saglabāt