diff options
Diffstat (limited to 'subprojects/frontend/src/editor/PanelStore.ts')
-rw-r--r-- | subprojects/frontend/src/editor/PanelStore.ts | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/subprojects/frontend/src/editor/PanelStore.ts b/subprojects/frontend/src/editor/PanelStore.ts index 653d309c..1af4ace1 100644 --- a/subprojects/frontend/src/editor/PanelStore.ts +++ b/subprojects/frontend/src/editor/PanelStore.ts | |||
@@ -10,14 +10,17 @@ const log = getLogger('editor.PanelStore'); | |||
10 | export default class PanelStore { | 10 | export default class PanelStore { |
11 | state = false; | 11 | state = false; |
12 | 12 | ||
13 | element: Element | undefined; | ||
14 | |||
13 | constructor( | 15 | constructor( |
14 | private readonly panelId: string, | 16 | readonly panelClass: string, |
15 | private readonly openCommand: Command, | 17 | private readonly openCommand: Command, |
16 | private readonly closeCommand: Command, | 18 | private readonly closeCommand: Command, |
17 | private readonly store: EditorStore, | 19 | protected readonly store: EditorStore, |
18 | ) { | 20 | ) { |
19 | makeObservable(this, { | 21 | makeObservable(this, { |
20 | state: observable, | 22 | state: observable, |
23 | element: observable, | ||
21 | open: action, | 24 | open: action, |
22 | close: action, | 25 | close: action, |
23 | toggle: action, | 26 | toggle: action, |
@@ -25,6 +28,10 @@ export default class PanelStore { | |||
25 | }); | 28 | }); |
26 | } | 29 | } |
27 | 30 | ||
31 | get id(): string { | ||
32 | return `${this.store.id}-${this.panelClass}`; | ||
33 | } | ||
34 | |||
28 | open(): boolean { | 35 | open(): boolean { |
29 | return this.setState(true); | 36 | return this.setState(true); |
30 | } | 37 | } |
@@ -41,7 +48,7 @@ export default class PanelStore { | |||
41 | if (this.state === newState) { | 48 | if (this.state === newState) { |
42 | return false; | 49 | return false; |
43 | } | 50 | } |
44 | log.debug('Show', this.panelId, 'panel', newState); | 51 | log.debug('Show', this.panelClass, 'panel', newState); |
45 | if (newState) { | 52 | if (newState) { |
46 | this.doOpen(); | 53 | this.doOpen(); |
47 | } else { | 54 | } else { |
@@ -58,7 +65,7 @@ export default class PanelStore { | |||
58 | } | 65 | } |
59 | } | 66 | } |
60 | 67 | ||
61 | private doOpen(): void { | 68 | protected doOpen(): void { |
62 | if (!this.store.doCommand(this.openCommand)) { | 69 | if (!this.store.doCommand(this.openCommand)) { |
63 | return; | 70 | return; |
64 | } | 71 | } |
@@ -66,10 +73,19 @@ export default class PanelStore { | |||
66 | if (view === undefined) { | 73 | if (view === undefined) { |
67 | return; | 74 | return; |
68 | } | 75 | } |
69 | const buttonQuery = `.cm-${this.panelId}.cm-panel button[name="close"]`; | 76 | // We always access the panel DOM element by class name, even for the search panel, |
70 | const closeButton = view.dom.querySelector(buttonQuery); | 77 | // where we control the creation of the element, so that we can have a uniform way to |
78 | // access panel created by both CodeMirror and us. | ||
79 | this.element = | ||
80 | view.dom.querySelector(`.${this.panelClass}.cm-panel`) ?? undefined; | ||
81 | if (this.element === undefined) { | ||
82 | log.error('Failed to add panel', this.panelClass, 'to DOM'); | ||
83 | return; | ||
84 | } | ||
85 | this.element.id = this.id; | ||
86 | const closeButton = this.element.querySelector('button[name="close"]'); | ||
71 | if (closeButton !== null) { | 87 | if (closeButton !== null) { |
72 | log.debug('Addig close button callback to', this.panelId, 'panel'); | 88 | log.debug('Addig close button callback to', this.panelClass, 'panel'); |
73 | // We must remove the event listener from the button that dispatches a transaction | 89 | // We must remove the event listener from the button that dispatches a transaction |
74 | // without going through `EditorStore`. This listened is added by CodeMirror, | 90 | // without going through `EditorStore`. This listened is added by CodeMirror, |
75 | // and we can only remove it by cloning the DOM node: https://stackoverflow.com/a/9251864 | 91 | // and we can only remove it by cloning the DOM node: https://stackoverflow.com/a/9251864 |
@@ -79,12 +95,17 @@ export default class PanelStore { | |||
79 | event.preventDefault(); | 95 | event.preventDefault(); |
80 | }); | 96 | }); |
81 | closeButton.replaceWith(closeButtonWithoutListeners); | 97 | closeButton.replaceWith(closeButtonWithoutListeners); |
82 | } else { | ||
83 | log.error('Opened', this.panelId, 'panel has no close button'); | ||
84 | } | 98 | } |
85 | } | 99 | } |
86 | 100 | ||
87 | private doClose(): void { | 101 | protected doClose(): void { |
88 | this.store.doCommand(this.closeCommand); | 102 | this.store.doCommand(this.closeCommand); |
103 | if (this.element === undefined) { | ||
104 | return; | ||
105 | } | ||
106 | if (this.store.view !== undefined) { | ||
107 | log.error('Failed to remove search panel from DOM'); | ||
108 | } | ||
109 | this.element = undefined; | ||
89 | } | 110 | } |
90 | } | 111 | } |