diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-12-09 20:39:44 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-12-11 12:18:43 +0100 |
commit | ff64d4ce24c260632c0309af774a0a2cfc00fdcd (patch) | |
tree | 1c234ff2c1d9830ab99c792995b14139c177b00b /subprojects/frontend/src/editor/EditorStore.ts | |
parent | chore(frontend): upgrade to vite 4 (diff) | |
download | refinery-ff64d4ce24c260632c0309af774a0a2cfc00fdcd.tar.gz refinery-ff64d4ce24c260632c0309af774a0a2cfc00fdcd.tar.zst refinery-ff64d4ce24c260632c0309af774a0a2cfc00fdcd.zip |
refactor(frontend): lazy load XtextClient
Improve time to a usable editor by loading the xtext client lazily.
The already existing delay to connect masks the delay of loading.
Diffstat (limited to 'subprojects/frontend/src/editor/EditorStore.ts')
-rw-r--r-- | subprojects/frontend/src/editor/EditorStore.ts | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/subprojects/frontend/src/editor/EditorStore.ts b/subprojects/frontend/src/editor/EditorStore.ts index 1f301c31..0a0d885d 100644 --- a/subprojects/frontend/src/editor/EditorStore.ts +++ b/subprojects/frontend/src/editor/EditorStore.ts | |||
@@ -16,12 +16,12 @@ import { | |||
16 | type EditorState, | 16 | type EditorState, |
17 | } from '@codemirror/state'; | 17 | } from '@codemirror/state'; |
18 | import { type Command, EditorView } from '@codemirror/view'; | 18 | import { type Command, EditorView } from '@codemirror/view'; |
19 | import { makeAutoObservable, observable } from 'mobx'; | 19 | import { makeAutoObservable, observable, runInAction } from 'mobx'; |
20 | import { nanoid } from 'nanoid'; | 20 | import { nanoid } from 'nanoid'; |
21 | 21 | ||
22 | import type PWAStore from '../PWAStore'; | 22 | import type PWAStore from '../PWAStore'; |
23 | import getLogger from '../utils/getLogger'; | 23 | import getLogger from '../utils/getLogger'; |
24 | import XtextClient from '../xtext/XtextClient'; | 24 | import type XtextClient from '../xtext/XtextClient'; |
25 | 25 | ||
26 | import LintPanelStore from './LintPanelStore'; | 26 | import LintPanelStore from './LintPanelStore'; |
27 | import SearchPanelStore from './SearchPanelStore'; | 27 | import SearchPanelStore from './SearchPanelStore'; |
@@ -40,7 +40,7 @@ export default class EditorStore { | |||
40 | 40 | ||
41 | state: EditorState; | 41 | state: EditorState; |
42 | 42 | ||
43 | private readonly client: XtextClient; | 43 | private client: XtextClient | undefined; |
44 | 44 | ||
45 | view: EditorView | undefined; | 45 | view: EditorView | undefined; |
46 | 46 | ||
@@ -50,51 +50,63 @@ export default class EditorStore { | |||
50 | 50 | ||
51 | showLineNumbers = false; | 51 | showLineNumbers = false; |
52 | 52 | ||
53 | disposed = false; | ||
54 | |||
53 | constructor(initialValue: string, pwaStore: PWAStore) { | 55 | constructor(initialValue: string, pwaStore: PWAStore) { |
54 | this.id = nanoid(); | 56 | this.id = nanoid(); |
55 | this.state = createEditorState(initialValue, this); | 57 | this.state = createEditorState(initialValue, this); |
56 | this.client = new XtextClient(this, pwaStore); | ||
57 | this.searchPanel = new SearchPanelStore(this); | 58 | this.searchPanel = new SearchPanelStore(this); |
58 | this.lintPanel = new LintPanelStore(this); | 59 | this.lintPanel = new LintPanelStore(this); |
60 | (async () => { | ||
61 | const { default: LazyXtextClient } = await import('../xtext/XtextClient'); | ||
62 | runInAction(() => { | ||
63 | if (this.disposed) { | ||
64 | return; | ||
65 | } | ||
66 | this.client = new LazyXtextClient(this, pwaStore); | ||
67 | this.client.start(); | ||
68 | }); | ||
69 | })().catch((error) => { | ||
70 | log.error('Failed to load XtextClient', error); | ||
71 | }); | ||
59 | makeAutoObservable<EditorStore, 'client'>(this, { | 72 | makeAutoObservable<EditorStore, 'client'>(this, { |
60 | id: false, | 73 | id: false, |
61 | state: observable.ref, | 74 | state: observable.ref, |
62 | client: false, | 75 | client: observable.ref, |
63 | view: observable.ref, | 76 | view: observable.ref, |
64 | searchPanel: false, | 77 | searchPanel: false, |
65 | lintPanel: false, | 78 | lintPanel: false, |
66 | contentAssist: false, | 79 | contentAssist: false, |
67 | formatText: false, | 80 | formatText: false, |
68 | }); | 81 | }); |
69 | this.client.start(); | ||
70 | } | 82 | } |
71 | 83 | ||
72 | get opened(): boolean { | 84 | get opened(): boolean { |
73 | return this.client.webSocketClient.opened; | 85 | return this.client?.webSocketClient.opened ?? false; |
74 | } | 86 | } |
75 | 87 | ||
76 | get opening(): boolean { | 88 | get opening(): boolean { |
77 | return this.client.webSocketClient.opening; | 89 | return this.client?.webSocketClient.opening ?? true; |
78 | } | 90 | } |
79 | 91 | ||
80 | get disconnectedByUser(): boolean { | 92 | get disconnectedByUser(): boolean { |
81 | return this.client.webSocketClient.disconnectedByUser; | 93 | return this.client?.webSocketClient.disconnectedByUser ?? false; |
82 | } | 94 | } |
83 | 95 | ||
84 | get networkMissing(): boolean { | 96 | get networkMissing(): boolean { |
85 | return this.client.webSocketClient.networkMissing; | 97 | return this.client?.webSocketClient.networkMissing ?? false; |
86 | } | 98 | } |
87 | 99 | ||
88 | get connectionErrors(): string[] { | 100 | get connectionErrors(): string[] { |
89 | return this.client.webSocketClient.errors; | 101 | return this.client?.webSocketClient.errors ?? []; |
90 | } | 102 | } |
91 | 103 | ||
92 | connect(): void { | 104 | connect(): void { |
93 | this.client.webSocketClient.connect(); | 105 | this.client?.webSocketClient.connect(); |
94 | } | 106 | } |
95 | 107 | ||
96 | disconnect(): void { | 108 | disconnect(): void { |
97 | this.client.webSocketClient.disconnect(); | 109 | this.client?.webSocketClient.disconnect(); |
98 | } | 110 | } |
99 | 111 | ||
100 | setDarkMode(darkMode: boolean): void { | 112 | setDarkMode(darkMode: boolean): void { |
@@ -158,7 +170,7 @@ export default class EditorStore { | |||
158 | private dispatchTransactionWithoutView(tr: Transaction): void { | 170 | private dispatchTransactionWithoutView(tr: Transaction): void { |
159 | log.trace('Editor transaction', tr); | 171 | log.trace('Editor transaction', tr); |
160 | this.state = tr.state; | 172 | this.state = tr.state; |
161 | this.client.onTransaction(tr); | 173 | this.client?.onTransaction(tr); |
162 | } | 174 | } |
163 | 175 | ||
164 | doCommand(command: Command): boolean { | 176 | doCommand(command: Command): boolean { |
@@ -216,7 +228,12 @@ export default class EditorStore { | |||
216 | this.dispatch(setOccurrences(write, read)); | 228 | this.dispatch(setOccurrences(write, read)); |
217 | } | 229 | } |
218 | 230 | ||
219 | contentAssist(context: CompletionContext): Promise<CompletionResult> { | 231 | async contentAssist( |
232 | context: CompletionContext, | ||
233 | ): Promise<CompletionResult | null> { | ||
234 | if (this.client === undefined) { | ||
235 | return null; | ||
236 | } | ||
220 | return this.client.contentAssist(context); | 237 | return this.client.contentAssist(context); |
221 | } | 238 | } |
222 | 239 | ||
@@ -252,11 +269,15 @@ export default class EditorStore { | |||
252 | } | 269 | } |
253 | 270 | ||
254 | formatText(): boolean { | 271 | formatText(): boolean { |
272 | if (this.client === undefined) { | ||
273 | return false; | ||
274 | } | ||
255 | this.client.formatText(); | 275 | this.client.formatText(); |
256 | return true; | 276 | return true; |
257 | } | 277 | } |
258 | 278 | ||
259 | dispose(): void { | 279 | dispose(): void { |
260 | this.client.dispose(); | 280 | this.client?.dispose(); |
281 | this.disposed = true; | ||
261 | } | 282 | } |
262 | } | 283 | } |