From 19cd11118cde7160cd447c81bc965007c0437479 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 16 Aug 2022 21:14:50 +0200 Subject: refactor(frondend): improve editor store and theme Also bumps frontend dependencies. --- subprojects/frontend/src/editor/EditorArea.tsx | 138 +++---------------------- 1 file changed, 15 insertions(+), 123 deletions(-) (limited to 'subprojects/frontend/src/editor/EditorArea.tsx') diff --git a/subprojects/frontend/src/editor/EditorArea.tsx b/subprojects/frontend/src/editor/EditorArea.tsx index d4305610..e5712461 100644 --- a/subprojects/frontend/src/editor/EditorArea.tsx +++ b/subprojects/frontend/src/editor/EditorArea.tsx @@ -1,139 +1,31 @@ -import { closeLintPanel, openLintPanel } from '@codemirror/lint'; -import { closeSearchPanel, openSearchPanel } from '@codemirror/search'; -import { type Command, EditorView } from '@codemirror/view'; +import { useTheme } from '@mui/material/styles'; import { observer } from 'mobx-react-lite'; -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { useRootStore } from '../RootStore'; -import getLogger from '../utils/getLogger'; -import EditorParent from './EditorParent'; - -const log = getLogger('editor.EditorArea'); - -function usePanel( - panelId: string, - stateToSet: boolean, - editorView: EditorView | null, - openCommand: Command, - closeCommand: Command, - closeCallback: () => void, -) { - const [cachedViewState, setCachedViewState] = useState(false); - useEffect(() => { - if (editorView === null || cachedViewState === stateToSet) { - return; - } - if (stateToSet) { - openCommand(editorView); - const buttonQuery = `.cm-${panelId}.cm-panel button[name="close"]`; - const closeButton = editorView.dom.querySelector(buttonQuery); - if (closeButton) { - log.debug('Addig close button callback to', panelId, 'panel'); - // We must remove the event listener added by CodeMirror from the button - // that dispatches a transaction without going through `EditorStorre`. - // Cloning a DOM node removes event listeners, - // see https://stackoverflow.com/a/9251864 - const closeButtonWithoutListeners = closeButton.cloneNode(true); - closeButtonWithoutListeners.addEventListener('click', (event) => { - closeCallback(); - event.preventDefault(); - }); - closeButton.replaceWith(closeButtonWithoutListeners); - } else { - log.error('Opened', panelId, 'panel has no close button'); - } - } else { - closeCommand(editorView); - } - setCachedViewState(stateToSet); - }, [ - stateToSet, - editorView, - cachedViewState, - panelId, - openCommand, - closeCommand, - closeCallback, - ]); - return setCachedViewState; -} - -function fixCodeMirrorAccessibility(editorView: EditorView) { - // Reported by Lighthouse 8.3.0. - const { contentDOM } = editorView; - contentDOM.removeAttribute('aria-expanded'); - contentDOM.setAttribute('aria-label', 'Code editor'); -} +import EditorTheme from './EditorTheme'; function EditorArea(): JSX.Element { const { editorStore } = useRootStore(); - const editorParentRef = useRef(null); - const [editorViewState, setEditorViewState] = useState( - null, - ); + const { + palette: { mode: paletteMode }, + } = useTheme(); - const setSearchPanelOpen = usePanel( - 'search', - editorStore.showSearchPanel, - editorViewState, - openSearchPanel, - closeSearchPanel, - useCallback(() => editorStore.setSearchPanelOpen(false), [editorStore]), + useEffect( + () => editorStore.setDarkMode(paletteMode === 'dark'), + [editorStore, paletteMode], ); - const setLintPanelOpen = usePanel( - 'panel-lint', - editorStore.showLintPanel, - editorViewState, - openLintPanel, - closeLintPanel, - useCallback(() => editorStore.setLintPanelOpen(false), [editorStore]), + const editorParentRef = useCallback( + (editorParent: HTMLDivElement | null) => { + editorStore.setEditorParent(editorParent); + }, + [editorStore], ); - useEffect(() => { - if (editorParentRef.current === null) { - return () => { - // Nothing to clean up. - }; - } - - const editorView = new EditorView({ - state: editorStore.state, - parent: editorParentRef.current, - dispatch: (transaction) => { - editorStore.onTransaction(transaction); - editorView.update([transaction]); - if (editorView.state !== editorStore.state) { - log.error( - 'Failed to synchronize editor state - store state:', - editorStore.state, - 'view state:', - editorView.state, - ); - } - }, - }); - fixCodeMirrorAccessibility(editorView); - setEditorViewState(editorView); - setSearchPanelOpen(false); - setLintPanelOpen(false); - // `dispatch` is bound to the view instance, - // so it does not have to be called as a method. - // eslint-disable-next-line @typescript-eslint/unbound-method - editorStore.updateDispatcher(editorView.dispatch); - log.info('Editor created'); - - return () => { - editorStore.updateDispatcher(null); - editorView.destroy(); - log.info('Editor destroyed'); - }; - }, [editorStore, setSearchPanelOpen, setLintPanelOpen]); - return ( - -- cgit v1.2.3-54-g00ecf