Skip to content

Commit fe2852b

Browse files
update
1 parent 9b1a3e2 commit fe2852b

17 files changed

Lines changed: 158 additions & 138 deletions

packages/cli/src/components/CodeView.tsx

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { Box } from "ink";
77
import React, { Fragment, forwardRef, memo, useEffect, useImperativeHandle, useMemo, useRef } from "react";
88

99
import { useCodeTerminalSize } from "../hooks/useCodeTerminalSize";
10-
import { useIsMounted } from "../hooks/useIsMounted";
1110

1211
import { CodeContent } from "./CodeContent";
1312
import { CodeExtendLine } from "./CodeExtendLine";
@@ -28,6 +27,7 @@ export type CodeViewProps<T> = {
2827
fileName?: string | null;
2928
fileLang?: DiffHighlighterLang | string | null;
3029
};
30+
file?: File;
3131
extendData?: Record<string, { data: T }>;
3232
width?: number;
3333
codeViewTheme?: "light" | "dark";
@@ -115,12 +115,12 @@ CodeLine.displayName = "CodeLine";
115115
/**
116116
* CodeViewContent - renders all code lines using terminal size from context
117117
*/
118-
const CodeViewContent = memo(({ file, theme }: { file: File; theme: "light" | "dark" }) => {
118+
const CodeViewContent = memo(({ file, theme, width }: { file: File; theme: "light" | "dark", width?: number }) => {
119119
const { useCodeContext } = useCodeViewContext();
120120

121121
const enableHighlight = useCodeContext((s) => s.enableHighlight);
122122

123-
const { columns } = useCodeTerminalSize();
123+
const { columns: _columns } = useCodeTerminalSize();
124124

125125
// Calculate line number width based on max line number
126126
const lineNumWidth = useMemo(() => {
@@ -134,6 +134,8 @@ const CodeViewContent = memo(({ file, theme }: { file: File; theme: "light" | "d
134134
return Array.from({ length: totalLines }, (_, i) => i + 1);
135135
}, [file.rawLength]);
136136

137+
const columns = width || _columns;
138+
137139
if (!columns) return null;
138140

139141
return (
@@ -163,14 +165,13 @@ CodeViewContent.displayName = "CodeViewContent";
163165
const InternalCodeView = <T,>(
164166
props: Omit<CodeViewProps<T>, "data"> & {
165167
file: File;
166-
isMounted: boolean;
167168
wrapperRef?: RefObject<DOMElement>;
168169
}
169170
) => {
170171
const {
171172
file,
173+
width: _width,
172174
codeViewHighlight,
173-
isMounted,
174175
wrapperRef,
175176
extendData,
176177
renderExtendLine,
@@ -188,8 +189,8 @@ const InternalCodeView = <T,>(
188189
const {
189190
id,
190191
setId,
191-
mounted,
192-
setMounted,
192+
width,
193+
setWidth,
193194
enableHighlight,
194195
setEnableHighlight,
195196
setExtendData,
@@ -205,8 +206,8 @@ const InternalCodeView = <T,>(
205206
setId(fileId);
206207
}
207208

208-
if (mounted !== isMounted) {
209-
setMounted(isMounted);
209+
if (_width !== width) {
210+
setWidth(_width);
210211
}
211212

212213
if (codeViewHighlight !== enableHighlight) {
@@ -229,10 +230,10 @@ const InternalCodeView = <T,>(
229230
setTabWidth(codeViewTabWidth);
230231
}
231232
}, [
233+
_width,
232234
useCodeContext,
233235
codeViewHighlight,
234236
fileId,
235-
isMounted,
236237
extendData,
237238
renderExtendLine,
238239
codeViewTabSpace,
@@ -253,7 +254,7 @@ const InternalCodeView = <T,>(
253254
return (
254255
<CodeViewContext.Provider value={value}>
255256
<Box data-component="git-code-view" data-theme={theme} data-version={__VERSION__} flexDirection="column">
256-
<CodeViewContent file={file} theme={theme} />
257+
<CodeViewContent file={file} theme={theme} width={_width} />
257258
</Box>
258259
</CodeViewContext.Provider>
259260
);
@@ -262,42 +263,37 @@ const InternalCodeView = <T,>(
262263
const MemoedInternalCodeView = memo(InternalCodeView);
263264

264265
const CodeViewContainerWithRef = <T,>(props: CodeViewProps<T>, ref: ForwardedRef<{ getFileInstance: () => File }>) => {
265-
const { registerHighlighter, data, codeViewTheme, width, ...restProps } = props;
266+
const { registerHighlighter, data, codeViewTheme, file, ...restProps } = props;
266267

267268
const domRef = useRef<DOMElement>(null);
268269

269270
const theme = codeViewTheme || "light";
270271

271-
const file = useMemo(() => {
272+
const width = restProps.width;
273+
274+
const finalFile = useMemo(() => {
275+
if (file) return file;
272276
if (data) {
273277
return getFile(data.content || "", data.fileLang || "", theme, data.fileName || "");
274278
}
275279
return null;
276-
}, [data, theme]);
277-
278-
const fileRef = useRef(file);
279-
280-
if (fileRef.current && fileRef.current !== file) {
281-
fileRef.current = file;
282-
}
283-
284-
const isMounted = useIsMounted();
280+
}, [data, theme, file]);
285281

286282
useEffect(() => {
287-
if (!file) return;
288-
file.doRaw();
289-
}, [file]);
283+
if (!finalFile) return;
284+
finalFile.doRaw();
285+
}, [finalFile]);
290286

291287
useEffect(() => {
292-
if (!file) return;
288+
if (!finalFile) return;
293289
if (props.codeViewHighlight) {
294-
file.doSyntax({ registerHighlighter: registerHighlighter, theme: codeViewTheme });
290+
finalFile.doSyntax({ registerHighlighter: registerHighlighter, theme: codeViewTheme });
295291
}
296-
}, [file, props.codeViewHighlight, codeViewTheme, registerHighlighter]);
292+
}, [finalFile, props.codeViewHighlight, codeViewTheme, registerHighlighter]);
297293

298-
useImperativeHandle(ref, () => ({ getFileInstance: () => file }), [file]);
294+
useImperativeHandle(ref, () => ({ getFileInstance: () => finalFile }), [finalFile]);
299295

300-
if (!file) return null;
296+
if (!finalFile) return null;
301297

302298
return (
303299
<Box
@@ -307,11 +303,10 @@ const CodeViewContainerWithRef = <T,>(props: CodeViewProps<T>, ref: ForwardedRef
307303
flexShrink={typeof width === "number" ? 0 : undefined}
308304
>
309305
<MemoedInternalCodeView
310-
key={file.fileName}
306+
key={finalFile.getId()}
311307
{...restProps}
312308
wrapperRef={domRef}
313-
file={file}
314-
isMounted={isMounted}
309+
file={finalFile}
315310
codeViewTheme={codeViewTheme}
316311
codeViewTabWidth={props.codeViewTabWidth || "medium"}
317312
/>

packages/cli/src/components/DiffSplitView.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { DiffSplitExtendLine } from "./DiffSplitExtendLine";
1010
import { DiffSplitHunkLine } from "./DiffSplitHunkLine";
1111
import { useDiffViewContext } from "./DiffViewContext";
1212

13-
export const DiffSplitView = memo(({ diffFile }: { diffFile: DiffFile }) => {
13+
export const DiffSplitView = memo(({ diffFile, width }: { diffFile: DiffFile; width?: number }) => {
1414
const { useDiffContext } = useDiffViewContext();
1515

1616
const enableHighlight = useDiffContext.useShallowStableSelector((s) => s.enableHighlight);
@@ -19,14 +19,16 @@ export const DiffSplitView = memo(({ diffFile }: { diffFile: DiffFile }) => {
1919

2020
const theme = diffFile._getTheme();
2121

22-
const { columns } = useTerminalSize();
22+
const { columns: _columns } = useTerminalSize();
2323

2424
const splitLineLength = Math.max(diffFile.splitLineLength, diffFile.fileLineLength);
2525

2626
const lineNumWidth = splitLineLength.toString().length;
2727

2828
const lines = getSplitContentLines(diffFile);
2929

30+
const columns = width || _columns;
31+
3032
if (!columns) return null;
3133

3234
return (

packages/cli/src/components/DiffUnifiedView.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { useDiffViewContext } from "./DiffViewContext";
1313

1414
import type { DiffFile } from "@git-diff-view/core";
1515

16-
export const DiffUnifiedView = memo(({ diffFile }: { diffFile: DiffFile }) => {
16+
export const DiffUnifiedView = memo(({ diffFile, width }: { diffFile: DiffFile; width?: number }) => {
1717
const { useDiffContext } = useDiffViewContext();
1818

1919
const enableHighlight = useDiffContext.useShallowStableSelector((s) => s.enableHighlight);
@@ -22,14 +22,16 @@ export const DiffUnifiedView = memo(({ diffFile }: { diffFile: DiffFile }) => {
2222

2323
const theme = diffFile._getTheme();
2424

25-
const { columns } = useTerminalSize();
25+
const { columns: _columns } = useTerminalSize();
2626

2727
const unifiedLineLength = Math.max(diffFile.unifiedLineLength, diffFile.fileLineLength);
2828

2929
const lineNumWidth = unifiedLineLength.toString().length;
3030

3131
const lines = getUnifiedContentLine(diffFile);
3232

33+
const columns = width || _columns;
34+
3335
if (!columns) return null;
3436

3537
return (

packages/cli/src/components/DiffView.tsx

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { DiffModeEnum } from "@git-diff-view/utils";
44
import { Box } from "ink";
55
import React, { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useRef } from "react";
66

7-
import { useIsMounted } from "../hooks/useIsMounted";
87
import { useUnmount } from "../hooks/useUnmount";
98

109
import { DiffSplitView } from "./DiffSplitView";
@@ -71,15 +70,14 @@ type DiffViewProps_2<T> = Omit<DiffViewProps<T>, "data"> & {
7170

7271
const InternalDiffView = <T extends unknown>(
7372
props: Omit<DiffViewProps<T>, "data"> & {
74-
isMounted: boolean;
7573
wrapperRef?: RefObject<DOMElement>;
7674
}
7775
) => {
7876
const {
77+
width: _width,
7978
diffFile,
8079
diffViewMode,
8180
diffViewHighlight,
82-
isMounted,
8381
wrapperRef,
8482
extendData,
8583
renderExtendLine,
@@ -99,8 +97,6 @@ const InternalDiffView = <T extends unknown>(
9997
setId,
10098
mode,
10199
setMode,
102-
mounted,
103-
setMounted,
104100
enableHighlight,
105101
setEnableHighlight,
106102
setExtendData,
@@ -112,6 +108,8 @@ const InternalDiffView = <T extends unknown>(
112108
setTabWidth,
113109
hideOperator,
114110
setHideOperator,
111+
width,
112+
setWidth,
115113
} = useDiffContext.getReadonlyState();
116114

117115
if (diffFileId && diffFileId !== id) {
@@ -122,10 +120,6 @@ const InternalDiffView = <T extends unknown>(
122120
setMode(diffViewMode);
123121
}
124122

125-
if (mounted !== isMounted) {
126-
setMounted(isMounted);
127-
}
128-
129123
if (diffViewHighlight !== enableHighlight) {
130124
setEnableHighlight(diffViewHighlight);
131125
}
@@ -149,12 +143,16 @@ const InternalDiffView = <T extends unknown>(
149143
if (diffViewHideOperator !== hideOperator) {
150144
setHideOperator(diffViewHideOperator);
151145
}
146+
147+
if (_width !== width) {
148+
setWidth(_width);
149+
}
152150
}, [
151+
_width,
153152
useDiffContext,
154153
diffViewHighlight,
155154
diffViewMode,
156155
diffFileId,
157-
isMounted,
158156
extendData,
159157
renderExtendLine,
160158
diffViewTabSpace,
@@ -181,9 +179,9 @@ const InternalDiffView = <T extends unknown>(
181179
data-highlighter={diffFile._getHighlighterName()}
182180
>
183181
{diffViewMode & DiffModeEnum.Split ? (
184-
<DiffSplitView diffFile={diffFile} />
182+
<DiffSplitView diffFile={diffFile} width={_width} />
185183
) : (
186-
<DiffUnifiedView diffFile={diffFile} />
184+
<DiffUnifiedView diffFile={diffFile} width={_width} />
187185
)}
188186
</Box>
189187
</DiffViewContext.Provider>
@@ -196,7 +194,9 @@ const DiffViewContainerWithRef = <T extends unknown>(
196194
props: DiffViewProps<T>,
197195
ref: ForwardedRef<{ getDiffFileInstance: () => DiffFile }>
198196
) => {
199-
const { registerHighlighter, data, diffViewTheme, diffFile: _diffFile, width, ...restProps } = props;
197+
const { registerHighlighter, data, diffViewTheme, diffFile: _diffFile, ...restProps } = props;
198+
199+
const width = restProps.width;
200200

201201
const domRef = useRef<DOMElement>(null);
202202

@@ -229,8 +229,6 @@ const DiffViewContainerWithRef = <T extends unknown>(
229229
diffFileRef.current = diffFile;
230230
}
231231

232-
const isMounted = useIsMounted();
233-
234232
useEffect(() => {
235233
if (_diffFile && diffFile) {
236234
_diffFile._addClonedInstance(diffFile);
@@ -275,7 +273,6 @@ const DiffViewContainerWithRef = <T extends unknown>(
275273
{...restProps}
276274
wrapperRef={domRef}
277275
diffFile={diffFile}
278-
isMounted={isMounted}
279276
diffViewTheme={diffViewTheme}
280277
diffViewTabWidth={props.diffViewTabWidth || "medium"}
281278
diffViewMode={restProps.diffViewMode || DiffModeEnum.SplitGitHub}

packages/cli/src/components/codeTools.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ import type { CodeViewProps } from "./CodeView";
55
import type { DOMElement } from "ink";
66
import type { Ref, UseSelectorWithStore } from "reactivity-store";
77

8-
export const createCodeConfigStore = <T = any>(props: CodeViewProps<T> & { isMounted: boolean }, fileId: string) => {
8+
export const createCodeConfigStore = <T = any>(props: CodeViewProps<T>, fileId: string) => {
99
return createStore(() => {
1010
const id = ref(fileId);
1111

1212
const setId = (_id: string) => (id.value = _id);
1313

14+
const width = ref(props.width);
15+
16+
const setWidth = (w: number) => (width.value = w);
17+
1418
const tabSpace = ref(props.codeViewTabSpace);
1519

1620
const setTabSpace = (_tabSpace: boolean) => (tabSpace.value = _tabSpace);
@@ -23,10 +27,6 @@ export const createCodeConfigStore = <T = any>(props: CodeViewProps<T> & { isMou
2327

2428
const setWrapper = (_wrapper?: DOMElement) => (wrapper.value = markRaw({ current: _wrapper }));
2529

26-
const mounted = ref(props.isMounted);
27-
28-
const setMounted = (_mounted: boolean) => (mounted.value = _mounted);
29-
3030
const enableHighlight = ref(props.codeViewHighlight);
3131

3232
const setEnableHighlight = (_enableHighlight: boolean) => (enableHighlight.value = _enableHighlight);
@@ -56,10 +56,10 @@ export const createCodeConfigStore = <T = any>(props: CodeViewProps<T> & { isMou
5656
return {
5757
id,
5858
setId,
59+
width,
60+
setWidth,
5961
wrapper,
6062
setWrapper,
61-
mounted,
62-
setMounted,
6363
tabSpace,
6464
setTabSpace,
6565
tabWidth,
@@ -75,10 +75,10 @@ export const createCodeConfigStore = <T = any>(props: CodeViewProps<T> & { isMou
7575
}) as UseSelectorWithStore<{
7676
id: Ref<string>;
7777
setId: (id: string) => void;
78+
width: Ref<number>;
79+
setWidth: (w: number) => void;
7880
wrapper: Ref<{ current: DOMElement }>;
7981
setWrapper: (wrapper?: DOMElement) => void;
80-
mounted: Ref<boolean>;
81-
setMounted: (mounted: boolean) => void;
8282
tabSpace: Ref<boolean>;
8383
setTabSpace: (tabSpace: boolean) => void;
8484
tabWidth: Ref<"small" | "medium" | "large">;

0 commit comments

Comments
 (0)