Skip to content

Commit

Permalink
Merge pull request #515 from eclipsesource/features/lazy-loading
Browse files Browse the repository at this point in the history
Adapt to latest lazy loading of Monaco editor
  • Loading branch information
ivy-lli committed Mar 20, 2024
2 parents 1b87961 + ac8b42d commit cf4ae16
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 89 deletions.
12 changes: 11 additions & 1 deletion integration/eclipse/src/app.ts
@@ -1,7 +1,8 @@
import { DiagramLoader } from '@eclipse-glsp/client';

import { getParameters } from '@eclipse-glsp/ide';
import { MonacoEditorUtil } from '@axonivy/inscription-editor';
import { IvyBaseJsonrpcGLSPClient } from '@axonivy/process-editor';
import { getParameters } from '@eclipse-glsp/ide';
import { ApplicationIdProvider, GLSPClient, GLSPWebSocketProvider } from '@eclipse-glsp/protocol';
import { MessageConnection } from 'vscode-jsonrpc';

Expand All @@ -26,6 +27,7 @@ const theme = (urlParameters.theme as ThemeMode) ?? 'light';
const clientId = urlParameters.client || ApplicationIdProvider.get();
const widgetId = urlParameters.widget || clientId;
const showGrid = urlParameters.grid ? urlParameters.grid === 'true' : true;
const debug = urlParameters.debug ? urlParameters.debug === 'true' : false;
setWidgetId(widgetId);

const webSocketUrl = `ws://localhost:${port}/${id}`;
Expand All @@ -34,6 +36,7 @@ let glspClient: GLSPClient;
let container: Container;
const wsProvider = new GLSPWebSocketProvider(webSocketUrl);
wsProvider.listen({ onConnection: initialize, onReconnect: reconnect, logger: console });
initMonaco();

async function initialize(connectionProvider: MessageConnection, isReconnecting = false): Promise<void> {
glspClient = new IvyBaseJsonrpcGLSPClient({ id, connectionProvider });
Expand Down Expand Up @@ -66,3 +69,10 @@ async function reconnect(connectionProvider: MessageConnection): Promise<void> {
glspClient.stop();
initialize(connectionProvider, true /* isReconnecting */);
}

async function initMonaco(): Promise<void> {
// packaging with vite has it's own handling of workers so it can be properly accessed
// we therefore import the worker here and use that instead of the default mechanism
const worker = await import('monaco-editor/esm/vs/editor/editor.worker?worker');
MonacoEditorUtil.configureInstance({ theme, debug, worker: { workerConstructor: worker.default } });
}
12 changes: 1 addition & 11 deletions integration/eclipse/src/startup.ts
@@ -1,12 +1,10 @@
import { IVY_TYPES, ToolBar } from '@axonivy/process-editor';
import { EnableInscriptionAction } from '@axonivy/process-editor-inscription';
import { EnableViewportAction, ShowGridAction, SwitchThemeAction, ThemeMode, UpdatePaletteItems } from '@axonivy/process-editor-protocol';
import { EnableViewportAction, ShowGridAction, SwitchThemeAction, UpdatePaletteItems } from '@axonivy/process-editor-protocol';
import { EnableToolPaletteAction, GLSPActionDispatcher, IDiagramStartup, TYPES } from '@eclipse-glsp/client';
import { ContainerModule, inject, injectable } from 'inversify';
import { IvyDiagramOptions } from './di.config';

import { MonacoUtil } from '@axonivy/inscription-core';
import { MonacoEditorUtil } from '@axonivy/inscription-editor';
import './index.css';

@injectable()
Expand All @@ -32,16 +30,8 @@ export class EclipseDiagramStartup implements IDiagramStartup {
}

async postModelInitialization(): Promise<void> {
await this.initMonaco(this.options.theme);
this.actionDispatcher.dispatch(EnableInscriptionAction.create({}));
}

async initMonaco(theme: ThemeMode): Promise<void> {
const monaco = await import('monaco-editor/esm/vs/editor/editor.api');
const editorWorker = await import('monaco-editor/esm/vs/editor/editor.worker?worker');
await MonacoUtil.initStandalone(editorWorker.default);
await MonacoEditorUtil.configureInstance(monaco, theme);
}
}

