From 27a22d7609fa600d98531684b12e888397d1b135 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 13 Feb 2026 10:02:58 +0100 Subject: [PATCH] fix: shove logic out of react --- .../src/repl/components/panel/SettingsTab.jsx | 52 ++++++------------- website/src/repl/prebakeCodeMirror.mjs | 31 +++++++++-- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/website/src/repl/components/panel/SettingsTab.jsx b/website/src/repl/components/panel/SettingsTab.jsx index f640cd8c0..90bb7ad67 100644 --- a/website/src/repl/components/panel/SettingsTab.jsx +++ b/website/src/repl/components/panel/SettingsTab.jsx @@ -1,5 +1,5 @@ import { defaultSettings, settingsMap, useSettings, storePrebakeScript, setSettingsTab } from '../../../settings.mjs'; -import { themes, codemirrorSettings } from '@strudel/codemirror'; +import { themes } from '@strudel/codemirror'; import { PrebakeCodeMirror } from '../../../repl/prebakeCodeMirror.mjs'; import { confirmAndReloadPage, isUdels } from '../../util.mjs'; import { ButtonGroup } from './Forms.jsx'; @@ -9,8 +9,7 @@ import { confirmDialog } from '../../util.mjs'; import { DEFAULT_MAX_POLYPHONY, setMaxPolyphony, setMultiChannelOrbits } from '@strudel/webaudio'; import { ActionButton, SpecialActionButton } from '../button/action-button.jsx'; import { exportScript, ImportPrebakeScriptButton } from './ImportPrebakeScriptButton.jsx'; -import { useCallback, useEffect, useRef } from 'react'; -import { Code } from '../Code.jsx'; +import { useEffect, useRef } from 'react'; function cx(...classes) { // : Array @@ -360,46 +359,25 @@ function MainSettingsContent({ started }) { function PrebakeSettingsContent() { const { fontFamily, includePrebakeScriptInShare, prebakeScript } = useSettings(); - const init = useCallback(() => { - const settings = codemirrorSettings.get(); - // TODO: This instance need to be created at the top level to not create a new instance here - const prebakeCodemirror = new PrebakeCodeMirror( - prebakeScript, - (code) => storePrebakeScript(code), - containerRef, - editorRef, - settings, - ); - editorRef.current = prebakeCodemirror; - }, []); const editorRef = useRef(); - const containerRef = useRef(); - const handleSaveEvent = async (e) => { - await editorRef.current?.savePrebake(); - e?.cancelable && e.preventDefault?.(); - }; - const handleToggleComment = (e) => { - if (e.detail.view !== editorRef.current.view) { - return; // ignore events from other editors - } - editorRef.current?.toggleComment(); - e?.cancelable && e.preventDefault?.(); - }; - const handleSetCode = (code) => { - editorRef.current?.setCode(code); - }; useEffect(() => { - document.addEventListener('repl-evaluate', handleSaveEvent); - document.addEventListener('repl-toggle-comment', handleToggleComment); return () => { - document.removeEventListener('prebake-evaluate', handleSaveEvent); - document.removeEventListener('prebake-toggle-comment', handleToggleComment); + editorRef.current?.cleanup(); }; - }, []); + }); + return (
- +
{ + if (editorRef.current) { + return; + } + editorRef.current = new PrebakeCodeMirror(prebakeScript, (code) => storePrebakeScript(code), el); + }} + >
- + editorRef.current?.editor.setCode(code)} /> exportScript(prebakeScript)}>export editorRef.current?.savePrebake()}>save
diff --git a/website/src/repl/prebakeCodeMirror.mjs b/website/src/repl/prebakeCodeMirror.mjs index 1423c1d33..9c310c8b6 100644 --- a/website/src/repl/prebakeCodeMirror.mjs +++ b/website/src/repl/prebakeCodeMirror.mjs @@ -4,10 +4,11 @@ import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language' import { Compartment, EditorState, Prec } from '@codemirror/state'; import { drawSelection, EditorView, keymap } from '@codemirror/view'; import { logger } from '@strudel/core'; -import { basicSetup, flash, initTheme, extensions, parseBooleans } from '@strudel/codemirror'; +import { basicSetup, flash, initTheme, extensions, parseBooleans, codemirrorSettings } from '@strudel/codemirror'; export class PrebakeCodeMirror { - constructor(initialCode, storePrebake, containerRef, editorRef, settings) { + constructor(initialCode, storePrebake, container) { + const settings = codemirrorSettings.get(); this.storePrebake = storePrebake; const compartments = Object.fromEntries(Object.keys(extensions).map((key) => [key, new Compartment()])); const initialSettings = Object.keys(compartments).map((key) => @@ -55,12 +56,34 @@ export class PrebakeCodeMirror { ), ], }); - editorRef.current = state; + this.code = initialCode; this.view = new EditorView({ state, - parent: containerRef.current, + parent: container, }); + + const handleSaveEvent = async (e) => { + if (e.detail.view !== this.view) { + return; // ignore events from other editors + } + await this.savePrebake(); + e?.cancelable && e.preventDefault?.(); + }; + const handleToggleComment = (e) => { + if (e.detail.view !== this.view) { + return; // ignore events from other editors + } + this.toggleComment(); + e?.cancelable && e.preventDefault?.(); + }; + + document.addEventListener('repl-evaluate', handleSaveEvent); + document.addEventListener('repl-toggle-comment', handleToggleComment); + this.cleanup = () => { + document.removeEventListener('prebake-evaluate', handleSaveEvent); + document.removeEventListener('prebake-toggle-comment', handleToggleComment); + }; } async savePrebake() {