diff --git a/packages/editor/core/src/ui/mentions/mention-node-view.tsx b/packages/editor/core/src/ui/mentions/mention-node-view.tsx index 939528785..2100bd24a 100644 --- a/packages/editor/core/src/ui/mentions/mention-node-view.tsx +++ b/packages/editor/core/src/ui/mentions/mention-node-view.tsx @@ -2,14 +2,12 @@ // @ts-nocheck import { NodeViewWrapper } from "@tiptap/react"; import { cn } from "src/lib/utils"; -import { useRouter } from "next/navigation"; import { IMentionHighlight } from "src/types/mention-suggestion"; import { useEffect, useState } from "react"; // eslint-disable-next-line import/no-anonymous-default-export export const MentionNodeView = (props) => { // TODO: move it to web app - const router = useRouter(); const [highlightsState, setHighlightsState] = useState(); useEffect(() => { @@ -21,25 +19,20 @@ export const MentionNodeView = (props) => { hightlights(); }, [props.extension.options]); - const handleClick = () => { - if (!props.extension.options.readonly) { - router.push(props.node.attrs.redirect_uri); - } - }; - return ( - @{props.node.attrs.label} - + ); }; diff --git a/web/core/hooks/use-reload-confirmation.tsx b/web/core/hooks/use-reload-confirmation.tsx index 1591574d0..998c5845d 100644 --- a/web/core/hooks/use-reload-confirmation.tsx +++ b/web/core/hooks/use-reload-confirmation.tsx @@ -1,41 +1,55 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { useState } from "react"; +import { useCallback, useEffect, useState } from "react"; //TODO: remove temp flag isActive later and use showAlert as the source of truth const useReloadConfirmations = (isActive = true) => { const [showAlert, setShowAlert] = useState(false); - // const router = useAppRouter(); - // const handleBeforeUnload = useCallback( - // (event: BeforeUnloadEvent) => { - // if (!isActive || !showAlert) return; - // event.preventDefault(); - // event.returnValue = ""; - // }, - // [isActive, showAlert] - // ); + const handleBeforeUnload = useCallback( + (event: BeforeUnloadEvent) => { + if (!isActive || !showAlert) return; + event.preventDefault(); + event.returnValue = ""; + }, + [isActive, showAlert] + ); - // const handleRouteChangeStart = useCallback( - // (url: string, { shallow }: { shallow: boolean }) => { - // if (!isActive || !showAlert) return; - // const leave = confirm("Are you sure you want to leave? Changes you made may not be saved."); - // if (!leave) { - // router.events.emit("routeChangeError", new Error("Route change cancelled by user"), url, shallow); - // throw "routeChange aborted."; - // } - // }, - // [isActive, router.events, showAlert] - // ); + const handleAnchorClick = useCallback( + (event: MouseEvent) => { + if (!isActive || !showAlert) return; + // Skip if event target is not available or defaultPrevented + if (!event.target || event.defaultPrevented) return; + // Skip control/command/option/alt+click + if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; + // check if the event target is an anchor or a child of an anchor tag + const eventTarget = event.target as HTMLElement; + if (!eventTarget.closest("a")) return; // This is intentionally not type safe + // check if anchor target is _blank + const anchorElement = eventTarget.closest("a") as HTMLAnchorElement; + const isAnchorTargetBlank = anchorElement.getAttribute("target") === "_blank"; + if (isAnchorTargetBlank) return; + // show confirm dialog + const leave = confirm("Are you sure you want to leave? Changes you made may not be saved."); + if (!leave) { + event.preventDefault(); + event.stopPropagation(); + } + }, + [isActive, showAlert] + ); - // useEffect(() => { - // window.addEventListener("beforeunload", handleBeforeUnload); - // router.events.on("routeChangeStart", handleRouteChangeStart); + useEffect(() => { + // handle browser refresh + window.addEventListener("beforeunload", handleBeforeUnload, true); + // handle anchor tag click + window.addEventListener("click", handleAnchorClick, true); + // TODO: handle back / forward button click - // return () => { - // window.removeEventListener("beforeunload", handleBeforeUnload); - // router.events.off("routeChangeStart", handleRouteChangeStart); - // }; - // }, [handleBeforeUnload, handleRouteChangeStart, router.events]); + return () => { + // cleanup + window.removeEventListener("beforeunload", handleBeforeUnload, true); + window.removeEventListener("click", handleAnchorClick, true); + }; + }, [handleAnchorClick, handleBeforeUnload]); return { setShowAlert }; };