Skip to content

Commit

Permalink
[pr] command palette
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed Mar 27, 2024
1 parent 17fe000 commit 838ed52
Show file tree
Hide file tree
Showing 61 changed files with 5,147 additions and 309 deletions.
206 changes: 206 additions & 0 deletions excalidraw-app/App.tsx
Expand Up @@ -50,6 +50,7 @@ import {
} from "../packages/excalidraw/utils";
import {
FIREBASE_STORAGE_PREFIXES,
isExcalidrawPlusSignedUser,
STORAGE_KEYS,
SYNC_BROWSER_TABS_TIMEOUT,
} from "./app_constants";
Expand Down Expand Up @@ -109,6 +110,19 @@ import { OverwriteConfirmDialog } from "../packages/excalidraw/components/Overwr
import Trans from "../packages/excalidraw/components/Trans";
import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog";
import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError";
import {
CommandPalette,
DEFAULT_CATEGORIES,
} from "../packages/excalidraw/components/CommandPalette/CommandPalette";
import {
GithubIcon,
XBrandIcon,
DiscordIcon,
ExcalLogo,
usersIcon,
exportToPlus,
share,
} from "../packages/excalidraw/components/icons";

polyfill();

Expand Down Expand Up @@ -763,6 +777,45 @@ const ExcalidrawWrapper = () => {
);
}

const ExcalidrawPlusCommand = {
label: "Excalidraw+",
category: DEFAULT_CATEGORIES.links,
predicate: true,
icon: <div style={{ width: 14 }}>{ExcalLogo}</div>,
keywords: ["plus", "cloud", "server"],
perform: () => {
window.open(
`${
import.meta.env.VITE_APP_PLUS_LP
}/plus?utm_source=excalidraw&utm_medium=app&utm_content=command_palette`,
"_blank",
);
},
};
const ExcalidrawPlusAppCommand = {
label: t("labels.signin"),
category: DEFAULT_CATEGORIES.links,
predicate: true,
icon: <div style={{ width: 14 }}>{ExcalLogo}</div>,
keywords: [
"excalidraw",
"plus",
"cloud",
"server",
"signin",
"login",
"signup",
],
perform: () => {
window.open(
`${
import.meta.env.VITE_APP_PLUS_APP
}?utm_source=excalidraw&utm_medium=app&utm_content=command_palette`,
"_blank",
);
},
};

return (
<div
style={{ height: "100%" }}
Expand Down Expand Up @@ -976,6 +1029,159 @@ const ExcalidrawWrapper = () => {
{errorMessage}
</ErrorDialog>
)}

<CommandPalette
customCommandPaletteItems={[
{
label: t("labels.liveCollaboration"),
category: DEFAULT_CATEGORIES.app,
keywords: [
"team",
"multiplayer",
"share",
"public",
"session",
"invite",
],
icon: usersIcon,
perform: () => {
setShareDialogState({
isOpen: true,
type: "collaborationOnly",
});
},
},
{
label: t("roomDialog.button_stopSession"),
category: DEFAULT_CATEGORIES.app,
predicate: () => !!collabAPI?.isCollaborating(),
keywords: [
"stop",
"session",
"end",
"leave",
"close",
"exit",
"collaboration",
],
perform: () => {
if (collabAPI) {
collabAPI.stopCollaboration();
if (!collabAPI.isCollaborating()) {
setShareDialogState({ isOpen: false });
}
}
},
},
{
label: t("labels.share"),
category: DEFAULT_CATEGORIES.app,
predicate: true,
icon: share,
keywords: [
"link",
"shareable",
"readonly",
"export",
"publish",
"snapshot",
"url",
"collaborate",
"invite",
],
perform: async () => {
setShareDialogState({ isOpen: true, type: "share" });
},
},
{
label: "GitHub",
icon: GithubIcon,
category: DEFAULT_CATEGORIES.links,
predicate: true,
keywords: [
"issues",
"bugs",
"requests",
"report",
"features",
"social",
"community",
],
perform: () => {
window.open(
"https://github.com/excalidraw/excalidraw",
"_blank",
"noopener noreferrer",
);
},
},
{
label: t("labels.followUs"),
icon: XBrandIcon,
category: DEFAULT_CATEGORIES.links,
predicate: true,
keywords: ["twitter", "contact", "social", "community"],
perform: () => {
window.open(
"https://x.com/excalidraw",
"_blank",
"noopener noreferrer",
);
},
},
{
label: t("labels.discordChat"),
category: DEFAULT_CATEGORIES.links,
predicate: true,
icon: DiscordIcon,
keywords: [
"chat",
"talk",
"contact",
"bugs",
"requests",
"report",
"feedback",
"suggestions",
"social",
"community",
],
perform: () => {
window.open(
"https://discord.gg/UexuTaE",
"_blank",
"noopener noreferrer",
);
},
},
...(isExcalidrawPlusSignedUser
? [
{
...ExcalidrawPlusAppCommand,
label: "Sign in / Go to Excalidraw+",
},
]
: [ExcalidrawPlusCommand, ExcalidrawPlusAppCommand]),

{
label: t("overwriteConfirm.action.excalidrawPlus.button"),
category: DEFAULT_CATEGORIES.export,
icon: exportToPlus,
predicate: true,
keywords: ["plus", "export", "save", "backup"],
perform: () => {
if (excalidrawAPI) {
exportToExcalidrawPlus(
excalidrawAPI.getSceneElements(),
excalidrawAPI.getAppState(),
excalidrawAPI.getFiles(),
excalidrawAPI.getName(),
);
}
},
},
]}
/>
</Excalidraw>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion excalidraw-app/components/AppMainMenu.tsx
Expand Up @@ -19,7 +19,7 @@ export const AppMainMenu: React.FC<{
onSelect={() => props.onCollabDialogOpen()}
/>
)}

