Skip to content

Commit 16d6382

Browse files
committed
fix: CodeEditor - refactor to use state for MergeView instances
1 parent 5fb7873 commit 16d6382

File tree

3 files changed

+58
-57
lines changed

3 files changed

+58
-57
lines changed

src/Common/CodeMirror/CodeEditorRenderer.tsx

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import CodeMirror, { EditorView, ReactCodeMirrorRef, ViewUpdate } from '@uiw/rea
1919
import { MergeView } from '@codemirror/merge'
2020

2121
import { getComponentSpecificThemeClass } from '@Shared/Providers'
22-
import { getUniqueId } from '@Shared/Helpers'
2322
import { Progressing } from '@Common/Progressing'
2423

2524
import { useCodeEditorContext } from './CodeEditor.context'
@@ -53,11 +52,11 @@ export const CodeEditorRenderer = ({
5352

5453
// STATES
5554
const [gutterWidth, setGutterWidth] = useState(0)
56-
const [codeEditorDiffViewKey, setCodeEditorDiffViewKey] = useState<string>('')
55+
const [codeMirrorMergeInstance, setCodeMirrorMergeInstance] = useState<MergeView>(null)
56+
const [diffMinimapInstance, setDiffMinimapInstance] = useState<MergeView>(null)
5757

5858
// REFS
5959
const codeMirrorRef = useRef<ReactCodeMirrorRef>()
60-
const codeMirrorMergeRef = useRef<MergeView>()
6160
const codeMirrorMergeParentRef = useRef<HTMLDivElement>()
6261
const diffMinimapRef = useRef<MergeView>()
6362
const diffMinimapParentRef = useRef<HTMLDivElement>()
@@ -91,9 +90,9 @@ export const CodeEditorRenderer = ({
9190
let isFocused = false
9291
const body = document.querySelector('body')
9392
if (body) {
94-
if (codeMirrorMergeRef.current) {
95-
const lhsEditor = codeMirrorMergeRef.current.a
96-
const rhsEditor = codeMirrorMergeRef.current.b
93+
if (codeMirrorMergeInstance) {
94+
const lhsEditor = codeMirrorMergeInstance.a
95+
const rhsEditor = codeMirrorMergeInstance.b
9796

9897
isFocused =
9998
(lhsEditor.hasFocus || rhsEditor.hasFocus) &&
@@ -112,49 +111,41 @@ export const CodeEditorRenderer = ({
112111
}
113112
}
114113
}, [
115-
codeMirrorMergeRef.current?.a?.hasFocus,
116-
codeMirrorMergeRef.current?.b?.hasFocus,
114+
codeMirrorMergeInstance?.a?.hasFocus,
115+
codeMirrorMergeInstance?.b?.hasFocus,
117116
codeMirrorRef.current?.view?.hasFocus,
118117
])
119118

120119
// SYNCING LEFT RIGHT EDITOR HORIZONTAL SCROLLS
121120
const handleLHSScroll = () => {
122-
codeMirrorMergeRef.current.a.scrollDOM.scrollTo({
123-
left: codeMirrorMergeRef.current.b.scrollDOM.scrollLeft,
121+
codeMirrorMergeInstance.a.scrollDOM.scrollTo({
122+
left: codeMirrorMergeInstance.b.scrollDOM.scrollLeft,
124123
})
125124
}
126125

127126
const handleRHSScroll = () => {
128-
codeMirrorMergeRef.current.b.scrollDOM.scrollTo({
129-
left: codeMirrorMergeRef.current.a.scrollDOM.scrollLeft,
127+
codeMirrorMergeInstance.b.scrollDOM.scrollTo({
128+
left: codeMirrorMergeInstance.a.scrollDOM.scrollLeft,
130129
})
131130
}
132131

133132
useEffect(() => {
134133
if (!loading) {
135-
// This timeout is added to ensure ref of diff editor is properly initialized and \
136-
// key state is set to trigger re-render of diffMinimap with diff editor latest ref.
137-
setTimeout(() => {
138-
setCodeEditorDiffViewKey(getUniqueId())
139-
140-
// SYNCING LEFT RIGHT EDITOR HORIZONTAL SCROLLS
141-
if (codeMirrorMergeRef.current) {
142-
codeMirrorMergeRef.current.a.scrollDOM.addEventListener('scroll', handleRHSScroll)
143-
codeMirrorMergeRef.current.b.scrollDOM.addEventListener('scroll', handleLHSScroll)
144-
}
145-
}, 0)
134+
// SYNCING LEFT RIGHT EDITOR HORIZONTAL SCROLLS
135+
if (codeMirrorMergeInstance) {
136+
codeMirrorMergeInstance.a.scrollDOM.addEventListener('scroll', handleRHSScroll)
137+
codeMirrorMergeInstance.b.scrollDOM.addEventListener('scroll', handleLHSScroll)
138+
}
146139
}
147140

148141
return () => {
149-
setCodeEditorDiffViewKey('')
150-
151142
// SYNCING LEFT RIGHT EDITOR HORIZONTAL SCROLLS
152-
if (codeMirrorMergeRef.current) {
153-
codeMirrorMergeRef.current.b.scrollDOM.removeEventListener('scroll', handleLHSScroll)
154-
codeMirrorMergeRef.current.a.scrollDOM.removeEventListener('scroll', handleRHSScroll)
143+
if (codeMirrorMergeInstance) {
144+
codeMirrorMergeInstance.b.scrollDOM.removeEventListener('scroll', handleLHSScroll)
145+
codeMirrorMergeInstance.a.scrollDOM.removeEventListener('scroll', handleRHSScroll)
155146
}
156147
}
157-
}, [loading, diffMode, codemirrorMergeKey])
148+
}, [codeMirrorMergeInstance])
158149

159150
const onCreateEditor = () => {
160151
updateGutterWidth()
@@ -168,6 +159,8 @@ export const CodeEditorRenderer = ({
168159
handleLhsOnChange(val, vu)
169160
}
170161

162+
// Using `diffMinimapRef` instead of `diffMinimapInstance` since this extension captures the initial reference in a closure.
163+
// Changes to `diffMinimapInstance` won't be reflected after initialization, so we rely on `diffMinimapRef.current` for updates.
171164
updateDiffMinimapValues(diffMinimapRef.current, vu.transactions, 'a')
172165
})
173166

@@ -178,45 +171,49 @@ export const CodeEditorRenderer = ({
178171
handleOnChange(val, vu)
179172
}
180173

174+
// Using `diffMinimapRef` instead of `diffMinimapInstance` since this extension captures the initial reference in a closure.
175+
// Changes to `diffMinimapInstance` won't be reflected after initialization, so we rely on `diffMinimapRef.current` for updates.
181176
updateDiffMinimapValues(diffMinimapRef.current, vu.transactions, 'b')
182177
})
183178

184179
// DIFF VIEW INITIALIZATION
185180
useEffect(() => {
186181
if (!loading && codeMirrorMergeParentRef.current) {
187-
codeMirrorMergeRef.current = new MergeView({
188-
a: {
189-
doc: lhsValue,
190-
extensions: [...originalViewExtensions, originalUpdateListener],
191-
},
192-
b: {
193-
doc: value,
194-
extensions: [...modifiedViewExtensions, modifiedUpdateListener],
195-
},
196-
...(!readOnly ? { revertControls: 'a-to-b', renderRevertControl: getRevertControlButton } : {}),
197-
diffConfig: { scanLimit: 5000 },
198-
parent: codeMirrorMergeParentRef.current,
199-
})
182+
setCodeMirrorMergeInstance(
183+
new MergeView({
184+
a: {
185+
doc: lhsValue,
186+
extensions: [...originalViewExtensions, originalUpdateListener],
187+
},
188+
b: {
189+
doc: value,
190+
extensions: [...modifiedViewExtensions, modifiedUpdateListener],
191+
},
192+
...(!readOnly ? { revertControls: 'a-to-b', renderRevertControl: getRevertControlButton } : {}),
193+
diffConfig: { scanLimit: 5000 },
194+
parent: codeMirrorMergeParentRef.current,
195+
}),
196+
)
200197
}
201198

202199
return () => {
203-
codeMirrorMergeRef.current?.destroy()
200+
codeMirrorMergeInstance?.destroy()
204201
}
205202
}, [loading, codemirrorMergeKey, diffMode])
206203

207204
// Sync external changes of `lhsValue` and `value` state to the diff-editor state.
208205
useEffect(() => {
209-
if (codeMirrorMergeRef.current) {
210-
const originalDoc = codeMirrorMergeRef.current.a.state.doc.toString()
206+
if (codeMirrorMergeInstance) {
207+
const originalDoc = codeMirrorMergeInstance.a.state.doc.toString()
211208
if (originalDoc !== lhsValue) {
212-
codeMirrorMergeRef.current.a.dispatch({
209+
codeMirrorMergeInstance.a.dispatch({
213210
changes: { from: 0, to: originalDoc.length, insert: lhsValue || '' },
214211
})
215212
}
216213

217-
const modifiedDoc = codeMirrorMergeRef.current.b.state.doc.toString()
214+
const modifiedDoc = codeMirrorMergeInstance.b.state.doc.toString()
218215
if (modifiedDoc !== value) {
219-
codeMirrorMergeRef.current.b.dispatch({
216+
codeMirrorMergeInstance.b.dispatch({
220217
changes: { from: 0, to: originalDoc.length, insert: value || '' },
221218
})
222219
}
@@ -225,8 +222,8 @@ export const CodeEditorRenderer = ({
225222

226223
// MINIMAP INITIALIZATION
227224
useEffect(() => {
228-
if (!loading && diffMinimapParentRef.current) {
229-
diffMinimapRef.current = new MergeView({
225+
if (codeMirrorMergeInstance && diffMinimapParentRef.current) {
226+
const diffMinimapMergeView = new MergeView({
230227
a: {
231228
doc: lhsValue,
232229
extensions: diffMinimapExtensions,
@@ -239,12 +236,15 @@ export const CodeEditorRenderer = ({
239236
diffConfig: { scanLimit: 5000 },
240237
parent: diffMinimapParentRef.current,
241238
})
239+
240+
diffMinimapRef.current = diffMinimapMergeView
241+
setDiffMinimapInstance(diffMinimapMergeView)
242242
}
243243

244244
return () => {
245-
diffMinimapRef.current?.destroy()
245+
diffMinimapInstance?.destroy()
246246
}
247-
}, [codeEditorDiffViewKey])
247+
}, [codeMirrorMergeInstance])
248248

249249
const { codeEditorClassName, codeEditorHeight, codeEditorParentClassName } = getCodeEditorHeight(height)
250250

@@ -265,9 +265,9 @@ export const CodeEditorRenderer = ({
265265
className={`cm-merge-theme flex-grow-1 h-100 dc__overflow-hidden ${readOnly ? 'code-editor__read-only' : ''}`}
266266
/>
267267
<DiffMinimap
268-
key={codeEditorDiffViewKey}
269268
theme={theme}
270-
view={codeMirrorMergeRef.current}
269+
view={codeMirrorMergeInstance}
270+
minimapView={diffMinimapInstance}
271271
diffMinimapParentRef={diffMinimapParentRef}
272272
/>
273273
</div>

src/Common/CodeMirror/Extensions/DiffMinimap.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { DiffMinimapProps } from '../types'
66
import { CODE_EDITOR_FONT_SIZE, CODE_EDITOR_MIN_OVERLAY_HEIGHT } from '../CodeEditor.constants'
77
import { useCodeEditorContext } from '../CodeEditor.context'
88

9-
export const DiffMinimap = ({ view, theme, diffMinimapParentRef }: DiffMinimapProps) => {
9+
export const DiffMinimap = ({ view, minimapView, theme, diffMinimapParentRef }: DiffMinimapProps) => {
1010
// CONTEXTS
1111
const { lhsValue, value } = useCodeEditorContext()
1212

@@ -30,7 +30,7 @@ export const DiffMinimap = ({ view, theme, diffMinimapParentRef }: DiffMinimapPr
3030
}
3131

3232
return 1
33-
}, [lhsValue, value])
33+
}, [lhsValue, value, view, minimapView])
3434

3535
// Update the overlay position and size
3636
const updateOverlay = () => {
@@ -107,7 +107,7 @@ export const DiffMinimap = ({ view, theme, diffMinimapParentRef }: DiffMinimapPr
107107
dom.removeEventListener('scroll', handleDiffScroll)
108108
}
109109
}
110-
}, [])
110+
}, [view])
111111

112112
useEffect(() => {
113113
if (isDragging) {

src/Common/CodeMirror/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,6 @@ export type CodeEditorRendererProps = Required<
150150

151151
export interface DiffMinimapProps extends Pick<CodeEditorRendererProps, 'theme'> {
152152
view: MergeView
153+
minimapView: MergeView
153154
diffMinimapParentRef: MutableRefObject<HTMLDivElement>
154155
}

0 commit comments

Comments
 (0)