From 36311cc1c2085d5c9d99902a8c6e48b6144bb88f Mon Sep 17 00:00:00 2001 From: Shubham Panth Date: Mon, 7 Oct 2024 16:50:21 +0200 Subject: [PATCH] fixes #2304 (#2391) this changes fixes the problem it occurred on #2304, bit of format needed before publishing live --- src/components/popups-etc/editor-modal.tsx | 117 +++++++++++---------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/src/components/popups-etc/editor-modal.tsx b/src/components/popups-etc/editor-modal.tsx index c43d59d558..8eb9e9b6b2 100644 --- a/src/components/popups-etc/editor-modal.tsx +++ b/src/components/popups-etc/editor-modal.tsx @@ -45,27 +45,36 @@ export default function EditorModal() { // This is probably bad practice const _openEditor = openEditor.peek() // Gotta peek to avoid cycles const _text = text.value // But we want to sub to this - if (!codeMirror.value || !_openEditor) return - codeMirror.value.dispatch({ - changes: { - ..._openEditor.editRange, - insert: _text - } - }) - - openEditor.value = { - ..._openEditor, - text: _text, - editRange: { - from: _openEditor.editRange.from, - to: _openEditor.editRange.from + _text.length - } + // Sync only if there's an active CodeMirror editor and an open editor + if (!codeMirror.value || !_openEditor) return; + + // Differentiate between map and palette updates + if (_openEditor.kind === 'palette' || _openEditor.kind === 'map') { + console.log('dispatching', _openEditor.editRange, _text); + + codeMirror.value.dispatch({ + changes: { + from: _openEditor.editRange.from, + to: _openEditor.editRange.to, + insert: _text + } + }) + + // Update openEditor with new text and correct range + openEditor.value = { + ..._openEditor, + text: _text, + editRange: { + from: _openEditor.editRange.from, + to: _openEditor.editRange.from + _text.length + } + }; } + setUpdateCulprit(UpdateCulprit.OpenEditor); }, [text.value]); - useEffect(() => { // if update comes from codemirror doc (probably from a collab session) // this ensures that updates are not triggered from this effect which may cause an @@ -87,55 +96,53 @@ export default function EditorModal() { if (!openEditor.value) return; const code = codeMirror.value?.state.doc.toString() ?? ''; - const levenshteinDistances = _foldRanges.value.map((foldRange, foldRangeIndex) => { - const widgetKind = _widgets.value[foldRangeIndex]?.value.spec.widget.props.kind; + const levenshtainDistances = _foldRanges.value.map((foldRange, index) => { + const widgetKind = _widgets.value[index]?.value.spec.widget.props.kind; - // if the widget kind is not the same as the open editor kind, don't do anything - if (widgetKind !== openEditor.value?.kind) return -1; + // Filter out unrelated widgets + if (!openEditor.value || widgetKind !== openEditor.value.kind) return -1; - const theCode = code.slice(foldRange?.from, foldRange?.to); - - const distance = levenshtein(text.value, theCode) - return distance; + const foldCode = code.slice(foldRange.from, foldRange.to); + return levenshtein(text.value, foldCode); }); - // if (levenshtainDistances.length === 0) alert(`You are currently editing a deleted ${openEditor.value?.kind}`); - if (levenshteinDistances.length === 0) return; + // Find closest matching fold range + const validDistances = levenshtainDistances.filter(d => d >= 0); + if (validDistances.length === 0) return; - // compute the index of the min distance - let indexOfMinDistance = 0; - levenshteinDistances.forEach((distance, didx) => { - if (levenshteinDistances[indexOfMinDistance]! < 0) indexOfMinDistance = didx; - const min = levenshteinDistances[indexOfMinDistance]!; - if (distance >= 0 && distance <= min) indexOfMinDistance = didx; - }); + const indexOfMinDistance = validDistances.indexOf(Math.min(...validDistances)); + const editRange = _foldRanges.value[indexOfMinDistance]; - // update the open editor if the index is not -1 - if (indexOfMinDistance !== -1) { - const editRange = _foldRanges.value[indexOfMinDistance] - const openEditorCode = code.slice(editRange?.from, editRange?.to) + // Update the open editor range and content + if (editRange) { + const openEditorCode = code.slice(editRange.from, editRange.to); - // the map editor needs to get the bitmaps after running the code - if (openEditor.value?.kind === 'map') runGameHeadless(code ?? ''); - - text.value = openEditorCode; + // If it's a map editor, update bitmaps based on headless game logic + if (openEditor.value.kind === 'map') { + runGameHeadless(code); + } - openEditor.value = { - ...openEditor.value as OpenEditor, - editRange: { - from: editRange!.from, - to: editRange!.to - }, - text: openEditorCode - } - - } + openEditor.value = { + ...openEditor.value as OpenEditor, + editRange: { + from: editRange.from, + to: editRange.to + }, + text: openEditorCode + } + } } + // Handle closing modal on escape key press or outside click usePopupCloseClick(styles.content!, () => openEditor.value = null, !!openEditor.value) - useEffect(() => tinykeys(window, { - 'Escape': () => openEditor.value = null - }), []) + useEffect(() => { + const unsubscribe = tinykeys(window, { + 'Escape': () => openEditor.value = null + }); + return () => unsubscribe() + }, []) + + // Render only when there's an open editor if (!openEditor.value) return null return ( @@ -146,4 +153,4 @@ export default function EditorModal() { ) -} +} \ No newline at end of file