From 299c4d93597b3065e6a1017ebe692cde66fc5e39 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 11 Oct 2021 01:03:21 +0200 Subject: feat(web): experiment with Lezer parser --- language-web/src/main/js/editor/EditorArea.tsx | 49 ++++++++++++++++++-------- 1 file changed, 35 insertions(+), 14 deletions(-) (limited to 'language-web/src/main/js/editor/EditorArea.tsx') diff --git a/language-web/src/main/js/editor/EditorArea.tsx b/language-web/src/main/js/editor/EditorArea.tsx index 58d65184..460005ce 100644 --- a/language-web/src/main/js/editor/EditorArea.tsx +++ b/language-web/src/main/js/editor/EditorArea.tsx @@ -1,8 +1,14 @@ import { Command, EditorView } from '@codemirror/view'; import { closeSearchPanel, openSearchPanel } from '@codemirror/search'; import { closeLintPanel, openLintPanel } from '@codemirror/lint'; + import { observer } from 'mobx-react-lite'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { + useCallback, + useEffect, + useRef, + useState, +} from 'react'; import { EditorParent } from './EditorParent'; import { getLogger } from '../logging'; @@ -11,36 +17,49 @@ import { useRootStore } from '../RootStore'; const log = getLogger('EditorArea'); function usePanel( - label: string, + 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; } - const success = stateToSet ? openCommand(editorView) : closeCommand(editorView); - if (!success) { - log.error( - 'Failed to synchronize', - label, - 'panel state - store state:', - cachedViewState, - 'view state:', - stateToSet, - ); + 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, - label, + panelId, openCommand, closeCommand, + closeCallback, ]); return setCachedViewState; } @@ -56,14 +75,16 @@ export const EditorArea = observer(() => { editorViewState, openSearchPanel, closeSearchPanel, + useCallback(() => editorStore.setSearchPanelOpen(false), [editorStore]), ); const setLintPanelOpen = usePanel( - 'lint', + 'panel-lint', editorStore.showLintPanel, editorViewState, openLintPanel, closeLintPanel, + useCallback(() => editorStore.setLintPanelOpen(false), [editorStore]), ); useEffect(() => { -- cgit v1.2.3-70-g09d2