diff --git a/app/actions/definitions/developer.tsx b/app/actions/definitions/developer.tsx index 290202ee9..f0c5e950e 100644 --- a/app/actions/definitions/developer.tsx +++ b/app/actions/definitions/developer.tsx @@ -86,19 +86,14 @@ export const clearIndexedDB = createAction({ }); export const createTestUsers = createAction({ - name: "Create test users", + name: "Create 10 test users", icon: , section: DeveloperSection, visible: () => env.ENVIRONMENT === "development", perform: async () => { const count = 10; - - try { - await client.post("/developer.create_test_users", { count }); - toast.message(`${count} test users created`); - } catch (err) { - toast.error(err.message); - } + await client.post("/developer.create_test_users", { count }); + toast.message(`${count} test users created`); }, }); diff --git a/app/actions/definitions/documents.tsx b/app/actions/definitions/documents.tsx index 61407ef2c..c52e625d1 100644 --- a/app/actions/definitions/documents.tsx +++ b/app/actions/definitions/documents.tsx @@ -251,17 +251,13 @@ export const unpublishDocument = createAction({ return; } - try { - await document.unpublish(); + await document.unpublish(); - toast.success( - t("Unpublished {{ documentName }}", { - documentName: document.noun, - }) - ); - } catch (err) { - toast.error(err.message); - } + toast.success( + t("Unpublished {{ documentName }}", { + documentName: document.noun, + }) + ); }, }); @@ -288,9 +284,7 @@ export const subscribeDocument = createAction({ } const document = stores.documents.get(activeDocumentId); - await document?.subscribe(); - toast.success(t("Subscribed to document notifications")); }, }); @@ -540,17 +534,13 @@ export const pinDocumentToCollection = createAction({ return; } - try { - const document = stores.documents.get(activeDocumentId); - await document?.pin(document.collectionId); + const document = stores.documents.get(activeDocumentId); + await document?.pin(document.collectionId); - const collection = stores.collections.get(activeCollectionId); + const collection = stores.collections.get(activeCollectionId); - if (!collection || !location.pathname.startsWith(collection?.url)) { - toast.success(t("Pinned to collection")); - } - } catch (err) { - toast.error(err.message); + if (!collection || !location.pathname.startsWith(collection?.url)) { + toast.success(t("Pinned to collection")); } }, }); @@ -583,14 +573,10 @@ export const pinDocumentToHome = createAction({ } const document = stores.documents.get(activeDocumentId); - try { - await document?.pin(); + await document?.pin(); - if (location.pathname !== homePath()) { - toast.success(t("Pinned to home")); - } - } catch (err) { - toast.error(err.message); + if (location.pathname !== homePath()) { + toast.success(t("Pinned to home")); } }, }); @@ -641,21 +627,16 @@ export const importDocument = createAction({ input.onchange = async (ev) => { const files = getEventFiles(ev); - try { - const file = files[0]; - const document = await documents.import( - file, - activeDocumentId, - activeCollectionId, - { - publish: true, - } - ); - history.push(document.url); - } catch (err) { - toast.error(err.message); - throw err; - } + const file = files[0]; + const document = await documents.import( + file, + activeDocumentId, + activeCollectionId, + { + publish: true, + } + ); + history.push(document.url); }; input.click(); diff --git a/app/actions/index.ts b/app/actions/index.ts index 4083bcc10..d5e2af267 100644 --- a/app/actions/index.ts +++ b/app/actions/index.ts @@ -74,13 +74,7 @@ export function actionToMenuItem( icon, visible, dangerous: action.dangerous, - onClick: () => { - try { - action.perform?.(context); - } catch (err) { - toast.error(err.message); - } - }, + onClick: () => performAction(action, context), selected: action.selected?.(context), }; } @@ -114,10 +108,18 @@ export function actionToKBar( keywords: action.keywords ?? "", shortcut: action.shortcut || [], icon: resolvedIcon, - perform: action.perform ? () => action.perform?.(context) : undefined, + perform: action.perform + ? () => performAction(action, context) + : undefined, }, ].concat( // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. children.map((child) => ({ ...child, parent: child.parent ?? action.id })) ); } + +export async function performAction(action: Action, context: ActionContext) { + return action.perform?.(context).catch((err: Error) => { + toast.error(err.message); + }); +} diff --git a/app/components/ActionButton.tsx b/app/components/ActionButton.tsx index d2b686182..eb67d988d 100644 --- a/app/components/ActionButton.tsx +++ b/app/components/ActionButton.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/prop-types */ import * as React from "react"; import Tooltip, { Props as TooltipProps } from "~/components/Tooltip"; +import { performAction } from "~/actions"; import { Action, ActionContext } from "~/types"; export type Props = React.HTMLAttributes & { @@ -60,10 +61,10 @@ const ActionButton = React.forwardRef( ? (ev) => { ev.preventDefault(); ev.stopPropagation(); - const response = action.perform?.(actionContext); + const response = performAction(action, actionContext); if (response?.finally) { setExecuting(true); - response.finally(() => setExecuting(false)); + void response.finally(() => setExecuting(false)); } } : rest.onClick diff --git a/app/types.ts b/app/types.ts index b9f59c6de..74b7d9514 100644 --- a/app/types.ts +++ b/app/types.ts @@ -107,6 +107,10 @@ export type Action = { placeholder?: ((context: ActionContext) => string) | string; selected?: (context: ActionContext) => boolean; visible?: (context: ActionContext) => boolean; + /** + * Perform the action – note this should generally not be called directly, use `performAction` + * instead. Errors will be caught and displayed to the user as a toast message. + */ perform?: (context: ActionContext) => Promise | any; children?: ((context: ActionContext) => Action[]) | Action[]; };