/* eslint-disable @typescript-eslint/ban-ts-comment */ import { type DiffFile, getSplitContentLines } from "@git-diff-view/core"; import { diffAsideWidthName, diffFontSizeName, getDiffIdFromElement, removeAllSelection } from "@git-diff-view/utils"; import { Fragment, memo, useMemo, useRef } from "react"; // SEE https://github.com/facebook/react/pull/25231 // @ts-ignore import { useSyncExternalStore } from "use-sync-external-store/shim/index.js"; import { SplitSide } from ".."; import { useTextWidth } from "../hooks/useTextWidth"; import { DiffSplitContentLine } from "./DiffSplitContentLineWrap"; import { DiffSplitExtendLine } from "./DiffSplitExtendLineWrap"; import { DiffSplitHunkLine } from "./DiffSplitHunkLineWrap"; import { DiffSplitWidgetLine } from "./DiffSplitWidgetLineWrap"; import { useDiffViewContext } from "./DiffViewContext"; import type { MouseEventHandler } from "react"; export const DiffSplitViewWrap = memo(({ diffFile }: { diffFile: DiffFile }) => { const splitLineLength = Math.max(diffFile.splitLineLength, diffFile.fileLineLength); const { useDiffContext } = useDiffViewContext(); const ref = useRef(null); const tempRef = useRef(undefined); const { fontSize, enableAddWidget, enableHighlight } = useDiffContext.useShallowStableSelector((s) => ({ fontSize: s.fontSize, enableAddWidget: s.enableAddWidget, enableHighlight: s.enableHighlight, })); useSyncExternalStore(diffFile.subscribe, diffFile.getUpdateCount, diffFile.getUpdateCount); const font = useMemo(() => ({ fontSize: fontSize + "px", fontFamily: "Menlo, Consolas, monospace" }), [fontSize]); const _width = useTextWidth({ text: splitLineLength.toString(), font, }); const width = Math.max(40, _width + 25); const lines = getSplitContentLines(diffFile); const setStyle = (side?: SplitSide) => { if (!ref.current) return; if (!side) { ref.current.textContent = ""; } else { const id = `diff-root${diffFile.getId()}`; const targetSide = side === SplitSide.old ? SplitSide.new : SplitSide.old; ref.current.textContent = `#${id} [data-side="${SplitSide[targetSide]}"] {user-select: none} \n#${id} [data-state="extend"] {user-select: none} \n#${id} [data-state="hunk"] {user-select: none} \n#${id} [data-state="widget"] {user-select: none}`; } }; const onMouseDown: MouseEventHandler = (e) => { let ele: Element | null = e.target as Element; // need remove all the selection if (ele && ele instanceof HTMLElement && ele.nodeName === "BUTTON") { removeAllSelection(); return; } const id = getDiffIdFromElement(ele as HTMLElement); if (id && id !== `diff-root${diffFile.getId()}`) { return; } while (ele && ele instanceof HTMLElement) { const state = ele.getAttribute("data-state"); const side = ele.getAttribute("data-side") as unknown as SplitSide; if (side) { if (tempRef.current !== (SplitSide[side] as unknown as SplitSide)) { tempRef.current = SplitSide[side] as unknown as SplitSide; setStyle(SplitSide[side] as unknown as SplitSide); removeAllSelection(); } } if (state) { if (state === "extend" || state === "hunk" || state === "widget") { if (tempRef.current !== undefined) { tempRef.current = undefined; setStyle(undefined); removeAllSelection(); } return; } else { return; } } ele = ele.parentElement; } }; return (