diff --git a/examples/src/sheets/main.ts b/examples/src/sheets/main.ts index ec4cf001e4b..9e8b7e6272d 100644 --- a/examples/src/sheets/main.ts +++ b/examples/src/sheets/main.ts @@ -85,6 +85,9 @@ univer.registerPlugin(UniverDataValidationPlugin); univer.registerPlugin(UniverSheetsDataValidationPlugin); univer.registerPlugin(UniverSheetsFindReplacePlugin); +// sheet condition formatting +univer.registerPlugin(UniverSheetsConditionalFormattingUIPlugin); + // create univer sheet instance univer.createUniverSheet(DEFAULT_WORKBOOK_DATA_DEMO); @@ -93,9 +96,6 @@ univer.createUniverSheet(DEFAULT_WORKBOOK_DATA_DEMO); // univer.__getInjector().get(IUniverInstanceService).disposeUnit(DEFAULT_WORKBOOK_DATA_DEMO.id); // }, 5000); -// sheet condition formatting -univer.registerPlugin(UniverSheetsConditionalFormattingUIPlugin); - declare global { interface Window { univer?: Univer; diff --git a/packages/core/src/services/plugin/plugin-holder.ts b/packages/core/src/services/plugin/plugin-holder.ts index ef01e2e7f44..b943a7499fc 100644 --- a/packages/core/src/services/plugin/plugin-holder.ts +++ b/packages/core/src/services/plugin/plugin-holder.ts @@ -26,12 +26,14 @@ import { type Plugin, type PluginCtor, PluginRegistry, PluginStore } from './plu export class PluginHolder extends Disposable { protected _started: boolean = false; + get started(): boolean { return this._started; } protected readonly _pluginRegistered = new Set(); protected readonly _pluginStore = new PluginStore(); protected readonly _pluginRegistry = new PluginRegistry(); constructor( + private readonly _immediateStart: boolean, @ILogService protected readonly _logService: ILogService, @Inject(Injector) protected readonly _injector: Injector, @Inject(LifecycleService) protected readonly _lifecycleService: LifecycleService, @@ -48,7 +50,7 @@ export class PluginHolder extends Disposable { this._pluginRegistry.removePlugins(); } - protected _registerPlugin>(pluginCtor: T, config?: ConstructorParameters[0]): void { + registerPlugin>(pluginCtor: T, config?: ConstructorParameters[0]): void { const { pluginName } = pluginCtor; if (this._pluginRegistered.has(pluginName)) { this._logService.warn('[PluginService]', `plugin ${pluginName} has already been registered. This registration will be ignored.`); @@ -58,21 +60,24 @@ export class PluginHolder extends Disposable { this._pluginRegistry.registerPlugin(pluginCtor, config); } - _start(): void { + start(): void { if (this._started) return; this._started = true; - this._flush(); + this.flush(); } - _flush(): void { + flush(): void { if (!this._started) return; const plugins = this._pluginRegistry.getRegisterPlugins().map(({ plugin, options }) => this._initPlugin(plugin, options)); this._pluginRegistry.removePlugins(); - this.disposeWithMe(this._lifecycleService.subscribeWithPrevious().subscribe((stage) => { + const lifecycleSubscription = this.disposeWithMe(this._lifecycleService.subscribeWithPrevious().subscribe((stage) => { this._pluginsRunLifecycle(plugins, stage); + if (stage === LifecycleStages.Steady) { + lifecycleSubscription.dispose(); + } })); } diff --git a/packages/core/src/services/plugin/plugin.service.ts b/packages/core/src/services/plugin/plugin.service.ts index e2190301348..9d29d2dbf32 100644 --- a/packages/core/src/services/plugin/plugin.service.ts +++ b/packages/core/src/services/plugin/plugin.service.ts @@ -14,11 +14,10 @@ * limitations under the License. */ +import type { IDisposable } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import type { UniverType } from '@univerjs/protocol'; import { type UnitType, UniverInstanceType } from '../../common/unit'; -import { LifecycleInitializerService, LifecycleService } from '../lifecycle/lifecycle.service'; -import { LifecycleStages } from '../lifecycle/lifecycle'; -import { ILogService } from '../log/log.service'; import { PluginHolder } from './plugin-holder'; import type { Plugin, PluginCtor } from './plugin'; @@ -27,42 +26,61 @@ const INIT_LAZY_PLUGINS_TIMEOUT = 200; /** * This service manages plugin registration. */ -export class PluginService extends PluginHolder { - private _pluginHoldersForTypes = new Map(); +export class PluginService implements IDisposable { + private readonly _pluginHolderForUniver: PluginHolder; + private readonly _pluginHoldersForTypes = new Map(); constructor( - @ILogService _logService: ILogService, - @Inject(Injector) _injector: Injector, - @Inject(LifecycleService) _lifecycleService: LifecycleService, - @Inject(LifecycleInitializerService) _lifecycleInitializerService: LifecycleInitializerService + @Inject(Injector) private readonly _injector: Injector ) { - super(_logService, _injector, _lifecycleService, _lifecycleInitializerService); + this._pluginHolderForUniver = this._injector.createInstance(PluginHolder, true); } - override dispose(): void { + dispose(): void { this._clearFlushLazyPluginsTimer(); - // Dispose all plugin holders including self. - super.dispose(); for (const holder of this._pluginHoldersForTypes.values()) { holder.dispose(); } + + this._pluginHolderForUniver.dispose(); } /** Register a plugin into univer. */ registerPlugin>(plugin: T, config?: ConstructorParameters[0]): void { this._assertPluginValid(plugin); + if (this._pluginHolderForUniver.started) { + this._scheduleInitPluginAfterStarted(); + } + const { type } = plugin; if (type === UniverInstanceType.UNIVER) { - return this._registerPlugin(plugin, config); + this._pluginHolderForUniver.registerPlugin(plugin, config); + } else { + // If it's type is for specific document, we should run them at specific time. + const holder = this._ensurePluginHolderForType(type); + holder.registerPlugin(plugin, config); } + } - // If it's type is for specific document, we should run them at specific time. + start(): void { + this._pluginHolderForUniver.start(); + } + + startPluginForType(type: UniverType): void { const holder = this._ensurePluginHolderForType(type); + holder.start(); + } - // @ts-ignore - holder._registerPlugin(plugin, config); + _ensurePluginHolderForType(type: UnitType): PluginHolder { + if (!this._pluginHoldersForTypes.has(type)) { + const pluginHolder = this._injector.createInstance(PluginHolder, false); + this._pluginHoldersForTypes.set(type, pluginHolder); + return pluginHolder; + } + + return this._pluginHoldersForTypes.get(type)!; } private _assertPluginValid(plugin: PluginCtor): void { @@ -77,44 +95,14 @@ export class PluginService extends PluginHolder { } } - protected override _registerPlugin>(pluginCtor: T, options?: ConstructorParameters[0]): void { - const { pluginName } = pluginCtor; - if (this._pluginRegistered.has(pluginName)) { - this._logService.warn('[PluginService]', `plugin ${pluginName} has already been registered. This registration will be ignored.`); - return; - } - - this._pluginRegistered.add(pluginName); - - if (this._started) { - this._pluginRegistry.registerPlugin(pluginCtor, options); - - // If Univer has already started, we should manually call onStarting for the plugin. - // We do that in an asynchronous way, because user may lazy load several plugins at the same time. - return this._scheduleInitPluginAfterStarted(); - } else { - // For plugins at Univer level. Plugins would be initialized immediately so they can register dependencies. - const pluginInstance: Plugin = this._injector.createInstance(pluginCtor, options); - this._pluginStore.addPlugin(pluginInstance); - this._pluginsRunLifecycle([pluginInstance], LifecycleStages.Starting); - } - } - - _ensurePluginHolderForType(type: UnitType): PluginHolder { - if (!this._pluginHoldersForTypes.has(type)) { - const pluginHolder = this._injector.createInstance(PluginHolder); - this._pluginHoldersForTypes.set(type, pluginHolder); - return pluginHolder; - } - - return this._pluginHoldersForTypes.get(type)!; - } - private _initLazyPluginsTimer?: number; private _scheduleInitPluginAfterStarted() { if (this._initLazyPluginsTimer === undefined) { this._initLazyPluginsTimer = setTimeout( - () => this._flushLazyPlugins(), + () => { + this._flushLazyPlugins(); + this._clearFlushLazyPluginsTimer(); + }, INIT_LAZY_PLUGINS_TIMEOUT ) as unknown as number; } @@ -128,10 +116,11 @@ export class PluginService extends PluginHolder { } private _flushLazyPlugins() { - this._flush(); - + this._pluginHolderForUniver.flush(); for (const [_, holder] of this._pluginHoldersForTypes) { - holder._flush(); + if (holder.started) { + holder.flush(); + } } } } diff --git a/packages/core/src/univer.ts b/packages/core/src/univer.ts index 1c4ac388d89..059bda5111e 100644 --- a/packages/core/src/univer.ts +++ b/packages/core/src/univer.ts @@ -111,6 +111,10 @@ export class Univer { return this._univerInstanceService.createUnit(UniverInstanceType.SLIDE, data); } + start(): void { + this._tryProgressToStart(); + } + private _init(injector: Injector): void { this._univerInstanceService.registerCtorForType(UniverInstanceType.SHEET, Workbook); this._univerInstanceService.registerCtorForType(UniverInstanceType.DOC, DocumentDataModel); @@ -122,11 +126,9 @@ export class Univer { this._tryProgressToStart(); if (!this._startedTypes.has(type)) { + this._pluginService.startPluginForType(type); this._startedTypes.add(type); - const pluginHolder = this._pluginService._ensurePluginHolderForType(type); - pluginHolder._start(); - const model = injector.createInstance(ctor, data); univerInstanceService.__addUnit(model); @@ -143,7 +145,7 @@ export class Univer { } private _tryProgressToStart(): void { - this._pluginService._start(); + this._pluginService.start(); } private _tryProgressToReady(): void {