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 28, 2024
1 parent 4987503 commit d6a02b4
Show file tree
Hide file tree
Showing 62 changed files with 5,189 additions and 315 deletions.
207 changes: 207 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,160 @@ 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(),
);
}
},
},
CommandPalette.defaultItems.toggleTheme,
]}
/>
</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: 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
6 changes: 3 additions & 3 deletions packages/excalidraw/actions/actionBoundText.tsx
Expand Up @@ -36,7 +36,7 @@ import { register } from "./register";

export const actionUnbindText = register({
name: "unbindText",
contextItemLabel: "labels.unbindText",
label: "labels.unbindText",
trackEvent: { category: "element" },
predicate: (elements, appState, _, app) => {
const selectedElements = app.scene.getSelectedElements(appState);
Expand Down Expand Up @@ -91,7 +91,7 @@ export const actionUnbindText = register({

export const actionBindText = register({
name: "bindText",
contextItemLabel: "labels.bindText",
label: "labels.bindText",
trackEvent: { category: "element" },
predicate: (elements, appState, _, app) => {
const selectedElements = app.scene.getSelectedElements(appState);
Expand Down Expand Up @@ -203,7 +203,7 @@ const pushContainerBelowText = (

export const actionWrapTextInContainer = register({
name: "wrapTextInContainer",
contextItemLabel: "labels.createContainerFromText",
label: "labels.createContainerFromText",
trackEvent: { category: "element" },
predicate: (elements, appState, _, app) => {
const selectedElements = app.scene.getSelectedElements(appState);
Expand Down

0 comments on commit d6a02b4

Please sign in to comment.