Browse Source

throttle take 2

zsviczian 2 years ago
parent
commit
6ecd843df2
2 changed files with 108 additions and 38 deletions
  1. 107 37
      src/components/App.tsx
  2. 1 1
      src/renderer/renderElement.ts

+ 107 - 37
src/components/App.tsx

@@ -175,7 +175,10 @@ import {
 } from "../keys";
 import { distance2d, getGridPoint, isPathALoop } from "../math";
 import { renderScene } from "../renderer/renderScene";
-import { invalidateShapeForElement } from "../renderer/renderElement";
+import {
+  generateElementWithCanvas,
+  invalidateShapeForElement,
+} from "../renderer/renderElement";
 import {
   calculateScrollCenter,
   getElementsAtPosition,
@@ -1283,10 +1286,7 @@ class App extends React.Component<AppProps, AppState> {
     }
   }
 
-  private renderScene = (
-    renderingElements: NonDeletedExcalidrawElement[] = [],
-    shouldCacheIgnoreZoom: boolean | null = null,
-  ) => {
+  private renderScene = () => {
     const cursorButton: {
       [id: string]: string | undefined;
     } = {};
@@ -1324,26 +1324,25 @@ class App extends React.Component<AppProps, AppState> {
       cursorButton[socketId] = user.button;
     });
 
-    renderingElements =
-      renderingElements.length > 0
-        ? renderingElements
-        : this.scene.getNonDeletedElements().filter((element) => {
-            if (isImageElement(element)) {
-              if (
-                // not placed on canvas yet (but in elements array)
-                this.state.pendingImageElementId === element.id
-              ) {
-                return false;
-              }
-            }
-            // don't render text element that's being currently edited (it's
-            // rendered on remote only)
-            return (
-              !this.state.editingElement ||
-              this.state.editingElement.type !== "text" ||
-              element.id !== this.state.editingElement.id
-            );
-          });
+    const renderingElements = this.scene
+      .getNonDeletedElements()
+      .filter((element) => {
+        if (isImageElement(element)) {
+          if (
+            // not placed on canvas yet (but in elements array)
+            this.state.pendingImageElementId === element.id
+          ) {
+            return false;
+          }
+        }
+        // don't render text element that's being currently edited (it's
+        // rendered on remote only)
+        return (
+          !this.state.editingElement ||
+          this.state.editingElement.type !== "text" ||
+          element.id !== this.state.editingElement.id
+        );
+      });
 
     const selectionColor = getComputedStyle(
       document.querySelector(".excalidraw")!,
@@ -1367,10 +1366,7 @@ class App extends React.Component<AppProps, AppState> {
           remoteSelectedElementIds,
           remotePointerUsernames: pointerUsernames,
           remotePointerUserStates: pointerUserStates,
-          shouldCacheIgnoreZoom:
-            shouldCacheIgnoreZoom === null
-              ? this.state.shouldCacheIgnoreZoom
-              : shouldCacheIgnoreZoom,
+          shouldCacheIgnoreZoom: this.state.shouldCacheIgnoreZoom,
           theme: this.state.theme,
           imageCache: this.imageCache,
           isExporting: false,
@@ -6374,14 +6370,88 @@ class App extends React.Component<AppProps, AppState> {
 
   private resetShouldCacheIgnoreZoomDebounced = debounce(() => {
     if (!this.unmounted) {
-      //generateElementWithCanvas
-      const elements = this.scene.getNonDeletedElements();
-      let i = 0;
-      for (; i < elements.length; i += 200) {
-        const chunk = elements.slice(i, i + 200);
-        setTimeout(() => this.renderScene(chunk, false),i*100);
-      }
-      setTimeout(() => this.setState({ shouldCacheIgnoreZoom: false }),i*100);
+      const cursorButton: {
+        [id: string]: string | undefined;
+      } = {};
+      const pointerViewportCoords: RenderConfig["remotePointerViewportCoords"] =
+        {};
+      const remoteSelectedElementIds: RenderConfig["remoteSelectedElementIds"] =
+        {};
+      const pointerUsernames: { [id: string]: string } = {};
+      const pointerUserStates: { [id: string]: string } = {};
+      this.state.collaborators.forEach((user, socketId) => {
+        if (user.selectedElementIds) {
+          for (const id of Object.keys(user.selectedElementIds)) {
+            if (!(id in remoteSelectedElementIds)) {
+              remoteSelectedElementIds[id] = [];
+            }
+            remoteSelectedElementIds[id].push(socketId);
+          }
+        }
+        if (!user.pointer) {
+          return;
+        }
+        if (user.username) {
+          pointerUsernames[socketId] = user.username;
+        }
+        if (user.userState) {
+          pointerUserStates[socketId] = user.userState;
+        }
+        pointerViewportCoords[socketId] = sceneCoordsToViewportCoords(
+          {
+            sceneX: user.pointer.x,
+            sceneY: user.pointer.y,
+          },
+          this.state,
+        );
+        cursorButton[socketId] = user.button;
+      });
+
+      const renderingElements = this.scene
+        .getNonDeletedElements()
+        .filter((element) => {
+          if (isImageElement(element)) {
+            if (
+              // not placed on canvas yet (but in elements array)
+              this.state.pendingImageElementId === element.id
+            ) {
+              return false;
+            }
+          }
+          // don't render text element that's being currently edited (it's
+          // rendered on remote only)
+          return (
+            !this.state.editingElement ||
+            this.state.editingElement.type !== "text" ||
+            element.id !== this.state.editingElement.id
+          );
+        });
+
+      const selectionColor = getComputedStyle(
+        document.querySelector(".excalidraw")!,
+      ).getPropertyValue("--color-selection");
+
+      const renderConfig: RenderConfig = {
+        selectionColor,
+        scrollX: this.state.scrollX,
+        scrollY: this.state.scrollY,
+        viewBackgroundColor: this.state.viewBackgroundColor,
+        zoom: this.state.zoom,
+        remotePointerViewportCoords: pointerViewportCoords,
+        remotePointerButton: cursorButton,
+        remoteSelectedElementIds,
+        remotePointerUsernames: pointerUsernames,
+        remotePointerUserStates: pointerUserStates,
+        shouldCacheIgnoreZoom: false,
+        theme: this.state.theme,
+        imageCache: this.imageCache,
+        isExporting: false,
+        renderScrollbars: !this.device.isMobile,
+      };
+      renderingElements.forEach((el) =>
+        setTimeout(() => generateElementWithCanvas(el, renderConfig)),
+      );
+      setTimeout(() => this.setState({ shouldCacheIgnoreZoom: false }));
     }
   }, 300);
 

+ 1 - 1
src/renderer/renderElement.ts

@@ -655,7 +655,7 @@ const generateElementShape = (
   }
 };
 
-const generateElementWithCanvas = (
+export const generateElementWithCanvas = (
   element: NonDeletedExcalidrawElement,
   renderConfig: RenderConfig,
 ) => {