import React from "react"; import { showSelectedShapeActions } from "../element"; import { calculateScrollCenter } from "../scene"; import { exportCanvas } from "../data"; import { AppState } from "../types"; import { NonDeletedExcalidrawElement } from "../element/types"; import { ActionManager } from "../actions/manager"; import { Island } from "./Island"; import Stack from "./Stack"; import { FixedSideContainer } from "./FixedSideContainer"; import { LockIcon } from "./LockIcon"; import { ExportDialog, ExportCB } from "./ExportDialog"; import { LanguageList } from "./LanguageList"; import { t, languages, setLanguage } from "../i18n"; import { HintViewer } from "./HintViewer"; import useIsMobile from "../is-mobile"; import { ExportType } from "../scene/types"; import { MobileMenu } from "./MobileMenu"; import { ZoomActions, SelectedShapeActions, ShapesSwitcher } from "./Actions"; import { Section } from "./Section"; import { RoomDialog } from "./RoomDialog"; import { ErrorDialog } from "./ErrorDialog"; import { ShortcutsDialog } from "./ShortcutsDialog"; import { LoadingMessage } from "./LoadingMessage"; import { GitHubCorner } from "./GitHubCorner"; interface LayerUIProps { actionManager: ActionManager; appState: AppState; canvas: HTMLCanvasElement | null; setAppState: any; elements: readonly NonDeletedExcalidrawElement[]; onRoomCreate: () => void; onUsernameChange: (username: string) => void; onRoomDestroy: () => void; onLockToggle: () => void; } export const LayerUI = React.memo( ({ actionManager, appState, setAppState, canvas, elements, onRoomCreate, onUsernameChange, onRoomDestroy, onLockToggle, }: LayerUIProps) => { const isMobile = useIsMobile(); function renderExportDialog() { const createExporter = (type: ExportType): ExportCB => ( exportedElements, scale, ) => { if (canvas) { exportCanvas(type, exportedElements, appState, canvas, { exportBackground: appState.exportBackground, name: appState.name, viewBackgroundColor: appState.viewBackgroundColor, scale, }); } }; return ( { if (canvas) { exportCanvas( "backend", exportedElements, { ...appState, selectedElementIds: {}, }, canvas, appState, ); } }} /> ); } return isMobile ? ( ) : ( <> {appState.isLoading && } {appState.errorMessage && ( setAppState({ errorMessage: null })} /> )} {appState.showShortcutsDialog && ( setAppState({ showShortcutsDialog: null })} /> )}
{actionManager.renderAction("loadScene")} {actionManager.renderAction("saveScene")} {renderExportDialog()} {actionManager.renderAction("clearCanvas")} {actionManager.renderAction("changeViewBackgroundColor")}
{showSelectedShapeActions(appState, elements) && (
)}
{(heading) => ( {heading} )}
{ setLanguage(lng); setAppState({}); }} languages={languages} floating /> {actionManager.renderAction("toggleShortcuts")} {appState.scrolledOutside && ( )}
); }, (prev, next) => { const getNecessaryObj = (appState: AppState): Partial => { const { draggingElement, resizingElement, multiElement, editingElement, isResizing, cursorX, cursorY, ...ret } = appState; return ret; }; const prevAppState = getNecessaryObj(prev.appState); const nextAppState = getNecessaryObj(next.appState); const keys = Object.keys(prevAppState) as (keyof Partial)[]; return ( prev.elements === next.elements && keys.every((key) => prevAppState[key] === nextAppState[key]) ); }, );