<MainMenu.DefaultItems.CommandPalette />
<MainMenu.DefaultItems.Help />
<MainMenu.DefaultItems.ClearCanvas />
<MainMenu.Separator />
Expand Down
2 changes: 2 additions & 0 deletions excalidraw-app/components/TopErrorBoundary.tsx
Expand Up @@ -67,6 +67,8 @@ export class TopErrorBoundary extends React.Component<

window.open(
`https://github.com/excalidraw/excalidraw/issues/new?body=${body}`,
"_blank",
"noopener noreferrer",
);
}

Expand Down
13 changes: 11 additions & 2 deletions excalidraw-app/share/ShareDialog.tsx
@@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import * as Popover from "@radix-ui/react-popover";
import { copyTextToSystemClipboard } from "../../packages/excalidraw/clipboard";
import { trackEvent } from "../../packages/excalidraw/analytics";
Expand All @@ -22,6 +22,7 @@ import { activeRoomLinkAtom, CollabAPI } from "../collab/Collab";
import { atom, useAtom, useAtomValue } from "jotai";

import "./ShareDialog.scss";
import { useUIAppState } from "../../packages/excalidraw/context/ui-appState";

type OnExportToBackend = () => void;
type ShareDialogType = "share" | "collaborationOnly";
Expand Down Expand Up @@ -275,6 +276,14 @@ export const ShareDialog = (props: {
}) => {
const [shareDialogState, setShareDialogState] = useAtom(shareDialogStateAtom);

const { openDialog } = useUIAppState();

useEffect(() => {
if (openDialog) {
setShareDialogState({ isOpen: false });
}
}, [openDialog, setShareDialogState]);

if (!shareDialogState.isOpen) {
return null;
}
Expand All @@ -285,6 +294,6 @@ export const ShareDialog = (props: {
collabAPI={props.collabAPI}
onExportToBackend={props.onExportToBackend}
type={shareDialogState.type}
></ShareDialogInner>
/>
);
};
2 changes: 2 additions & 0 deletions packages/excalidraw/CHANGELOG.md
Expand Up @@ -23,6 +23,8 @@ Please add the latest change on the top under the correct section.

- Expose `getVisibleSceneBounds` helper to get scene bounds of visible canvas area. [#7450](https://github.com/excalidraw/excalidraw/pull/7450)

- Add CommandPalette component for users to quickly find and discover commands to speed up their workflow. Apart from the core commands built into the component, custom command items can be passed as a prop. [#7804](https://github.com/excalidraw/excalidraw/pull/7804)

### Fixes

- Keep customData when converting to ExcalidrawElement. [#7656](https://github.com/excalidraw/excalidraw/pull/7656)
Expand Down
2 changes: 1 addition & 1 deletion packages/excalidraw/actions/actionAddToLibrary.ts
Expand Up @@ -58,5 +58,5 @@ export const actionAddToLibrary = register({
};
});
},
contextItemLabel: "labels.addToLibrary",
label: "labels.addToLibrary",
});
16 changes: 14 additions & 2 deletions packages/excalidraw/actions/actionAlign.tsx
Expand Up @@ -15,13 +15,13 @@ import { updateFrameMembershipOfSelectedElements } from "../frame";
import { t } from "../i18n";
import { KEYS } from "../keys";
import { isSomeElementSelected } from "../scene";
import { AppClassProperties, AppState } from "../types";
import { AppClassProperties, AppState, UIAppState } from "../types";
import { arrayToMap, getShortcutKey } from "../utils";
import { register } from "./register";

const alignActionsPredicate = (
elements: readonly ExcalidrawElement[],
appState: AppState,
appState: UIAppState,
_: unknown,
app: AppClassProperties,
) => {
Expand Down Expand Up @@ -59,6 +59,8 @@ const alignSelectedElements = (

export const actionAlignTop = register({
name: "alignTop",
label: "labels.alignTop",
icon: AlignTopIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down Expand Up @@ -90,6 +92,8 @@ export const actionAlignTop = register({

export const actionAlignBottom = register({
name: "alignBottom",
label: "labels.alignBottom",
icon: AlignBottomIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down Expand Up @@ -121,6 +125,8 @@ export const actionAlignBottom = register({

export const actionAlignLeft = register({
name: "alignLeft",
label: "labels.alignLeft",
icon: AlignLeftIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down Expand Up @@ -152,6 +158,8 @@ export const actionAlignLeft = register({

export const actionAlignRight = register({
name: "alignRight",
label: "labels.alignRight",
icon: AlignRightIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down Expand Up @@ -183,6 +191,8 @@ export const actionAlignRight = register({

export const actionAlignVerticallyCentered = register({
name: "alignVerticallyCentered",
label: "labels.centerVertically",
icon: CenterVerticallyIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down Expand Up @@ -210,6 +220,8 @@ export const actionAlignVerticallyCentered = register({

export const actionAlignHorizontallyCentered = register({
name: "alignHorizontallyCentered",
label: "labels.centerHorizontally",
icon: CenterHorizontallyIcon,
trackEvent: { category: "element" },
predicate: alignActionsPredicate,
perform: (elements, appState, _, app) => {
Expand Down

0 comments on commit 838ed52

Please sign in to comment.