Merge branch 'master' of github.com:excalidraw/excalidraw into cleanipp

* 'master' of github.com:excalidraw/excalidraw: (37 commits)
  feat: Add toast (#2772)
  docs: Update readme with documentation (#2788)
  fix: allow text-selecting in dialogs & reset cursor (#2783)
  chore: Update translations from Crowdin (#2742)
  fix: broken Individuals link (#2782)
  refactor: Converting span to kbd tag (#2774)
  fix: don't render due to zoom after unmount (#2779)
  fix: Track the chart type correctly (#2773)
  chore(deps-dev): bump terser-webpack-plugin in /src/packages/excalidraw (#2750)
  chore(deps-dev): bump webpack in /src/packages/utils (#2768)
  fix: delay version logging & prevent duplicates (#2770)
  chore(deps-dev): bump webpack in /src/packages/excalidraw (#2769)
  chore(deps-dev): bump ts-loader in /src/packages/excalidraw (#2749)
  chore(deps-dev): bump ts-loader in /src/packages/utils (#2753)
  chore(deps): bump nanoid from 2.1.11 to 3.1.20 (#2581)
  feat: Track current version (#2731)
  chore(actions): Use cancel workflow action (#2763)
  chore(deps): bump @testing-library/react from 11.2.2 to 11.2.3 (#2755)
  chore(deps-dev): bump firebase-tools from 9.1.0 to 9.1.2 (#2761)
  chore(deps-dev): bump eslint-plugin-prettier from 3.3.0 to 3.3.1 (#2754)
  ...
This commit is contained in:
Panayiotis Lipiridis 2021-01-15 18:30:11 +02:00
commit 1eb8920bc3
115 changed files with 2445 additions and 4938 deletions

View file

@ -1,34 +1,53 @@
import React, { useState, useLayoutEffect, useEffect, useRef } from "react";
import Excalidraw from "../packages/excalidraw/index";
import LanguageDetector from "i18next-browser-languagedetector";
import React, {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import { ExcalidrawImperativeAPI } from "../components/App";
import { ErrorDialog } from "../components/ErrorDialog";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { APP_NAME, EVENT, TITLE_TIMEOUT } from "../constants";
import { ImportedDataState } from "../data/types";
import {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "../element/types";
import { Language, t } from "../i18n";
import Excalidraw, {
defaultLang,
languages,
} from "../packages/excalidraw/index";
import { AppState, ExcalidrawAPIRefValue } from "../types";
import {
debounce,
getVersion,
ResolvablePromise,
resolvablePromise,
} from "../utils";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
import { LanguageList } from "./components/LanguageList";
import { exportToBackend, getCollaborationLinkData, loadScene } from "./data";
import { loadFromFirebase } from "./data/firebase";
import {
getTotalStorageSize,
importFromLocalStorage,
saveToLocalStorage,
STORAGE_KEYS,
} from "./data/localStorage";
import { ImportedDataState } from "../data/types";
import CollabWrapper, { CollabAPI } from "./collab/CollabWrapper";
import { TopErrorBoundary } from "../components/TopErrorBoundary";
import { t } from "../i18n";
import { exportToBackend, loadScene } from "./data";
import { getCollaborationLinkData } from "./data";
import { EVENT } from "../constants";
import { loadFromFirebase } from "./data/firebase";
import { ExcalidrawImperativeAPI } from "../components/App";
import { debounce, ResolvablePromise, resolvablePromise } from "../utils";
import { AppState, ExcalidrawAPIRefValue } from "../types";
import {
ExcalidrawElement,
NonDeletedExcalidrawElement,
} from "../element/types";
import { SAVE_TO_LOCAL_STORAGE_TIMEOUT } from "./app_constants";
import { EVENT_LOAD, EVENT_SHARE, trackEvent } from "../analytics";
import { ErrorDialog } from "../components/ErrorDialog";
import { getDefaultAppState } from "../appState";
import { APP_NAME, TITLE_TIMEOUT } from "../constants";
const languageDetector = new LanguageDetector();
languageDetector.init({
languageUtils: {
formatLanguageCode: (langCode: Language["code"]) => langCode,
isWhitelisted: () => true,
},
checkWhitelist: false,
});
const excalidrawRef: React.MutableRefObject<
MarkRequired<ExcalidrawAPIRefValue, "ready" | "readyPromise">
@ -143,7 +162,6 @@ const initializeScene = async (opts: {
// into the remote scene
opts.resetScene();
const scenePromise = opts.initializeSocketClient();
trackEvent(EVENT_SHARE, "session join");
try {
const [, roomId, roomKey] = getCollaborationLinkData(
@ -182,6 +200,8 @@ const ExcalidrawWrapper = (props: { collab: CollabAPI }) => {
height: window.innerHeight,
});
const [errorMessage, setErrorMessage] = useState("");
const currentLangCode = languageDetector.detect() || defaultLang.code;
const [langCode, setLangCode] = useState(currentLangCode);
useLayoutEffect(() => {
const onResize = () => {
@ -209,12 +229,19 @@ const ExcalidrawWrapper = (props: { collab: CollabAPI }) => {
const { collab } = props;
useEffect(() => {
const storageSize = getTotalStorageSize();
if (storageSize) {
trackEvent(EVENT_LOAD, "storage", "size", storageSize);
} else {
trackEvent(EVENT_LOAD, "first time");
}
// delayed by 15 sec so that the app has a time to load the latest SW
setTimeout(() => {
const version = getVersion();
const loggedVersion = window.localStorage.getItem(
"excalidraw-lastLoggedVersion",
);
// prevent logging on multiple visits
if (version && version !== loggedVersion) {
window.localStorage.setItem("excalidraw-lastLoggedVersion", version);
trackEvent("load", "version", version);
}
}, 15000);
excalidrawRef.current!.readyPromise.then((excalidrawApi) => {
initializeScene({
resetScene: excalidrawApi.resetScene,
@ -256,6 +283,10 @@ const ExcalidrawWrapper = (props: { collab: CollabAPI }) => {
};
}, [collab.initializeSocketClient]);
useEffect(() => {
languageDetector.cacheUserLanguage(langCode);
}, [langCode]);
const onChange = (
elements: readonly ExcalidrawElement[],
appState: AppState,
@ -291,6 +322,32 @@ const ExcalidrawWrapper = (props: { collab: CollabAPI }) => {
}
}
};
const renderFooter = useCallback(
(isMobile: boolean) => {
const renderLanguageList = () => (
<LanguageList
onChange={(langCode) => {
setLangCode(langCode);
}}
languages={languages}
floating={!isMobile}
currentLangCode={langCode}
/>
);
if (isMobile) {
return (
<fieldset>
<legend>{t("labels.language")}</legend>
{renderLanguageList()}
</fieldset>
);
}
return renderLanguageList();
},
[langCode],
);
return (
<>
<Excalidraw
@ -304,6 +361,8 @@ const ExcalidrawWrapper = (props: { collab: CollabAPI }) => {
isCollaborating={collab.isCollaborating}
onPointerUpdate={collab.onPointerUpdate}
onExportToBackend={onExportToBackend}
renderFooter={renderFooter}
langCode={langCode}
/>
{errorMessage && (
<ErrorDialog