From f494e28ce9b28be2cbb4c6d702658f53842fc830 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Tue, 5 Dec 2023 22:48:33 -0500 Subject: [PATCH] chore: Refactor editor click handler for reusability --- app/components/Editor.tsx | 48 +----------------------- app/hooks/useEditorClickHandlers.ts | 57 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 46 deletions(-) create mode 100644 app/hooks/useEditorClickHandlers.ts diff --git a/app/components/Editor.tsx b/app/components/Editor.tsx index 193faf042..85f322aa6 100644 --- a/app/components/Editor.tsx +++ b/app/components/Editor.tsx @@ -6,7 +6,6 @@ import { DOMParser as ProsemirrorDOMParser } from "prosemirror-model"; import { TextSelection } from "prosemirror-state"; import * as React from "react"; import { mergeRefs } from "react-merge-refs"; -import { useHistory } from "react-router-dom"; import { Optional } from "utility-types"; import insertFiles from "@shared/editor/commands/insertFiles"; import { AttachmentPreset } from "@shared/types"; @@ -22,15 +21,13 @@ import ErrorBoundary from "~/components/ErrorBoundary"; import type { Props as EditorProps, Editor as SharedEditor } from "~/editor"; import useCurrentUser from "~/hooks/useCurrentUser"; import useDictionary from "~/hooks/useDictionary"; +import useEditorClickHandlers from "~/hooks/useEditorClickHandlers"; import useEmbeds from "~/hooks/useEmbeds"; import useStores from "~/hooks/useStores"; import useUserLocale from "~/hooks/useUserLocale"; import { NotFoundError } from "~/utils/errors"; import { uploadFile } from "~/utils/files"; -import { isModKey } from "~/utils/keyboard"; import lazyWithRetry from "~/utils/lazyWithRetry"; -import { sharedDocumentPath } from "~/utils/routeHelpers"; -import { isHash } from "~/utils/urls"; import DocumentBreadcrumb from "./DocumentBreadcrumb"; const LazyLoadedEditor = lazyWithRetry(() => import("~/editor")); @@ -66,7 +63,6 @@ function Editor(props: Props, ref: React.RefObject | null) { const { comments, documents } = useStores(); const dictionary = useDictionary(); const embeds = useEmbeds(!shareId); - const history = useHistory(); const localRef = React.useRef(); const preferences = useCurrentUser({ rejectOnEmpty: false })?.preferences; const previousHeadings = React.useRef(null); @@ -135,47 +131,7 @@ function Editor(props: Props, ref: React.RefObject | null) { [id] ); - const handleClickLink = React.useCallback( - (href: string, event: MouseEvent) => { - // on page hash - if (isHash(href)) { - window.location.href = href; - return; - } - - if (isInternalUrl(href) && !isModKey(event) && !event.shiftKey) { - // relative - let navigateTo = href; - - // probably absolute - if (href[0] !== "/") { - try { - const url = new URL(href); - navigateTo = url.pathname + url.hash; - } catch (err) { - navigateTo = href; - } - } - - // Link to our own API should be opened in a new tab, not in the app - if (navigateTo.startsWith("/api/")) { - window.open(href, "_blank"); - return; - } - - // If we're navigating to an internal document link then prepend the - // share route to the URL so that the document is loaded in context - if (shareId && navigateTo.includes("/doc/")) { - navigateTo = sharedDocumentPath(shareId, navigateTo); - } - - history.push(navigateTo); - } else if (href) { - window.open(href, "_blank"); - } - }, - [history, shareId] - ); + const { handleClickLink } = useEditorClickHandlers({ shareId }); const focusAtEnd = React.useCallback(() => { localRef?.current?.focusAtEnd(); diff --git a/app/hooks/useEditorClickHandlers.ts b/app/hooks/useEditorClickHandlers.ts new file mode 100644 index 000000000..822a2e9e8 --- /dev/null +++ b/app/hooks/useEditorClickHandlers.ts @@ -0,0 +1,57 @@ +import * as React from "react"; +import { useHistory } from "react-router-dom"; +import { isInternalUrl } from "@shared/utils/urls"; +import { isModKey } from "~/utils/keyboard"; +import { sharedDocumentPath } from "~/utils/routeHelpers"; +import { isHash } from "~/utils/urls"; + +export default function useEditorClickHandlers({ + shareId, +}: { + shareId?: string; +}) { + const history = useHistory(); + const handleClickLink = React.useCallback( + (href: string, event: MouseEvent) => { + // on page hash + if (isHash(href)) { + window.location.href = href; + return; + } + + if (isInternalUrl(href) && !isModKey(event) && !event.shiftKey) { + // relative + let navigateTo = href; + + // probably absolute + if (href[0] !== "/") { + try { + const url = new URL(href); + navigateTo = url.pathname + url.hash; + } catch (err) { + navigateTo = href; + } + } + + // Link to our own API should be opened in a new tab, not in the app + if (navigateTo.startsWith("/api/")) { + window.open(href, "_blank"); + return; + } + + // If we're navigating to an internal document link then prepend the + // share route to the URL so that the document is loaded in context + if (shareId && navigateTo.includes("/doc/")) { + navigateTo = sharedDocumentPath(shareId, navigateTo); + } + + history.push(navigateTo); + } else if (href) { + window.open(href, "_blank"); + } + }, + [history, shareId] + ); + + return { handleClickLink }; +}