@@ -19,7 +19,6 @@ import CodeMirror, { EditorView, ReactCodeMirrorRef, ViewUpdate } from '@uiw/rea
19
19
import { MergeView } from '@codemirror/merge'
20
20
21
21
import { getComponentSpecificThemeClass } from '@Shared/Providers'
22
- import { getUniqueId } from '@Shared/Helpers'
23
22
import { Progressing } from '@Common/Progressing'
24
23
25
24
import { useCodeEditorContext } from './CodeEditor.context'
@@ -53,11 +52,11 @@ export const CodeEditorRenderer = ({
53
52
54
53
// STATES
55
54
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 )
57
57
58
58
// REFS
59
59
const codeMirrorRef = useRef < ReactCodeMirrorRef > ( )
60
- const codeMirrorMergeRef = useRef < MergeView > ( )
61
60
const codeMirrorMergeParentRef = useRef < HTMLDivElement > ( )
62
61
const diffMinimapRef = useRef < MergeView > ( )
63
62
const diffMinimapParentRef = useRef < HTMLDivElement > ( )
@@ -91,9 +90,9 @@ export const CodeEditorRenderer = ({
91
90
let isFocused = false
92
91
const body = document . querySelector ( 'body' )
93
92
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
97
96
98
97
isFocused =
99
98
( lhsEditor . hasFocus || rhsEditor . hasFocus ) &&
@@ -112,49 +111,41 @@ export const CodeEditorRenderer = ({
112
111
}
113
112
}
114
113
} , [
115
- codeMirrorMergeRef . current ?. a ?. hasFocus ,
116
- codeMirrorMergeRef . current ?. b ?. hasFocus ,
114
+ codeMirrorMergeInstance ?. a ?. hasFocus ,
115
+ codeMirrorMergeInstance ?. b ?. hasFocus ,
117
116
codeMirrorRef . current ?. view ?. hasFocus ,
118
117
] )
119
118
120
119
// SYNCING LEFT RIGHT EDITOR HORIZONTAL SCROLLS
121
120
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 ,
124
123
} )
125
124
}
126
125
127
126
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 ,
130
129
} )
131
130
}
132
131
133
132
useEffect ( ( ) => {
134
133
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
+ }
146
139
}
147
140
148
141
return ( ) => {
149
- setCodeEditorDiffViewKey ( '' )
150
-
151
142
// 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 )
155
146
}
156
147
}
157
- } , [ loading , diffMode , codemirrorMergeKey ] )
148
+ } , [ codeMirrorMergeInstance ] )
158
149
159
150
const onCreateEditor = ( ) => {
160
151
updateGutterWidth ( )
@@ -168,6 +159,8 @@ export const CodeEditorRenderer = ({
168
159
handleLhsOnChange ( val , vu )
169
160
}
170
161
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.
171
164
updateDiffMinimapValues ( diffMinimapRef . current , vu . transactions , 'a' )
172
165
} )
173
166
@@ -178,45 +171,49 @@ export const CodeEditorRenderer = ({
178
171
handleOnChange ( val , vu )
179
172
}
180
173
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.
181
176
updateDiffMinimapValues ( diffMinimapRef . current , vu . transactions , 'b' )
182
177
} )
183
178
184
179
// DIFF VIEW INITIALIZATION
185
180
useEffect ( ( ) => {
186
181
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
+ )
200
197
}
201
198
202
199
return ( ) => {
203
- codeMirrorMergeRef . current ?. destroy ( )
200
+ codeMirrorMergeInstance ?. destroy ( )
204
201
}
205
202
} , [ loading , codemirrorMergeKey , diffMode ] )
206
203
207
204
// Sync external changes of `lhsValue` and `value` state to the diff-editor state.
208
205
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 ( )
211
208
if ( originalDoc !== lhsValue ) {
212
- codeMirrorMergeRef . current . a . dispatch ( {
209
+ codeMirrorMergeInstance . a . dispatch ( {
213
210
changes : { from : 0 , to : originalDoc . length , insert : lhsValue || '' } ,
214
211
} )
215
212
}
216
213
217
- const modifiedDoc = codeMirrorMergeRef . current . b . state . doc . toString ( )
214
+ const modifiedDoc = codeMirrorMergeInstance . b . state . doc . toString ( )
218
215
if ( modifiedDoc !== value ) {
219
- codeMirrorMergeRef . current . b . dispatch ( {
216
+ codeMirrorMergeInstance . b . dispatch ( {
220
217
changes : { from : 0 , to : originalDoc . length , insert : value || '' } ,
221
218
} )
222
219
}
@@ -225,8 +222,8 @@ export const CodeEditorRenderer = ({
225
222
226
223
// MINIMAP INITIALIZATION
227
224
useEffect ( ( ) => {
228
- if ( ! loading && diffMinimapParentRef . current ) {
229
- diffMinimapRef . current = new MergeView ( {
225
+ if ( codeMirrorMergeInstance && diffMinimapParentRef . current ) {
226
+ const diffMinimapMergeView = new MergeView ( {
230
227
a : {
231
228
doc : lhsValue ,
232
229
extensions : diffMinimapExtensions ,
@@ -239,12 +236,15 @@ export const CodeEditorRenderer = ({
239
236
diffConfig : { scanLimit : 5000 } ,
240
237
parent : diffMinimapParentRef . current ,
241
238
} )
239
+
240
+ diffMinimapRef . current = diffMinimapMergeView
241
+ setDiffMinimapInstance ( diffMinimapMergeView )
242
242
}
243
243
244
244
return ( ) => {
245
- diffMinimapRef . current ?. destroy ( )
245
+ diffMinimapInstance ?. destroy ( )
246
246
}
247
- } , [ codeEditorDiffViewKey ] )
247
+ } , [ codeMirrorMergeInstance ] )
248
248
249
249
const { codeEditorClassName, codeEditorHeight, codeEditorParentClassName } = getCodeEditorHeight ( height )
250
250
@@ -265,9 +265,9 @@ export const CodeEditorRenderer = ({
265
265
className = { `cm-merge-theme flex-grow-1 h-100 dc__overflow-hidden ${ readOnly ? 'code-editor__read-only' : '' } ` }
266
266
/>
267
267
< DiffMinimap
268
- key = { codeEditorDiffViewKey }
269
268
theme = { theme }
270
- view = { codeMirrorMergeRef . current }
269
+ view = { codeMirrorMergeInstance }
270
+ minimapView = { diffMinimapInstance }
271
271
diffMinimapParentRef = { diffMinimapParentRef }
272
272
/>
273
273
</ div >
0 commit comments