diff --git a/src/controller/__tests__/layout.test.ts b/src/controller/__tests__/layout.test.ts index 18332d1bf..c44ff6ade 100644 --- a/src/controller/__tests__/layout.test.ts +++ b/src/controller/__tests__/layout.test.ts @@ -7,6 +7,14 @@ const layoutController = container.resolve(LayoutController); const layoutService = container.resolve(LayoutService); describe('The layout controller', () => { + test('Should support to listen to the Workbench did mount event', () => { + const mockFn = jest.fn(); + layoutService.onWorkbenchDidMount(mockFn); + layoutController.onWorkbenchDidMount(); + + expect(mockFn).toBeCalled(); + }); + test('Should support to execute onPaneSizeChange', () => { const original = layoutService.setPaneSize; const mockFn = jest.fn(); diff --git a/src/controller/layout.ts b/src/controller/layout.ts index 4c9fb0b59..10572e480 100644 --- a/src/controller/layout.ts +++ b/src/controller/layout.ts @@ -2,8 +2,10 @@ import 'reflect-metadata'; import { container, singleton } from 'tsyringe'; import { Controller } from 'mo/react/controller'; import { ILayoutService, LayoutService } from 'mo/services'; +import { LayoutEvents } from 'mo/model/workbench/layout'; export interface ILayoutController extends Partial { + onWorkbenchDidMount?: () => void; onPaneSizeChange?: (splitPanePos: number[]) => void; onHorizontalPaneSizeChange?: (horizontalSplitPanePos: number[]) => void; } @@ -26,4 +28,8 @@ export class LayoutController extends Controller implements ILayoutController { public onHorizontalPaneSizeChange = (horizontalSplitPanePos: number[]) => { this.layoutService.setHorizontalPaneSize(horizontalSplitPanePos); }; + + public onWorkbenchDidMount = () => { + this.layoutService.emit(LayoutEvents.OnWorkbenchDidMount); + }; } diff --git a/src/model/workbench/layout.ts b/src/model/workbench/layout.ts index 43d5ed506..d35f77777 100644 --- a/src/model/workbench/layout.ts +++ b/src/model/workbench/layout.ts @@ -8,6 +8,10 @@ export enum MenuBarMode { vertical = 'vertical', } +export enum LayoutEvents { + OnWorkbenchDidMount = 'workbench.didMount', +} + export interface ViewVisibility { hidden: boolean; } diff --git a/src/provider/create.ts b/src/provider/create.ts index beaaf8925..8921b1be1 100644 --- a/src/provider/create.ts +++ b/src/provider/create.ts @@ -14,7 +14,7 @@ export interface IConfigProps { defaultLocale?: string; } -namespace stanalone { +namespace standalone { let instance: InstanceService | null = null; /** @@ -37,12 +37,12 @@ namespace stanalone { } export default function create(config: IConfigProps) { - return stanalone.create(config); + return standalone.create(config); } /** * Do NOT call it in production, ONLY used for test cases */ export function clearInstance() { - stanalone.clearInstance(); + standalone.clearInstance(); } diff --git a/src/services/__tests__/layoutService.test.ts b/src/services/__tests__/layoutService.test.ts index 61a707342..b89df4415 100644 --- a/src/services/__tests__/layoutService.test.ts +++ b/src/services/__tests__/layoutService.test.ts @@ -1,5 +1,5 @@ import { ID_APP } from 'mo/common/id'; -import { MenuBarMode, Position } from 'mo/model/workbench/layout'; +import { LayoutEvents, MenuBarMode, Position } from 'mo/model/workbench/layout'; import 'reflect-metadata'; import { container } from 'tsyringe'; import { LayoutService } from '../workbench'; @@ -143,5 +143,14 @@ describe('The layout service', () => { layoutService.setAuxiliaryBar((pre) => !pre); expect(layoutService.getState().auxiliaryBar.hidden).toBe(true); }); + + test('Should support to listen to the Workbench did mount event', () => { + const mockFn = jest.fn(); + layoutService.onWorkbenchDidMount(mockFn); + + layoutService.emit(LayoutEvents.OnWorkbenchDidMount); + + expect(mockFn).toBeCalled(); + }); }); }); diff --git a/src/services/instanceService.tsx b/src/services/instanceService.tsx index ae3ea9f9e..82692c260 100644 --- a/src/services/instanceService.tsx +++ b/src/services/instanceService.tsx @@ -122,7 +122,11 @@ export default class InstanceService this.emit(InstanceHookKind.beforeLoad); molecule.extension.load(others); - molecule.monacoService.initWorkspace(molecule.layout.container!); + molecule.layout.onWorkbenchDidMount(() => { + molecule.monacoService.initWorkspace( + molecule.layout.container! + ); + }); this.rendered = true; } diff --git a/src/services/workbench/layoutService.ts b/src/services/workbench/layoutService.ts index c52c7dfe3..91beda3fa 100644 --- a/src/services/workbench/layoutService.ts +++ b/src/services/workbench/layoutService.ts @@ -6,6 +6,7 @@ import { Position, LayoutModel, MenuBarMode, + LayoutEvents, } from 'mo/model/workbench/layout'; import { MenuBarEvent } from 'mo/model/workbench/menuBar'; @@ -87,6 +88,11 @@ export interface ILayoutService extends Component { * Reset all layout data as default value */ reset(): void; + /** + * Listen to the workbench did mount event + * @param callback callback function + */ + onWorkbenchDidMount(callback: Function): void; } @singleton() @@ -101,6 +107,10 @@ export class LayoutService this.state = container.resolve(LayoutModel); } + public onWorkbenchDidMount(callback: Function): void { + this.subscribe(LayoutEvents.OnWorkbenchDidMount, callback); + } + public get container() { // Make sure to get the latest dom element. this._container = document.getElementById(ID_APP) || document.body; diff --git a/src/workbench/workbench.tsx b/src/workbench/workbench.tsx index fb8f8805a..5d43adf48 100644 --- a/src/workbench/workbench.tsx +++ b/src/workbench/workbench.tsx @@ -1,5 +1,5 @@ import 'reflect-metadata'; -import React from 'react'; +import React, { useEffect } from 'react'; import { container } from 'tsyringe'; import { @@ -60,6 +60,7 @@ export function WorkbenchView(props: IWorkbench & ILayout & ILayoutController) { sidebar, statusBar, onPaneSizeChange, + onWorkbenchDidMount, onHorizontalPaneSizeChange, splitPanePos, horizontalSplitPanePos, @@ -122,6 +123,11 @@ export function WorkbenchView(props: IWorkbench & ILayout & ILayoutController) { hideStatusBar ); + useEffect(() => { + // call onWorkbenchDidMount after the first render + onWorkbenchDidMount?.(); + }, []); + return (
diff --git a/stories/workbench/0-Workbench.stories.tsx b/stories/workbench/0-Workbench.stories.tsx index ecb9519e2..b835da108 100644 --- a/stories/workbench/0-Workbench.stories.tsx +++ b/stories/workbench/0-Workbench.stories.tsx @@ -13,17 +13,35 @@ moInstance.onBeforeInit(() => { molecule.builtin.inactiveModule('activityBarData'); }); -export const IDEDemo = () => moInstance.render(); - -IDEDemo.story = { - name: 'Workbench', +export default { + title: 'Workbench', }; -if (module.hot) { - module.hot.accept(); -} +export const NormalWorkbench = () => moInstance.render(); -export default { - title: 'Workbench', - component: IDEDemo, +export const EmbeddedWorkbench = () => { + return ( +
+

+ Embedded +

+
+ {moInstance.render()} +
+
+ ); };