Refactor LayerUI (#1434)
* chore(gitignore): add .idea to gitignore * refactor(layerui): pass named function to react.memo so that in dev tools the name shows up This makes debugging easier as well * refactor(layerui): break the functional component into multiple render methods
This commit is contained in:
parent
9131813661
commit
a18342b5b5
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,3 +12,4 @@ static
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
.idea
|
||||||
|
@ -114,7 +114,7 @@ import {
|
|||||||
TAP_TWICE_TIMEOUT,
|
TAP_TWICE_TIMEOUT,
|
||||||
} from "../time_constants";
|
} from "../time_constants";
|
||||||
|
|
||||||
import { LayerUI } from "./LayerUI";
|
import LayerUI from "./LayerUI";
|
||||||
import { ScrollBars, SceneState } from "../scene/types";
|
import { ScrollBars, SceneState } from "../scene/types";
|
||||||
import { generateCollaborationLink, getCollaborationLinkData } from "../data";
|
import { generateCollaborationLink, getCollaborationLinkData } from "../data";
|
||||||
import { mutateElement, newElementWith } from "../element/mutateElement";
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
||||||
|
@ -40,8 +40,7 @@ interface LayerUIProps {
|
|||||||
onLockToggle: () => void;
|
onLockToggle: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LayerUI = React.memo(
|
const LayerUI = ({
|
||||||
({
|
|
||||||
actionManager,
|
actionManager,
|
||||||
appState,
|
appState,
|
||||||
setAppState,
|
setAppState,
|
||||||
@ -51,10 +50,10 @@ export const LayerUI = React.memo(
|
|||||||
onUsernameChange,
|
onUsernameChange,
|
||||||
onRoomDestroy,
|
onRoomDestroy,
|
||||||
onLockToggle,
|
onLockToggle,
|
||||||
}: LayerUIProps) => {
|
}: LayerUIProps) => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
function renderExportDialog() {
|
const renderExportDialog = () => {
|
||||||
const createExporter = (type: ExportType): ExportCB => (
|
const createExporter = (type: ExportType): ExportCB => (
|
||||||
exportedElements,
|
exportedElements,
|
||||||
scale,
|
scale,
|
||||||
@ -92,44 +91,15 @@ export const LayerUI = React.memo(
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
return isMobile ? (
|
const renderCanvasActions = () => (
|
||||||
<MobileMenu
|
|
||||||
appState={appState}
|
|
||||||
elements={elements}
|
|
||||||
actionManager={actionManager}
|
|
||||||
exportButton={renderExportDialog()}
|
|
||||||
setAppState={setAppState}
|
|
||||||
onUsernameChange={onUsernameChange}
|
|
||||||
onRoomCreate={onRoomCreate}
|
|
||||||
onRoomDestroy={onRoomDestroy}
|
|
||||||
onLockToggle={onLockToggle}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{appState.isLoading && <LoadingMessage />}
|
|
||||||
{appState.errorMessage && (
|
|
||||||
<ErrorDialog
|
|
||||||
message={appState.errorMessage}
|
|
||||||
onClose={() => setAppState({ errorMessage: null })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{appState.showShortcutsDialog && (
|
|
||||||
<ShortcutsDialog
|
|
||||||
onClose={() => setAppState({ showShortcutsDialog: null })}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<FixedSideContainer side="top">
|
|
||||||
<HintViewer appState={appState} elements={elements} />
|
|
||||||
<div className="App-menu App-menu_top">
|
|
||||||
<Stack.Col gap={4}>
|
|
||||||
<Section heading="canvasActions">
|
<Section heading="canvasActions">
|
||||||
{/* the zIndex ensures this menu has higher stacking order,
|
{/* the zIndex ensures this menu has higher stacking order,
|
||||||
see https://github.com/excalidraw/excalidraw/pull/1445 */}
|
see https://github.com/excalidraw/excalidraw/pull/1445 */}
|
||||||
<Island padding={4} style={{ zIndex: 1 }}>
|
<Island padding={4} style={{ zIndex: 1 }}>
|
||||||
<Stack.Col gap={4}>
|
<Stack.Col gap={4}>
|
||||||
<Stack.Row gap={1} justifyContent={"space-between"}>
|
<Stack.Row gap={1} justifyContent="space-between">
|
||||||
{actionManager.renderAction("loadScene")}
|
{actionManager.renderAction("loadScene")}
|
||||||
{actionManager.renderAction("saveScene")}
|
{actionManager.renderAction("saveScene")}
|
||||||
{renderExportDialog()}
|
{renderExportDialog()}
|
||||||
@ -147,7 +117,9 @@ export const LayerUI = React.memo(
|
|||||||
</Stack.Col>
|
</Stack.Col>
|
||||||
</Island>
|
</Island>
|
||||||
</Section>
|
</Section>
|
||||||
{showSelectedShapeActions(appState, elements) && (
|
);
|
||||||
|
|
||||||
|
const renderSelectedShapeActions = () => (
|
||||||
<Section heading="selectedShapeActions">
|
<Section heading="selectedShapeActions">
|
||||||
<Island className={CLASSES.SHAPE_ACTIONS_MENU} padding={4}>
|
<Island className={CLASSES.SHAPE_ACTIONS_MENU} padding={4}>
|
||||||
<SelectedShapeActions
|
<SelectedShapeActions
|
||||||
@ -158,7 +130,20 @@ export const LayerUI = React.memo(
|
|||||||
/>
|
/>
|
||||||
</Island>
|
</Island>
|
||||||
</Section>
|
</Section>
|
||||||
)}
|
);
|
||||||
|
|
||||||
|
const renderFixedSideContainer = () => {
|
||||||
|
const shouldRenderSelectedShapeActions = showSelectedShapeActions(
|
||||||
|
appState,
|
||||||
|
elements,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<FixedSideContainer side="top">
|
||||||
|
<HintViewer appState={appState} elements={elements} />
|
||||||
|
<div className="App-menu App-menu_top">
|
||||||
|
<Stack.Col gap={4}>
|
||||||
|
{renderCanvasActions()}
|
||||||
|
{shouldRenderSelectedShapeActions && renderSelectedShapeActions()}
|
||||||
</Stack.Col>
|
</Stack.Col>
|
||||||
<Section heading="shapes">
|
<Section heading="shapes">
|
||||||
{(heading) => (
|
{(heading) => (
|
||||||
@ -197,9 +182,10 @@ export const LayerUI = React.memo(
|
|||||||
</Stack.Col>
|
</Stack.Col>
|
||||||
</div>
|
</div>
|
||||||
</FixedSideContainer>
|
</FixedSideContainer>
|
||||||
<aside>
|
);
|
||||||
<GitHubCorner />
|
};
|
||||||
</aside>
|
|
||||||
|
const renderFooter = () => (
|
||||||
<footer role="contentinfo">
|
<footer role="contentinfo">
|
||||||
<LanguageList
|
<LanguageList
|
||||||
onChange={(lng) => {
|
onChange={(lng) => {
|
||||||
@ -221,10 +207,44 @@ export const LayerUI = React.memo(
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
|
);
|
||||||
|
|
||||||
|
return isMobile ? (
|
||||||
|
<MobileMenu
|
||||||
|
appState={appState}
|
||||||
|
elements={elements}
|
||||||
|
actionManager={actionManager}
|
||||||
|
exportButton={renderExportDialog()}
|
||||||
|
setAppState={setAppState}
|
||||||
|
onUsernameChange={onUsernameChange}
|
||||||
|
onRoomCreate={onRoomCreate}
|
||||||
|
onRoomDestroy={onRoomDestroy}
|
||||||
|
onLockToggle={onLockToggle}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{appState.isLoading && <LoadingMessage />}
|
||||||
|
{appState.errorMessage && (
|
||||||
|
<ErrorDialog
|
||||||
|
message={appState.errorMessage}
|
||||||
|
onClose={() => setAppState({ errorMessage: null })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{appState.showShortcutsDialog && (
|
||||||
|
<ShortcutsDialog
|
||||||
|
onClose={() => setAppState({ showShortcutsDialog: null })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{renderFixedSideContainer()}
|
||||||
|
<aside>
|
||||||
|
<GitHubCorner />
|
||||||
|
</aside>
|
||||||
|
{renderFooter()}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
(prev, next) => {
|
|
||||||
|
const areEqual = (prev: LayerUIProps, next: LayerUIProps) => {
|
||||||
const getNecessaryObj = (appState: AppState): Partial<AppState> => {
|
const getNecessaryObj = (appState: AppState): Partial<AppState> => {
|
||||||
const {
|
const {
|
||||||
draggingElement,
|
draggingElement,
|
||||||
@ -247,5 +267,6 @@ export const LayerUI = React.memo(
|
|||||||
prev.elements === next.elements &&
|
prev.elements === next.elements &&
|
||||||
keys.every((key) => prevAppState[key] === nextAppState[key])
|
keys.every((key) => prevAppState[key] === nextAppState[key])
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
);
|
|
||||||
|
export default React.memo(LayerUI, areEqual);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user