@@ -3,14 +3,15 @@ import { useEffect } from 'preact/hooks'
3
3
import { IoClose } from 'react-icons/io5'
4
4
import tinykeys from 'tinykeys'
5
5
import { usePopupCloseClick } from '../../lib/utils/popup-close-click'
6
- import { codeMirror , editors , openEditor } from '../../lib/state'
6
+ import { codeMirror , editors , openEditor , codeMirrorEditorText , _foldRanges , _widgets } from '../../lib/state'
7
7
import styles from './editor-modal.module.css'
8
+ import levenshtein from 'js-levenshtein'
9
+ import { runGameHeadless } from '../../lib/engine'
8
10
9
11
export default function EditorModal ( ) {
10
12
const Content = openEditor . value ? editors [ openEditor . value . kind ] . modalContent : ( ) => null
11
13
const text = useSignal ( openEditor . value ?. text ?? '' )
12
14
13
- // Sync code changes with editor text
14
15
useSignalEffect ( ( ) => {
15
16
if ( openEditor . value ) text . value = openEditor . value . text
16
17
} )
@@ -29,7 +30,7 @@ export default function EditorModal() {
29
30
insert : _text
30
31
}
31
32
} )
32
-
33
+
33
34
openEditor . value = {
34
35
..._openEditor ,
35
36
text : _text ,
@@ -40,6 +41,59 @@ export default function EditorModal() {
40
41
}
41
42
} )
42
43
44
+ // the challenge now is making the editor keep track of what map editor it's currently focused on and streaming the changes in the map editor
45
+ // it's tricky because maps can grow and shrink
46
+
47
+ useEffect ( ( ) => {
48
+ // just do this to sync the editor text with the code mirror text
49
+
50
+ const code = codeMirror . value ?. state . doc . toString ( ) ?? '' ;
51
+ const levenshtainDistances = _foldRanges . value . map ( ( foldRange , foldRangeIndex ) => {
52
+ const widgetKind = _widgets . value [ foldRangeIndex ] ?. value . spec . widget . props . kind ;
53
+
54
+ // if the widget kind is not the same as the open editor kind, don't do anything
55
+ if ( widgetKind !== openEditor . value ?. kind ) return - 1 ;
56
+
57
+ const theCode = code . slice ( foldRange ?. from , foldRange ?. to ) ;
58
+
59
+ const distance = levenshtein ( text . value , theCode )
60
+ return distance ;
61
+ } ) ;
62
+
63
+
64
+
65
+ // if (levenshtainDistances.length === 0) alert(`You are currently editing a deleted ${openEditor.value?.kind}`);
66
+ if ( levenshtainDistances . length === 0 ) return ;
67
+
68
+ // compute the index of the min distance
69
+ let indexOfMinDistance = 0 ;
70
+ levenshtainDistances . forEach ( ( distance , didx ) => {
71
+ if ( levenshtainDistances [ indexOfMinDistance ] ! < 0 ) indexOfMinDistance = didx ;
72
+ const min = levenshtainDistances [ indexOfMinDistance ] ! ;
73
+ if ( distance >= 0 && distance <= min ) indexOfMinDistance = didx ;
74
+ } ) ;
75
+
76
+ // update the open editor if the index is not -1
77
+ if ( indexOfMinDistance !== - 1 ) {
78
+ const editRange = _foldRanges . value [ indexOfMinDistance ]
79
+ const openEditorCode = code . slice ( editRange ?. from , editRange ?. to )
80
+
81
+ // the map editor needs to get the bitmaps after running the code
82
+ if ( openEditor . value ?. kind === 'map' ) runGameHeadless ( code ?? '' ) ;
83
+
84
+ openEditor . value = {
85
+ ...openEditor . value ,
86
+ editRange : {
87
+ from : editRange ! . from ,
88
+ to : editRange ! . to
89
+ } ,
90
+ text : openEditorCode
91
+ }
92
+ }
93
+
94
+ } , [ codeMirrorEditorText . value ] ) ;
95
+
96
+
43
97
usePopupCloseClick ( styles . content ! , ( ) => openEditor . value = null , ! ! openEditor . value )
44
98
useEffect ( ( ) => tinykeys ( window , {
45
99
'Escape' : ( ) => openEditor . value = null
@@ -54,4 +108,4 @@ export default function EditorModal() {
54
108
</ div >
55
109
</ div >
56
110
)
57
- }
111
+ }
0 commit comments