Skip to content

Commit

Permalink
support tool locking
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed Jun 29, 2023
1 parent 61795f4 commit 64fc6cc
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 9 deletions.
11 changes: 8 additions & 3 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2858,8 +2858,11 @@ class App extends React.Component<AppProps, AppState> {

private setActiveTool = (
tool:
| { type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame" }
| { type: "custom"; customType: string },
| {
type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame";
locked?: boolean;
}
| { type: "custom"; customType: string; locked?: boolean },
) => {
const nextActiveTool = updateActiveTool(this.state, tool);
if (nextActiveTool.type === "hand") {
Expand Down Expand Up @@ -4224,7 +4227,9 @@ class App extends React.Component<AppProps, AppState> {
pointerDownState,
);
} else if (this.state.activeTool.type === "custom") {
setCursor(this.canvas, CURSOR_TYPE.AUTO);
if (this.state.activeTool.customType === "comment") {
setCursorForShape(this.canvas, this.state);
}
} else if (this.state.activeTool.type === "frame") {
this.createFrameElementOnPointerDown(pointerDownState);
} else if (
Expand Down
95 changes: 91 additions & 4 deletions src/excalidraw-app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import polyfill from "../polyfill";
import LanguageDetector from "i18next-browser-languagedetector";
import { useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import { trackEvent } from "../analytics";
import { getDefaultAppState } from "../appState";
import { ErrorDialog } from "../components/ErrorDialog";
Expand All @@ -21,7 +21,13 @@ import {
} from "../element/types";
import { useCallbackRefState } from "../hooks/useCallbackRefState";
import { t } from "../i18n";
import { Excalidraw, defaultLang } from "../packages/excalidraw/index";
import {
Excalidraw,
defaultLang,
Footer,
Button,
Sidebar,
} from "../packages/excalidraw/index";
import {
AppState,
LibraryItems,
Expand Down Expand Up @@ -80,7 +86,6 @@ import { reconcileElements } from "./collab/reconciliation";
import { parseLibraryTokensFromUrl, useHandleLibrary } from "../data/library";
import { AppMainMenu } from "./components/AppMainMenu";
import { AppWelcomeScreen } from "./components/AppWelcomeScreen";
import { AppFooter } from "./components/AppFooter";
import { atom, Provider, useAtom, useAtomValue } from "jotai";
import { useAtomWithInitialValue } from "../jotai";
import { appJotaiStore } from "./app-jotai";
Expand Down Expand Up @@ -637,6 +642,70 @@ const ExcalidrawWrapper = () => {

const isOffline = useAtomValue(isOfflineAtom);

const [activeToolType, setActiveToolType] = useState<string | null>(null);
const prevActiveTool = useRef<{
type: string;
locked?: boolean;
prevLockState?: boolean;
}>();

const toggleCommentTool = useCallback(() => {
const nextType =
excalidrawAPI?.getAppState().activeTool?.customType === "comment"
? "selection"
: "comment";
excalidrawAPI?.setActiveTool(
nextType === "comment"
? {
type: "custom",
customType: "comment",
locked: true,
}
: { type: "selection" },
);
}, [excalidrawAPI]);

useEffect(() => {
if (excalidrawAPI) {
const unsubOnChange = excalidrawAPI.onChange((_, appState) => {
const type = appState.activeTool.customType || appState.activeTool.type;
if (
prevActiveTool.current?.type === "comment" &&
type !== "comment" &&
!prevActiveTool.current?.prevLockState
) {
excalidrawAPI.setActiveTool({
...appState.activeTool,
locked: false,
});
}
setActiveToolType(type);
prevActiveTool.current = {
type,
locked: appState.activeTool.locked,
prevLockState:
prevActiveTool.current?.type !== "comment"
? prevActiveTool.current?.locked
: prevActiveTool.current?.prevLockState,
};
});

// on C keypress
const onKeyDown = (event: KeyboardEvent) => {
if (event.code === "KeyC") {
toggleCommentTool();
}
};

window.addEventListener("keydown", onKeyDown);

return () => {
window.removeEventListener("keydown", onKeyDown);
unsubOnChange();
};
}
}, [excalidrawAPI, toggleCommentTool]);

return (
<div
style={{ height: "100%" }}
Expand Down Expand Up @@ -711,7 +780,25 @@ const ExcalidrawWrapper = () => {
</OverwriteConfirmDialog.Action>
)}
</OverwriteConfirmDialog>
<AppFooter />
<Sidebar name="custom">test</Sidebar>
<Footer>
<div
style={{
display: "flex",
gap: ".5rem",
alignItems: "center",
marginRight: "auto",
}}
>
<Sidebar.Trigger name="custom">sidebar</Sidebar.Trigger>
<Button
onSelect={toggleCommentTool}
className={clsx({ active: activeToolType === "comment" })}
>
💬
</Button>
</div>
</Footer>
{isCollaborating && isOffline && (
<div className="collab-offline-warning">
{t("alerts.collabOfflineWarning")}
Expand Down
27 changes: 25 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,15 +369,19 @@ export const distance = (x: number, y: number) => Math.abs(x - y);
export const updateActiveTool = (
appState: Pick<AppState, "activeTool">,
data: (
| { type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame" }
| { type: "custom"; customType: string }
| {
type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame";
locked?: boolean;
}
| { type: "custom"; customType: string; locked?: boolean }
) & { lastActiveToolBeforeEraser?: LastActiveTool },
): AppState["activeTool"] => {
if (data.type === "custom") {
return {
...appState.activeTool,
type: "custom",
customType: data.customType,
locked: data.locked ?? appState.activeTool.locked,
};
}

Expand All @@ -389,6 +393,7 @@ export const updateActiveTool = (
: data.lastActiveToolBeforeEraser,
type: data.type,
customType: null,
locked: data.locked ?? appState.activeTool.locked,
};
};

Expand Down Expand Up @@ -464,6 +469,24 @@ export const setCursorForShape = (
// Ignore custom type as well and let host decide
} else if (!["image", "custom"].includes(appState.activeTool.type)) {
canvas.style.cursor = CURSOR_TYPE.CROSSHAIR;
} else if (
appState.activeTool.type === "custom" &&
appState.activeTool.customType === "comment"
) {
const cursorIconUrl = `data:${MIME_TYPES.svg},${encodeURIComponent(`
<svg
width="24"
height="24"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.25 18A3.25 3.25 0 0 1 2 14.75v-8.5A3.25 3.25 0 0 1 5.25 3h13.5A3.25 3.25 0 0 1 22 6.25v8.5A3.25 3.25 0 0 1 18.75 18h-5.738L8 21.75a1.25 1.25 0 0 1-1.999-1V18h-.75Zm7.264-1.5h6.236a1.75 1.75 0 0 0 1.75-1.75v-8.5a1.75 1.75 0 0 0-1.75-1.75H5.25A1.75 1.75 0 0 0 3.5 6.25v8.5c0 .966.784 1.75 1.75 1.75h2.249v3.75l5.015-3.75Z"
fill="${appState.theme === THEME.LIGHT ? "#000" : "#fff"}"
/>
</svg>
`)}`;
canvas.style.cursor = `url(${cursorIconUrl}) 5 20, auto`;
}
};

Expand Down

0 comments on commit 64fc6cc

Please sign in to comment.