mirror of
https://github.com/gosticks/plane.git
synced 2025-10-16 12:45:33 +00:00
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
|
|
//TODO: remove temp flag isActive later and use showAlert as the source of truth
|
|
const useReloadConfirmations = (isActive = true, message?: string, defaultShowAlert = false, onLeave?: () => void) => {
|
|
const [showAlert, setShowAlert] = useState(defaultShowAlert);
|
|
|
|
const alertMessage = message ?? "Are you sure you want to leave? Changes you made may not be saved.";
|
|
|
|
const handleBeforeUnload = useCallback(
|
|
(event: BeforeUnloadEvent) => {
|
|
if (!isActive || !showAlert) return;
|
|
event.preventDefault();
|
|
event.returnValue = "";
|
|
},
|
|
[isActive, 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 isLeaving = confirm(alertMessage);
|
|
if (isLeaving) {
|
|
onLeave && onLeave();
|
|
} else {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
},
|
|
[isActive, showAlert]
|
|
);
|
|
|
|
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 () => {
|
|
// cleanup
|
|
window.removeEventListener("beforeunload", handleBeforeUnload, true);
|
|
window.removeEventListener("click", handleAnchorClick, true);
|
|
};
|
|
}, [handleAnchorClick, handleBeforeUnload]);
|
|
|
|
return { setShowAlert };
|
|
};
|
|
|
|
export default useReloadConfirmations;
|