import React from "react"; import { AppState } from "../types"; import { ActionManager } from "../actions/manager"; import { t } from "../i18n"; import Stack from "./Stack"; import { showSelectedShapeActions } from "../element"; import { NonDeletedExcalidrawElement } from "../element/types"; import { FixedSideContainer } from "./FixedSideContainer"; import { Island } from "./Island"; import { HintViewer } from "./HintViewer"; import { calculateScrollCenter, getSelectedElements } from "../scene"; import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; import { Section } from "./Section"; import CollabButton from "./CollabButton"; import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars"; import { LockButton } from "./LockButton"; import { UserList } from "./UserList"; import { BackgroundPickerAndDarkModeToggle } from "./BackgroundPickerAndDarkModeToggle"; import { LibraryButton } from "./LibraryButton"; import { PenModeButton } from "./PenModeButton"; type MobileMenuProps = { appState: AppState; actionManager: ActionManager; renderJSONExportDialog: () => React.ReactNode; renderImageExportDialog: () => React.ReactNode; setAppState: React.Component["setState"]; elements: readonly NonDeletedExcalidrawElement[]; libraryMenu: JSX.Element | null; onCollabButtonClick?: () => void; onLockToggle: () => void; onPenModeToggle: () => void; canvas: HTMLCanvasElement | null; isCollaborating: boolean; renderCustomFooter?: (isMobile: boolean, appState: AppState) => JSX.Element; viewModeEnabled: boolean; showThemeBtn: boolean; onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void; renderTopRightUI?: ( isMobile: boolean, appState: AppState, ) => JSX.Element | null; }; export const MobileMenu = ({ appState, elements, libraryMenu, actionManager, renderJSONExportDialog, renderImageExportDialog, setAppState, onCollabButtonClick, onLockToggle, onPenModeToggle, canvas, isCollaborating, renderCustomFooter, viewModeEnabled, showThemeBtn, onImageAction, renderTopRightUI, }: MobileMenuProps) => { const renderToolbar = () => { return (
{(heading) => ( {heading} { onImageAction({ insertOnCanvasDirectly: pointerType !== "mouse", }); }} /> {renderTopRightUI && renderTopRightUI(true, appState)} {libraryMenu} )}
); }; const renderAppToolbar = () => { // Render eraser conditionally in mobile const showEraser = !appState.viewModeEnabled && !appState.editingElement && getSelectedElements(elements, appState).length === 0; if (viewModeEnabled) { return (
{actionManager.renderAction("toggleCanvasMenu")}
); } return (
{actionManager.renderAction("toggleCanvasMenu")} {actionManager.renderAction("toggleEditMenu")} {actionManager.renderAction("undo")} {actionManager.renderAction("redo")} {showEraser && actionManager.renderAction("eraser")} {actionManager.renderAction( appState.multiElement ? "finalize" : "duplicateSelection", )} {actionManager.renderAction("deleteSelectedElements")}
); }; const renderCanvasActions = () => { if (viewModeEnabled) { return ( <> {renderJSONExportDialog()} {renderImageExportDialog()} ); } return ( <> {actionManager.renderAction("clearCanvas")} {actionManager.renderAction("loadScene")} {renderJSONExportDialog()} {renderImageExportDialog()} {onCollabButtonClick && ( )} { } ); }; return ( <> {!viewModeEnabled && renderToolbar()}
{appState.openMenu === "canvas" ? (
{renderCanvasActions()} {renderCustomFooter?.(true, appState)} {appState.collaborators.size > 0 && (
{t("labels.collaborators")} {Array.from(appState.collaborators) // Collaborator is either not initialized or is actually the current user. .filter( ([_, client]) => Object.keys(client).length !== 0, ) .map(([clientId, client]) => ( {actionManager.renderAction("goToCollaborator", { id: clientId, })} ))}
)}
) : appState.openMenu === "shape" && !viewModeEnabled && showSelectedShapeActions(appState, elements) ? (
) : null}
); };