mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-11-03 20:34:40 +01:00 
			
		
		
		
	Pass Additional props remove localstorage related code for storing data and username from App.tsx to index.tsx (#2057)
Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
		@@ -44,7 +44,6 @@ import {
 | 
			
		||||
} from "../scene";
 | 
			
		||||
import {
 | 
			
		||||
  decryptAESGEM,
 | 
			
		||||
  saveToLocalStorage,
 | 
			
		||||
  loadScene,
 | 
			
		||||
  loadFromBlob,
 | 
			
		||||
  SOCKET_SERVER,
 | 
			
		||||
@@ -146,11 +145,7 @@ import {
 | 
			
		||||
  isBindableElement,
 | 
			
		||||
} from "../element/typeChecks";
 | 
			
		||||
import { actionFinalize, actionDeleteSelected } from "../actions";
 | 
			
		||||
import {
 | 
			
		||||
  restoreUsernameFromLocalStorage,
 | 
			
		||||
  saveUsernameToLocalStorage,
 | 
			
		||||
  loadLibrary,
 | 
			
		||||
} from "../data/localStorage";
 | 
			
		||||
import { loadLibrary } from "../data/localStorage";
 | 
			
		||||
 | 
			
		||||
import throttle from "lodash.throttle";
 | 
			
		||||
import { LinearElementEditor } from "../element/linearElementEditor";
 | 
			
		||||
@@ -310,6 +305,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
      offsetLeft,
 | 
			
		||||
    } = this.state;
 | 
			
		||||
 | 
			
		||||
    const { onUsernameChange } = this.props;
 | 
			
		||||
    const canvasScale = window.devicePixelRatio;
 | 
			
		||||
 | 
			
		||||
    const canvasWidth = canvasDOMWidth * canvasScale;
 | 
			
		||||
@@ -335,13 +331,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
          onRoomCreate={this.openPortal}
 | 
			
		||||
          onRoomDestroy={this.closePortal}
 | 
			
		||||
          onUsernameChange={(username) => {
 | 
			
		||||
            if (this.props.onUsernameChange) {
 | 
			
		||||
              this.props.onUsernameChange(username);
 | 
			
		||||
            }
 | 
			
		||||
            saveUsernameToLocalStorage(username);
 | 
			
		||||
            this.setState({
 | 
			
		||||
              username,
 | 
			
		||||
            });
 | 
			
		||||
            onUsernameChange && onUsernameChange(username);
 | 
			
		||||
            this.setState({ username });
 | 
			
		||||
          }}
 | 
			
		||||
          onLockToggle={this.toggleLock}
 | 
			
		||||
          onInsertShape={(elements) =>
 | 
			
		||||
@@ -434,8 +425,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
  private onBlur = withBatchedUpdates(() => {
 | 
			
		||||
    isHoldingSpace = false;
 | 
			
		||||
    this.setState({ isBindingEnabled: true });
 | 
			
		||||
    this.saveDebounced();
 | 
			
		||||
    this.saveDebounced.flush();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  private onUnload = () => {
 | 
			
		||||
@@ -510,7 +499,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
    let isCollaborationScene = !!getCollaborationLinkData(window.location.href);
 | 
			
		||||
    const isExternalScene = !!(id || jsonMatch || isCollaborationScene);
 | 
			
		||||
 | 
			
		||||
    if (isExternalScene && !this.props.initialData) {
 | 
			
		||||
    if (isExternalScene) {
 | 
			
		||||
      if (
 | 
			
		||||
        this.shouldForceLoadScene(scene) ||
 | 
			
		||||
        window.confirm(t("alerts.loadSceneOverridePrompt"))
 | 
			
		||||
@@ -840,7 +829,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
    if (this.state.scrolledOutside !== scrolledOutside) {
 | 
			
		||||
      this.setState({ scrolledOutside: scrolledOutside });
 | 
			
		||||
    }
 | 
			
		||||
    this.saveDebounced();
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      getDrawingVersion(this.scene.getElementsIncludingDeleted()) >
 | 
			
		||||
@@ -1433,16 +1421,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
    },
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  restoreUserName() {
 | 
			
		||||
    const username = restoreUsernameFromLocalStorage();
 | 
			
		||||
 | 
			
		||||
    if (username !== null) {
 | 
			
		||||
      this.setState({
 | 
			
		||||
        username,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Input handling
 | 
			
		||||
 | 
			
		||||
  private onKeyDown = withBatchedUpdates((event: KeyboardEvent) => {
 | 
			
		||||
@@ -3679,10 +3657,6 @@ class App extends React.Component<ExcalidrawProps, AppState> {
 | 
			
		||||
    this.setState({ shouldCacheIgnoreZoom: false });
 | 
			
		||||
  }, 300);
 | 
			
		||||
 | 
			
		||||
  private saveDebounced = debounce(() => {
 | 
			
		||||
    saveToLocalStorage(this.scene.getElementsIncludingDeleted(), this.state);
 | 
			
		||||
  }, 300);
 | 
			
		||||
 | 
			
		||||
  private getCanvasOffsets() {
 | 
			
		||||
    if (this.excalidrawRef?.current) {
 | 
			
		||||
      const parentElement = this.excalidrawRef.current.parentElement;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,6 @@ class Portal {
 | 
			
		||||
    this.socket.on("init-room", () => {
 | 
			
		||||
      if (this.socket) {
 | 
			
		||||
        this.socket.emit("join-room", this.roomID);
 | 
			
		||||
 | 
			
		||||
        this.app.restoreUserName();
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    this.socket.on("new-user", async (_socketId: string) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,12 +18,10 @@ import { serializeAsJSON } from "./json";
 | 
			
		||||
 | 
			
		||||
import { ExportType } from "../scene/types";
 | 
			
		||||
import { restore } from "./restore";
 | 
			
		||||
import { restoreFromLocalStorage } from "./localStorage";
 | 
			
		||||
import { DataState } from "./types";
 | 
			
		||||
 | 
			
		||||
export { loadFromBlob } from "./blob";
 | 
			
		||||
export { saveAsJSON, loadFromJSON } from "./json";
 | 
			
		||||
export { saveToLocalStorage } from "./localStorage";
 | 
			
		||||
 | 
			
		||||
const BACKEND_GET = process.env.REACT_APP_BACKEND_V1_GET_URL;
 | 
			
		||||
 | 
			
		||||
@@ -233,7 +231,7 @@ export const exportToBackend = async (
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const importFromBackend = async (
 | 
			
		||||
const importFromBackend = async (
 | 
			
		||||
  id: string | null,
 | 
			
		||||
  privateKey?: string | null,
 | 
			
		||||
) => {
 | 
			
		||||
@@ -246,7 +244,7 @@ export const importFromBackend = async (
 | 
			
		||||
    );
 | 
			
		||||
    if (!response.ok) {
 | 
			
		||||
      window.alert(t("alerts.importBackendFailed"));
 | 
			
		||||
      return restore(elements, appState);
 | 
			
		||||
      return { elements, appState };
 | 
			
		||||
    }
 | 
			
		||||
    let data;
 | 
			
		||||
    if (privateKey) {
 | 
			
		||||
@@ -277,7 +275,7 @@ export const importFromBackend = async (
 | 
			
		||||
    window.alert(t("alerts.importBackendFailed"));
 | 
			
		||||
    console.error(error);
 | 
			
		||||
  } finally {
 | 
			
		||||
    return restore(elements, appState);
 | 
			
		||||
    return { elements, appState };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -374,9 +372,13 @@ export const loadScene = async (
 | 
			
		||||
  if (id != null) {
 | 
			
		||||
    // the private key is used to decrypt the content from the server, take
 | 
			
		||||
    // extra care not to leak it
 | 
			
		||||
    data = await importFromBackend(id, privateKey);
 | 
			
		||||
    const { elements, appState } = await importFromBackend(id, privateKey);
 | 
			
		||||
    data = restore(elements, appState);
 | 
			
		||||
  } else {
 | 
			
		||||
    data = initialData || restoreFromLocalStorage();
 | 
			
		||||
    data = restore(
 | 
			
		||||
      initialData?.elements ?? [],
 | 
			
		||||
      initialData?.appState ?? getDefaultAppState(),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ export const saveUsernameToLocalStorage = (username: string) => {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const restoreUsernameFromLocalStorage = (): string | null => {
 | 
			
		||||
export const importUsernameFromLocalStorage = (): string | null => {
 | 
			
		||||
  try {
 | 
			
		||||
    const data = localStorage.getItem(LOCAL_STORAGE_KEY_COLLAB);
 | 
			
		||||
    if (data) {
 | 
			
		||||
@@ -95,7 +95,7 @@ export const saveToLocalStorage = (
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const restoreFromLocalStorage = () => {
 | 
			
		||||
export const importFromLocalStorage = () => {
 | 
			
		||||
  let savedElements = null;
 | 
			
		||||
  let savedState = null;
 | 
			
		||||
 | 
			
		||||
@@ -131,5 +131,5 @@ export const restoreFromLocalStorage = () => {
 | 
			
		||||
      // Do nothing because appState is already null
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return restore(elements, appState);
 | 
			
		||||
  return { elements, appState };
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import React, { useState, useLayoutEffect } from "react";
 | 
			
		||||
import React, { useState, useLayoutEffect, useEffect } from "react";
 | 
			
		||||
import ReactDOM from "react-dom";
 | 
			
		||||
import * as Sentry from "@sentry/browser";
 | 
			
		||||
import * as SentryIntegrations from "@sentry/integrations";
 | 
			
		||||
@@ -9,6 +9,19 @@ import Excalidraw from "./excalidraw-embed/index";
 | 
			
		||||
import { register as registerServiceWorker } from "./serviceWorker";
 | 
			
		||||
 | 
			
		||||
import { loadFromBlob } from "./data";
 | 
			
		||||
import { debounce } from "./utils";
 | 
			
		||||
import {
 | 
			
		||||
  importFromLocalStorage,
 | 
			
		||||
  importUsernameFromLocalStorage,
 | 
			
		||||
  saveUsernameToLocalStorage,
 | 
			
		||||
  saveToLocalStorage,
 | 
			
		||||
} from "./data/localStorage";
 | 
			
		||||
 | 
			
		||||
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./time_constants";
 | 
			
		||||
import { DataState } from "./data/types";
 | 
			
		||||
import { LoadingMessage } from "./components/LoadingMessage";
 | 
			
		||||
import { ExcalidrawElement } from "./element/types";
 | 
			
		||||
import { AppState } from "./types";
 | 
			
		||||
 | 
			
		||||
// On Apple mobile devices add the proprietary app icon and splashscreen markup.
 | 
			
		||||
// No one should have to do this manually, and eventually this annoyance will
 | 
			
		||||
@@ -60,29 +73,89 @@ Sentry.init({
 | 
			
		||||
 | 
			
		||||
window.__EXCALIDRAW_SHA__ = REACT_APP_GIT_SHA;
 | 
			
		||||
 | 
			
		||||
const saveDebounced = debounce(
 | 
			
		||||
  (elements: readonly ExcalidrawElement[], state: AppState) => {
 | 
			
		||||
    saveToLocalStorage(elements, state);
 | 
			
		||||
  },
 | 
			
		||||
  SAVE_TO_LOCAL_STORAGE_TIMEOUT,
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const onUsernameChange = (username: string) => {
 | 
			
		||||
  saveUsernameToLocalStorage(username);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const onBlur = () => {
 | 
			
		||||
  saveDebounced.flush();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function ExcalidrawApp() {
 | 
			
		||||
  // dimensions
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  const [dimensions, setDimensions] = useState({
 | 
			
		||||
    width: window.innerWidth,
 | 
			
		||||
    height: window.innerHeight,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const onResize = () => {
 | 
			
		||||
    setDimensions({
 | 
			
		||||
      width: window.innerWidth,
 | 
			
		||||
      height: window.innerHeight,
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  useLayoutEffect(() => {
 | 
			
		||||
    const onResize = () => {
 | 
			
		||||
      setDimensions({
 | 
			
		||||
        width: window.innerWidth,
 | 
			
		||||
        height: window.innerHeight,
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    window.addEventListener("resize", onResize);
 | 
			
		||||
 | 
			
		||||
    return () => window.removeEventListener("resize", onResize);
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const { width, height } = dimensions;
 | 
			
		||||
  // initial state
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  const [initialState, setInitialState] = useState<{
 | 
			
		||||
    data: DataState;
 | 
			
		||||
    user: {
 | 
			
		||||
      name: string | null;
 | 
			
		||||
    };
 | 
			
		||||
  } | null>(null);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    setInitialState({
 | 
			
		||||
      data: importFromLocalStorage(),
 | 
			
		||||
      user: {
 | 
			
		||||
        name: importUsernameFromLocalStorage(),
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  // blur/unload
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    window.addEventListener(EVENT.UNLOAD, onBlur, false);
 | 
			
		||||
    window.addEventListener(EVENT.BLUR, onBlur, false);
 | 
			
		||||
    return () => {
 | 
			
		||||
      window.removeEventListener(EVENT.UNLOAD, onBlur, false);
 | 
			
		||||
      window.removeEventListener(EVENT.BLUR, onBlur, false);
 | 
			
		||||
    };
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  // ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  if (!initialState) {
 | 
			
		||||
    return <LoadingMessage />;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <TopErrorBoundary>
 | 
			
		||||
      <Excalidraw width={width} height={height} />
 | 
			
		||||
      <Excalidraw
 | 
			
		||||
        width={dimensions.width}
 | 
			
		||||
        height={dimensions.height}
 | 
			
		||||
        onChange={saveDebounced}
 | 
			
		||||
        initialData={initialState.data}
 | 
			
		||||
        user={initialState.user}
 | 
			
		||||
        onUsernameChange={onUsernameChange}
 | 
			
		||||
      />
 | 
			
		||||
    </TopErrorBoundary>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,3 +3,4 @@ export const TAP_TWICE_TIMEOUT = 300;
 | 
			
		||||
export const INITIAL_SCENE_UPDATE_TIMEOUT = 5000;
 | 
			
		||||
export const SYNC_FULL_SCENE_INTERVAL_MS = 20000;
 | 
			
		||||
export const TOUCH_CTX_MENU_TIMEOUT = 500;
 | 
			
		||||
export const SAVE_TO_LOCAL_STORAGE_TIMEOUT = 300;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user