From 48d3ebb177ce74c1bf1217bf22d5af75cf015d82 Mon Sep 17 00:00:00 2001 From: MrWangJustToDo <2711470541@qq.com> Date: Wed, 24 Jan 2024 00:47:43 +0800 Subject: [PATCH] vue component almost done --- .../react/src/components/DiffViewContext.ts | 4 +- packages/vue/src/components/DiffAddWidget.tsx | 4 +- packages/vue/src/components/DiffSplitLine.tsx | 25 +- .../src/components/DiffUnifiedExtendLine.tsx | 71 +++++ .../src/components/DiffUnifiedHunkLine.tsx | 136 +++++++++ .../vue/src/components/DiffUnifiedLine.tsx | 269 ++++++++++++++++++ .../vue/src/components/DiffUnifiedView.tsx | 50 ++++ .../src/components/DiffUnifiedWidgetLine.tsx | 71 +++++ packages/vue/src/components/DiffView.tsx | 11 +- .../vue/src/hooks/useSubscribeDiffFile.ts | 2 + ui/vue-example/src/App.vue | 70 ++++- 11 files changed, 689 insertions(+), 24 deletions(-) create mode 100644 packages/vue/src/components/DiffUnifiedExtendLine.tsx create mode 100644 packages/vue/src/components/DiffUnifiedHunkLine.tsx create mode 100644 packages/vue/src/components/DiffUnifiedLine.tsx create mode 100644 packages/vue/src/components/DiffUnifiedView.tsx create mode 100644 packages/vue/src/components/DiffUnifiedWidgetLine.tsx diff --git a/packages/react/src/components/DiffViewContext.ts b/packages/react/src/components/DiffViewContext.ts index 5855267..43ba70a 100644 --- a/packages/react/src/components/DiffViewContext.ts +++ b/packages/react/src/components/DiffViewContext.ts @@ -4,8 +4,8 @@ import type { DiffViewProps, SplitSide } from ".."; import type { DiffFileExtends } from "../utils"; export enum DiffModeEnum { - Split, - Unified, + Split = 1, + Unified = 2, } export type DiffViewContextProps = { diff --git a/packages/vue/src/components/DiffAddWidget.tsx b/packages/vue/src/components/DiffAddWidget.tsx index 3caa7c7..b26bb3b 100644 --- a/packages/vue/src/components/DiffAddWidget.tsx +++ b/packages/vue/src/components/DiffAddWidget.tsx @@ -52,7 +52,7 @@ export const DiffUnifiedAddWidget = ({ diffFile: DiffFileExtends; lineNumber: number; side: SplitSide; - onWidgetClick?: (lineNumber: number, side: SplitSide) => void; + onWidgetClick?: (event: "onAddWidgetClick", lineNumber: number, side: SplitSide) => void; }) => { return (
{ diffFile.onOpenAddWidget(lineNumber, side); - onWidgetClick?.(lineNumber, side); + onWidgetClick?.("onAddWidgetClick", lineNumber, side); }} > + diff --git a/packages/vue/src/components/DiffSplitLine.tsx b/packages/vue/src/components/DiffSplitLine.tsx index b4c8d4a..953db5e 100644 --- a/packages/vue/src/components/DiffSplitLine.tsx +++ b/packages/vue/src/components/DiffSplitLine.tsx @@ -2,7 +2,6 @@ import { DiffLineType, type DiffFile } from "@git-diff-view/core"; import { computed, defineComponent, ref } from "vue"; import { useEnableAddWidget, useEnableHighlight, useEnableWrap, useOnAddWidgetClick } from "../context"; -import { useForceUpdate } from "../hooks/useForceUpdate"; import { useSubscribeDiffFile } from "../hooks/useSubscribeDiffFile"; import { useSyncHeight } from "../hooks/useSyncHeight"; @@ -25,11 +24,17 @@ export const DiffSplitLine = defineComponent( const currentItem = ref(props.side === SplitSide.old ? props.diffFile.getSplitLeftLine(props.index) : props.diffFile.getSplitRightLine(props.index)); - const currentItemHasDiff = ref(!!currentItem.value.diff); + const currentItemHasDiff = ref(!!currentItem.value?.diff); const currentItemHasChange = ref(currentItem.value?.diff?.isIncludeableLine()); - const currentSyntaxItem = ref(props.side === SplitSide.old ? props.diffFile.getOldSyntaxLine(currentItem.value.lineNumber) : props.diffFile.getNewSyntaxLine(currentItem.value.lineNumber)); + const currentItemHasHidden = ref(currentItem.value?.isHidden); + + const currentSyntaxItem = ref( + props.side === SplitSide.old + ? props.diffFile.getOldSyntaxLine(currentItem.value?.lineNumber) + : props.diffFile.getNewSyntaxLine(currentItem.value?.lineNumber) + ); useSubscribeDiffFile( props, @@ -38,14 +43,16 @@ export const DiffSplitLine = defineComponent( useSubscribeDiffFile( props, - (diffFile) => (currentSyntaxItem.value = props.side === SplitSide.old ? diffFile.getOldSyntaxLine(currentItem.value.lineNumber) : diffFile.getNewSyntaxLine(currentItem.value.lineNumber)) + (diffFile) => + (currentSyntaxItem.value = + props.side === SplitSide.old ? diffFile.getOldSyntaxLine(currentItem.value?.lineNumber) : diffFile.getNewSyntaxLine(currentItem.value?.lineNumber)) ); - useSubscribeDiffFile(props, () => (currentItemHasDiff.value = !!currentItem.value.diff)); + useSubscribeDiffFile(props, () => (currentItemHasDiff.value = !!currentItem.value?.diff)); - useSubscribeDiffFile(props, () => (currentItemHasChange.value = currentItem.value.diff?.isIncludeableLine())); + useSubscribeDiffFile(props, () => (currentItemHasHidden.value = currentItem.value?.isHidden)); - const count = useForceUpdate(props); + useSubscribeDiffFile(props, () => (currentItemHasChange.value = currentItem.value?.diff?.isIncludeableLine())); const lineSelector = computed(() => `tr[data-line="${props.lineNumber}"]`); @@ -58,9 +65,7 @@ export const DiffSplitLine = defineComponent( }); return () => { - count.value; - - if (currentItem.value?.isHidden) return null; + if (currentItemHasHidden.value) return null; const isAdded = currentItem.value?.diff?.type === DiffLineType.Add; diff --git a/packages/vue/src/components/DiffUnifiedExtendLine.tsx b/packages/vue/src/components/DiffUnifiedExtendLine.tsx new file mode 100644 index 0000000..6ef1635 --- /dev/null +++ b/packages/vue/src/components/DiffUnifiedExtendLine.tsx @@ -0,0 +1,71 @@ +import { computed, defineComponent, ref } from "vue"; + +import { SplitSide } from ".."; +import { useExtendData, useSlots } from "../context"; +import { useDomWidth } from "../hooks/useDomWidth"; +import { useSubscribeDiffFile } from "../hooks/useSubscribeDiffFile"; + +import type { DiffFileExtends } from "../utils"; + +export const DiffUnifiedExtendLine = defineComponent( + (props: { index: number; diffFile: DiffFileExtends; lineNumber: number }) => { + const extendData = useExtendData(); + + const slots = useSlots(); + + const unifiedItem = ref(props.diffFile.getUnifiedLine(props.index)); + + const oldExtend = ref(extendData.value?.oldFile?.[unifiedItem.value.oldLineNumber]); + + const newExtend = ref(extendData.value?.newFile?.[unifiedItem.value.newLineNumber]); + + useSubscribeDiffFile(props, (diffFile) => { + unifiedItem.value = diffFile.getUnifiedLine(props.index); + }); + + useSubscribeDiffFile(props, () => (oldExtend.value = extendData.value?.oldFile?.[unifiedItem.value.oldLineNumber])); + + useSubscribeDiffFile(props, () => (newExtend.value = extendData.value?.newFile?.[unifiedItem.value.newLineNumber])); + + const currentIsShow = computed(() => + Boolean((oldExtend.value || newExtend.value) && unifiedItem.value && !unifiedItem.value.isHidden && unifiedItem.value.diff) + ); + + const width = useDomWidth({ + selector: ref(".unified-diff-table-wrapper"), + enable: currentIsShow, + }); + + return () => { + if (!currentIsShow.value) return null; + + return ( + + +
+ {width.value > 0 && + oldExtend.value && + slots.extend({ + diffFile: props.diffFile, + side: SplitSide.old, + lineNumber: unifiedItem.value.oldLineNumber, + data: oldExtend.value.data, + onUpdate: props.diffFile.notifyAll, + })} + {width.value > 0 && + newExtend.value && + slots.extend({ + diffFile: props.diffFile, + side: SplitSide.new, + lineNumber: unifiedItem.value.newLineNumber, + data: newExtend.value.data, + onUpdate: props.diffFile.notifyAll, + })} +
+ + + ); + }; + }, + { name: "DiffUnifiedExtendLine", props: ["diffFile", "index", "lineNumber"] } +); diff --git a/packages/vue/src/components/DiffUnifiedHunkLine.tsx b/packages/vue/src/components/DiffUnifiedHunkLine.tsx new file mode 100644 index 0000000..f850ea2 --- /dev/null +++ b/packages/vue/src/components/DiffUnifiedHunkLine.tsx @@ -0,0 +1,136 @@ +import { composeLen } from "@git-diff-view/core"; +import { defineComponent, ref } from "vue"; + +import { useEnableWrap } from "../context"; +import { useSubscribeDiffFile } from "../hooks/useSubscribeDiffFile"; + +import { hunkContentBGName, hunkLineNumberBGName, plainLineNumberColorName } from "./color"; +import { ExpandAll, ExpandDown, ExpandUp } from "./DiffExpand"; + +import type { DiffFile } from "@git-diff-view/core"; + +export const DiffUnifiedHunkLine = defineComponent( + (props: { index: number; diffFile: DiffFile; lineNumber: number }) => { + const currentHunk = ref(props.diffFile.getUnifiedHunkLine(props.index)); + + const enableWrap = useEnableWrap(); + + const currentIsShow = ref(currentHunk.value && currentHunk.value.unifiedInfo.startHiddenIndex < currentHunk.value.unifiedInfo.endHiddenIndex); + + const currentIsEnableAll = ref( + currentHunk.value && currentHunk.value.unifiedInfo.endHiddenIndex - currentHunk.value.unifiedInfo.startHiddenIndex < composeLen + ); + + useSubscribeDiffFile(props, (diffFile) => (currentHunk.value = diffFile.getUnifiedHunkLine(props.index))); + + useSubscribeDiffFile( + props, + () => (currentIsShow.value = currentHunk.value && currentHunk.value.unifiedInfo.startHiddenIndex < currentHunk.value.unifiedInfo.endHiddenIndex) + ); + + useSubscribeDiffFile( + props, + () => + (currentIsEnableAll.value = + currentHunk.value && currentHunk.value.unifiedInfo.endHiddenIndex - currentHunk.value.unifiedInfo.startHiddenIndex < composeLen) + ); + + return () => { + if (!currentIsShow.value) return null; + + return ( + + + {currentIsEnableAll.value ? ( + + ) : ( + <> + + + + )} + + +
+ {currentHunk.value.unifiedInfo.plainText} +
+ + + ); + }; + }, + { name: "DiffUnifiedHunkLine", props: ["index", "diffFile", "lineNumber"] } +); + +export const DiffUnifiedExpandLastLine = defineComponent( + (props: { diffFile: DiffFile }) => { + const currentIsShow = ref(props.diffFile.getNeedShowExpandAll("unified")); + + const enableWrap = useEnableWrap(); + + useSubscribeDiffFile(props, (diffFile) => (currentIsShow.value = diffFile.getNeedShowExpandAll("unified"))); + + return () => { + if (!currentIsShow.value) return null; + + return ( + + + + + + + ); + }; + }, + { name: "DiffUnifiedExpandLastLine", props: ["diffFile"] } +); diff --git a/packages/vue/src/components/DiffUnifiedLine.tsx b/packages/vue/src/components/DiffUnifiedLine.tsx new file mode 100644 index 0000000..f8456a3 --- /dev/null +++ b/packages/vue/src/components/DiffUnifiedLine.tsx @@ -0,0 +1,269 @@ +import { defineComponent, ref } from "vue"; + +import { SplitSide } from ".."; +import { useEnableAddWidget, useEnableHighlight, useEnableWrap, useOnAddWidgetClick } from "../context"; +import { useSubscribeDiffFile } from "../hooks/useSubscribeDiffFile"; + +import { + addContentBGName, + addLineNumberBGName, + delContentBGName, + delLineNumberBGName, + expandContentBGName, + plainContentBGName, + plainLineNumberBGName, + plainLineNumberColorName, +} from "./color"; +import { DiffUnifiedAddWidget } from "./DiffAddWidget"; +import { DiffContent } from "./DiffContent"; + +import type { DiffFileExtends } from "../utils"; +import type { DiffFile, SyntaxLine, DiffLine } from "@git-diff-view/core"; + +const DiffUnifiedOldLine = ({ + index, + diffLine, + rawLine, + syntaxLine, + lineNumber, + diffFile, + enableWrap, + enableHighlight, + onAddWidgetClick, +}: { + index: number; + lineNumber: number; + rawLine: string; + syntaxLine?: SyntaxLine; + diffLine?: DiffLine; + diffFile: DiffFile; + enableWrap: boolean; + enableHighlight: boolean; + onAddWidgetClick?: (event: "onAddWidgetClick", lineNumber: number, side: SplitSide) => void; +}) => { + return ( + + + +
+ + {lineNumber} + + + +
+ + + + + + ); +}; + +const DiffUnifiedNewLine = ({ + index, + diffLine, + rawLine, + syntaxLine, + lineNumber, + diffFile, + enableWrap, + enableHighlight, + onAddWidgetClick, +}: { + index: number; + lineNumber: number; + rawLine: string; + syntaxLine?: SyntaxLine; + diffLine?: DiffLine; + diffFile: DiffFile; + enableWrap: boolean; + enableHighlight: boolean; + onAddWidgetClick?: (event: "onAddWidgetClick", lineNumber: number, side: SplitSide) => void; +}) => { + return ( + + + +
+ + + + {lineNumber} + +
+ + + + + + ); +}; + +export const DiffUnifiedLine = defineComponent( + (props: { index: number; diffFile: DiffFile; lineNumber: number }) => { + const unifiedItem = ref(props.diffFile.getUnifiedLine(props.index)); + + const enableWrap = useEnableWrap(); + + const onAddWidgetClick = useOnAddWidgetClick(); + + const enableHighlight = useEnableHighlight(); + + const enableAddWidget = useEnableAddWidget(); + + const currentItemHasHidden = ref(unifiedItem.value?.isHidden); + + const currentItemHasChange = ref(unifiedItem.value?.diff?.isIncludeableLine()); + + const currentSyntaxItem = ref( + unifiedItem.value?.newLineNumber + ? props.diffFile.getNewSyntaxLine(unifiedItem.value.newLineNumber) + : unifiedItem.value?.oldLineNumber + ? props.diffFile.getOldSyntaxLine(unifiedItem.value.oldLineNumber) + : undefined + ); + + useSubscribeDiffFile(props, (diffFile) => (unifiedItem.value = diffFile.getUnifiedLine(props.index))); + + useSubscribeDiffFile(props, () => (currentItemHasHidden.value = unifiedItem.value?.isHidden)); + + useSubscribeDiffFile(props, () => (currentItemHasChange.value = unifiedItem.value?.diff?.isIncludeableLine())); + + useSubscribeDiffFile( + props, + (diffFile) => + (currentSyntaxItem.value = unifiedItem.value?.newLineNumber + ? diffFile.getNewSyntaxLine(unifiedItem.value.newLineNumber) + : unifiedItem.value?.oldLineNumber + ? diffFile.getOldSyntaxLine(unifiedItem.value.oldLineNumber) + : undefined) + ); + + return () => { + if (currentItemHasHidden.value) return null; + + if (currentItemHasChange.value) { + if (unifiedItem.value.oldLineNumber) { + return ( + + ); + } else { + return ( + + ); + } + } else { + return ( + + + {enableAddWidget.value && unifiedItem.value.diff && ( + + )} +
+ + {unifiedItem.value.oldLineNumber} + + + + {unifiedItem.value.newLineNumber} + +
+ + + + + + ); + } + }; + }, + { name: "DiffUnifiedLine", props: ["diffFile", "index", "lineNumber"] } +); diff --git a/packages/vue/src/components/DiffUnifiedView.tsx b/packages/vue/src/components/DiffUnifiedView.tsx new file mode 100644 index 0000000..aff4f67 --- /dev/null +++ b/packages/vue/src/components/DiffUnifiedView.tsx @@ -0,0 +1,50 @@ +import { numIterator } from "@git-diff-view/core"; +import { Fragment } from "vue"; + +import { DiffUnifiedExtendLine } from "./DiffUnifiedExtendLine"; +import { DiffUnifiedExpandLastLine, DiffUnifiedHunkLine } from "./DiffUnifiedHunkLine"; +import { DiffUnifiedLine } from "./DiffUnifiedLine"; +import { DiffUnifiedWidgetLine } from "./DiffUnifiedWidgetLine"; + +import type { DiffFileExtends } from "../utils"; +import type { DiffFile } from "@git-diff-view/core"; + +export const DiffUnifiedView = ({ diffFile }: { diffFile: DiffFile }) => { + const unifiedLineLength = diffFile.unifiedLineLength; + + return ( +
+
+ + + + + + + + + + + + + {numIterator(unifiedLineLength, (index) => ( + + + + + + + ))} + + +
+
+
+ ); +}; diff --git a/packages/vue/src/components/DiffUnifiedWidgetLine.tsx b/packages/vue/src/components/DiffUnifiedWidgetLine.tsx new file mode 100644 index 0000000..7365818 --- /dev/null +++ b/packages/vue/src/components/DiffUnifiedWidgetLine.tsx @@ -0,0 +1,71 @@ +import { computed, defineComponent, ref } from "vue"; + +import { SplitSide } from ".."; +import { useSlots } from "../context"; +import { useDomWidth } from "../hooks/useDomWidth"; +import { useSubscribeDiffFile } from "../hooks/useSubscribeDiffFile"; + +import type { DiffFileExtends } from "../utils"; + +export const DiffUnifiedWidgetLine = defineComponent( + (props: { index: number; diffFile: DiffFileExtends; lineNumber: number }) => { + const slots = useSlots(); + + const unifiedItem = ref(props.diffFile.getUnifiedLine(props.index)); + + const oldWidget = ref(unifiedItem.value?.oldLineNumber ? props.diffFile.checkWidgetLine(unifiedItem.value.oldLineNumber, SplitSide.old) : undefined); + + const newWidget = ref(unifiedItem.value?.newLineNumber ? props.diffFile.checkWidgetLine(unifiedItem.value.newLineNumber, SplitSide.new) : undefined); + + useSubscribeDiffFile(props, (diffFile) => (unifiedItem.value = diffFile.getUnifiedLine(props.index))); + + useSubscribeDiffFile( + props, + (diffFile: DiffFileExtends) => + (oldWidget.value = unifiedItem.value?.oldLineNumber ? diffFile.checkWidgetLine(unifiedItem.value.oldLineNumber, SplitSide.old) : undefined) + ); + + useSubscribeDiffFile( + props, + (diffFile: DiffFileExtends) => + (newWidget.value = unifiedItem.value?.newLineNumber ? diffFile.checkWidgetLine(unifiedItem.value.newLineNumber, SplitSide.new) : undefined) + ); + + const currentIsShow = computed(() => oldWidget.value || newWidget.value); + + const width = useDomWidth({ + selector: ref(".unified-diff-table-wrapper"), + enable: currentIsShow, + }); + + return () => { + if (!currentIsShow.value) return null; + + return ( + + +
+ {width.value > 0 && + oldWidget.value && + slots.widget?.({ + diffFile: props.diffFile, + side: SplitSide.old, + lineNumber: unifiedItem.value.oldLineNumber, + onClose: props.diffFile.onCloseAddWidget, + })} + {width.value > 0 && + newWidget.value && + slots.widget?.({ + diffFile: props.diffFile, + side: SplitSide.new, + lineNumber: unifiedItem.value.newLineNumber, + onClose: props.diffFile.onCloseAddWidget, + })} +
+ + + ); + }; + }, + { name: "DiffUnifiedWidgetLine", props: ["diffFile", "index", "lineNumber"] } +); diff --git a/packages/vue/src/components/DiffView.tsx b/packages/vue/src/components/DiffView.tsx index 2989e32..74f28bb 100644 --- a/packages/vue/src/components/DiffView.tsx +++ b/packages/vue/src/components/DiffView.tsx @@ -16,13 +16,14 @@ import { useProvide } from "../hooks/useProvide"; import { DiffFileExtends } from "../utils"; import { DiffSplitView } from "./DiffSplitView"; +import { DiffUnifiedView } from "./DiffUnifiedView"; import type { DiffFile, highlighter } from "@git-diff-view/core"; import type { CSSProperties, SlotsType } from "vue"; export enum DiffModeEnum { - Split, - Unified, + Split = 1, + Unified = 2, } export enum SplitSide { @@ -136,7 +137,11 @@ export const DiffView = defineComponent, { onAddWidgetClick: return () => (
- + {!props.diffViewMode || props.diffViewMode === DiffModeEnum.Split ? ( + + ) : ( + + )}
); diff --git a/packages/vue/src/hooks/useSubscribeDiffFile.ts b/packages/vue/src/hooks/useSubscribeDiffFile.ts index 87b7a93..b6a2da5 100644 --- a/packages/vue/src/hooks/useSubscribeDiffFile.ts +++ b/packages/vue/src/hooks/useSubscribeDiffFile.ts @@ -6,6 +6,8 @@ export const useSubscribeDiffFile = (props: { diffFile: DiffFile }, onUpdate: (i const initSubscribe = (onClean: (cb: () => void) => void) => { const diffFile = props.diffFile; + onUpdate(diffFile); + const clean = diffFile.subscribe(() => onUpdate(diffFile)); onClean(clean); diff --git a/ui/vue-example/src/App.vue b/ui/vue-example/src/App.vue index 5837384..6a1c68c 100644 --- a/ui/vue-example/src/App.vue +++ b/ui/vue-example/src/App.vue @@ -1,19 +1,75 @@