export const ivyStartupDiagramModule = new ContainerModule(bind => {
Expand Down
90 changes: 74 additions & 16 deletions integration/standalone/index.html
@@ -1,18 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Inscription Editor for Axon Ivy Process Elements" />
<title>Process Editor</title>
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="sprotty" class="main-widget"></div>
<div id="inscription"></div>
<script type="module" src="/src/index.ts"></script>
</body>
</html>

<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Inscription Editor for Axon Ivy Process Elements" />
<title>Process Editor</title>
<style>
#root {
height: 100%;
}

/* from https://cssloaders.github.io/, licensed under MIT */
.loader {
width: 48px;
height: 48px;
border-radius: 50%;
position: relative;
top: 50%;
left: 50%;
animation: rotate 1s linear infinite;
}

.loader::before {
content: '';
box-sizing: border-box;
position: absolute;
inset: 0px;
border-radius: 50%;
border: 5px solid #a5a5a5;
animation: prixClipFix 2s linear infinite;
}

@keyframes rotate {
100% {
transform: rotate(360deg);
}
}

@keyframes prixClipFix {
0% {
clip-path: polygon(50% 50%, 0 0, 0 0, 0 0, 0 0, 0 0);
}

25% {
clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 0, 100% 0, 100% 0);
}

50% {
clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 100% 100%, 100% 100%);
}

75% {
clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 100%);
}

100% {
clip-path: polygon(50% 50%, 0 0, 100% 0, 100% 100%, 0 100%, 0 0);
}
}
</style>
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="sprotty" class="main-widget">
<div class="loader"></div>
</div>
<div id="inscription"></div>
<script type="module" src="/src/index.ts"></script>
</body>

</html>
10 changes: 10 additions & 0 deletions integration/standalone/src/app.ts
@@ -1,3 +1,4 @@
import { MonacoEditorUtil } from '@axonivy/inscription-editor';
import { IvyBaseJsonrpcGLSPClient, SwitchThemeActionHandler } from '@axonivy/process-editor';
import { ThemeMode } from '@axonivy/process-editor-protocol';
import { DiagramLoader, EditMode, GLSPActionDispatcher, GLSPWebSocketProvider, MessageAction, StatusAction } from '@eclipse-glsp/client';
Expand All @@ -20,6 +21,7 @@ const pid = parameters.get('pid') ?? '';
const sourceUri = parameters.get('file') ?? '';
const select = parameters.get('select');
const theme = (parameters.get('theme') as ThemeMode) ?? SwitchThemeActionHandler.prefsColorScheme();
const debug = parameters.has('debug', 'true');

const id = 'ivy-glsp-process';
const diagramType = 'ivy-glsp-process';
Expand All @@ -32,6 +34,7 @@ let glspClient: GLSPClient;
let container: Container;
const wsProvider = new GLSPWebSocketProvider(webSocketUrl);
wsProvider.listen({ onConnection: initialize, onReconnect: reconnect, logger: console });
initMonaco();

