aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/editor
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-09 20:39:44 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-12-11 12:18:43 +0100
commitff64d4ce24c260632c0309af774a0a2cfc00fdcd (patch)
tree1c234ff2c1d9830ab99c792995b14139c177b00b /subprojects/frontend/src/editor
parentchore(frontend): upgrade to vite 4 (diff)
downloadrefinery-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')
-rw-r--r--subprojects/frontend/src/editor/EditorStore.ts53
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';
18import { type Command, EditorView } from '@codemirror/view'; 18import { type Command, EditorView } from '@codemirror/view';
19import { makeAutoObservable, observable } from 'mobx'; 19import { makeAutoObservable, observable, runInAction } from 'mobx';
20import { nanoid } from 'nanoid'; 20import { nanoid } from 'nanoid';
21 21
22import type PWAStore from '../PWAStore'; 22import type PWAStore from '../PWAStore';
23import getLogger from '../utils/getLogger'; 23import getLogger from '../utils/getLogger';
24import XtextClient from '../xtext/XtextClient'; 24import type XtextClient from '../xtext/XtextClient';
25 25
26import LintPanelStore from './LintPanelStore'; 26import LintPanelStore from './LintPanelStore';
27import SearchPanelStore from './SearchPanelStore'; 27import 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}