All files / src/contexts/ExternalLinkWarning ExternalLinkWarning.tsx

0% Statements 0/22
0% Branches 0/4
0% Functions 0/7
0% Lines 0/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77                                                                                                                                                         
import { useDisclosure } from "@chakra-ui/react";
import {
  useContext,
  useState,
  createContext,
  FunctionComponent,
  MouseEventHandler,
  useCallback,
} from "react";
import {
  PREFERS_WARN_ON_EXTERNAL_LINK_CLICK,
  ExternalLinkPrompt,
  ExternalLinkPromptOptions,
} from "./constants";
import { ExternalLinkWarningModal } from "./ExternalLinkWarningModal";
 
const ExternalLinkWarningContext = createContext<ExternalLinkPrompt>(
  ({ onClick }) => onClick
);
 
export const useExternalLinkWarning = () =>
  useContext(ExternalLinkWarningContext);
 
export const ExternalLinkWarningProvider: FunctionComponent = ({
  children,
}) => {
  const [modalOption, setModalOptions] =
    useState<ExternalLinkPromptOptions | null>(null);
 
  const { isOpen, onOpen, onClose } = useDisclosure({
    // Reset the modal options when closed
    onClose: () => {
      setModalOptions(null);
    },
  });
 
  // Determines initial state from localStorage. If no value is found, default to showing warning
  const [shouldWarn, setShouldWarn] = useState(() => {
    try {
      const saved =
        localStorage.getItem(PREFERS_WARN_ON_EXTERNAL_LINK_CLICK) ?? "true";
      return JSON.parse(saved);
    } catch {
      return true;
    }
  });
 
  // Takes in an href & onClick to set options for modal. If it should warn the user, it will wrap the onClick
  // With additional logic to show the modal
  const withPrompt = useCallback<ExternalLinkPrompt>(
    ({ href, onClick }) => {
      if (!shouldWarn) return onClick;
 
      const handler: MouseEventHandler<HTMLAnchorElement> = (e) => {
        setModalOptions({ href, onClick });
        e.preventDefault();
        onOpen();
      };
 
      return handler;
    },
    [onOpen, shouldWarn]
  );
 
  return (
    <ExternalLinkWarningContext.Provider value={withPrompt}>
      {children}
      <ExternalLinkWarningModal
        isOpen={isOpen}
        onClose={onClose}
        setShouldWarn={setShouldWarn}
        {...modalOption}
      />
    </ExternalLinkWarningContext.Provider>
  );
};