async function initialize(connectionProvider: MessageConnection, isReconnecting = false): Promise<void> {
glspClient = new IvyBaseJsonrpcGLSPClient({ id, connectionProvider });
Expand Down Expand Up @@ -73,3 +76,10 @@ async function reconnect(connectionProvider: MessageConnection): Promise<void> {
glspClient.stop();
initialize(connectionProvider, true /* isReconnecting */);
}

async function initMonaco(): Promise<void> {
// packaging with vite has it's own handling of workers so it can be properly accessed
// we therefore import the worker here and use that instead of the default mechanism
const worker = await import('monaco-editor/esm/vs/editor/editor.worker?worker');
MonacoEditorUtil.configureInstance({ theme, debug, worker: { workerConstructor: worker.default } });
}
12 changes: 1 addition & 11 deletions integration/standalone/src/startup.ts
@@ -1,5 +1,5 @@
import { EnableInscriptionAction } from '@axonivy/process-editor-inscription';
import { EnableViewportAction, SwitchThemeAction, ThemeMode, UpdatePaletteItems } from '@axonivy/process-editor-protocol';
import { EnableViewportAction, SwitchThemeAction, UpdatePaletteItems } from '@axonivy/process-editor-protocol';
import {
EnableToolPaletteAction,
GLSPActionDispatcher,
Expand All @@ -11,8 +11,6 @@ import {
import { ContainerModule, inject, injectable } from 'inversify';
import { IvyDiagramOptions } from './di.config';

import { MonacoUtil } from '@axonivy/inscription-core';
import { MonacoEditorUtil } from '@axonivy/inscription-editor';
import './index.css';

@injectable()
Expand All @@ -34,7 +32,6 @@ export class StandaloneDiagramStartup implements IDiagramStartup {
}

async postModelInitialization(): Promise<void> {
await this.initMonaco(this.options.theme);
this.actionDispatcher.dispatch(
EnableInscriptionAction.create({
connection: { server: this.options.inscriptionContext.server },
Expand All @@ -46,13 +43,6 @@ export class StandaloneDiagramStartup implements IDiagramStartup {
this.actionDispatcher.dispatch(SelectAction.create({ selectedElementsIDs: elementIds }));
}
}

async initMonaco(theme: ThemeMode): Promise<void> {
const monaco = await import('monaco-editor/esm/vs/editor/editor.api');
const editorWorker = await import('monaco-editor/esm/vs/editor/editor.worker?worker');
await MonacoUtil.initStandalone(editorWorker.default);
await MonacoEditorUtil.configureInstance(monaco, theme);
}
}

export const ivyStartupDiagramModule = new ContainerModule(bind => {
Expand Down
2 changes: 1 addition & 1 deletion packages/editor/package.json
Expand Up @@ -18,7 +18,7 @@
"bpmn"
],
"dependencies": {
"@axonivy/ui-icons": "~11.3.0-next.71",
"@axonivy/ui-icons": "~11.3.0-next.81",
"@axonivy/process-editor-protocol": "11.3.0-next",
"@eclipse-glsp/client": "~2.1.0",
"showdown": "^2.1.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/inscription/package.json
Expand Up @@ -10,9 +10,9 @@
"url": "https://github.com/axonivy/glsp-editor-client"
},
"dependencies": {
"@axonivy/inscription-core": "~11.3.0-next.1022",
"@axonivy/inscription-editor": "~11.3.0-next.1022",
"@axonivy/inscription-protocol": "~11.3.0-next.1022",
"@axonivy/inscription-core": "~11.3.0-next.1026",
"@axonivy/inscription-editor": "~11.3.0-next.1026",
"@axonivy/inscription-protocol": "~11.3.0-next.1026",
"@axonivy/process-editor": "11.3.0-next",
"@eclipse-glsp/client": "~2.1.0",
"react": "^18.2.0",
Expand Down
13 changes: 5 additions & 8 deletions packages/inscription/src/inscription/inscription-ui.tsx
@@ -1,4 +1,4 @@
import { InscriptionClientJsonRpc, IvyScriptLanguage, MonacoUtil } from '@axonivy/inscription-core';
import { InscriptionClientJsonRpc, IvyScriptLanguage } from '@axonivy/inscription-core';
import { ClientContextProvider, MonacoEditorUtil, ThemeContextProvider, initQueryClient } from '@axonivy/inscription-editor';
import { InscriptionClient, InscriptionContext } from '@axonivy/inscription-protocol';
import { SwitchThemeActionHandler } from '@axonivy/process-editor';
Expand All @@ -17,7 +17,6 @@ import {
} from '@eclipse-glsp/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { inject, injectable, optional, postConstruct } from 'inversify';
import * as reactMonaco from 'monaco-editor/esm/vs/editor/editor.api';
import React from 'react';
import { Root, createRoot } from 'react-dom/client';
import { OpenAction } from 'sprotty-protocol';
Expand Down Expand Up @@ -95,13 +94,13 @@ export class InscriptionUi extends AbstractUIExtension implements IActionHandler
});
}

async startInscriptionClient() {
async startInscriptionClient(): Promise<InscriptionClient> {
const model = this.selectionService.getModelRoot();
const webSocketAddress = this.action?.connection?.server ?? GArgument.getString(model, 'webSocket') ?? 'ws://localhost:8081/';
if (this.action?.connection?.ivyScript) {
await IvyScriptLanguage.startClient(this.action?.connection?.ivyScript);
IvyScriptLanguage.startClient(this.action?.connection?.ivyScript, MonacoEditorUtil.getInstance());
} else {
await IvyScriptLanguage.startWebSocketClient(webSocketAddress, Promise.resolve(true));
IvyScriptLanguage.startWebSocketClient(webSocketAddress, MonacoEditorUtil.getInstance());
}
let client: InscriptionClient;
if (this.action?.connection?.inscription) {
Expand Down Expand Up @@ -130,9 +129,7 @@ export class InscriptionUi extends AbstractUIExtension implements IActionHandler
}
if (SwitchThemeAction.is(action)) {
this.updateInscriptionUi();
MonacoUtil.monacoInitialized().then(() => {
reactMonaco.editor.defineTheme(MonacoEditorUtil.DEFAULT_THEME_NAME, MonacoEditorUtil.themeData(action.theme));
});
MonacoEditorUtil.setTheme(action.theme);
}
return;
}
Expand Down

0 comments on commit cf4ae16

Please sign in to comment.