diff --git a/examples/src/sheets-multi/main.tsx b/examples/src/sheets-multi/main.tsx index bc9aaf9031..05b2538cdc 100644 --- a/examples/src/sheets-multi/main.tsx +++ b/examples/src/sheets-multi/main.tsx @@ -21,7 +21,6 @@ import { LocaleType, LogLevel, Tools, Univer } from '@univerjs/core'; import { defaultTheme } from '@univerjs/design'; import { UniverDocsPlugin } from '@univerjs/docs'; import { UniverDocsUIPlugin } from '@univerjs/docs-ui'; -import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'; import { UniverRenderEnginePlugin } from '@univerjs/engine-render'; import { UniverSheetsPlugin } from '@univerjs/sheets'; import { UniverSheetsFormulaPlugin } from '@univerjs/sheets-formula'; @@ -63,7 +62,6 @@ function factory(id: string) { // sheet feature plugins univer.registerPlugin(UniverSheetsNumfmtPlugin); - univer.registerPlugin(UniverFormulaEnginePlugin); univer.registerPlugin(UniverSheetsFormulaPlugin); // create univer sheet instance diff --git a/examples/src/sheets/main.ts b/examples/src/sheets/main.ts index 7942f9f2a4..b92babddd9 100644 --- a/examples/src/sheets/main.ts +++ b/examples/src/sheets/main.ts @@ -20,7 +20,6 @@ import { UniverDocsPlugin } from '@univerjs/docs'; import { UniverDocsUIPlugin } from '@univerjs/docs-ui'; import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'; import { UniverRenderEnginePlugin } from '@univerjs/engine-render'; -import { UniverFindReplacePlugin } from '@univerjs/find-replace'; import { UniverSheetsFilterPlugin } from '@univerjs/sheets-filter'; import type { IUniverRPCMainThreadConfig } from '@univerjs/rpc'; import { UniverRPCMainThreadPlugin } from '@univerjs/rpc'; @@ -38,13 +37,9 @@ import { UniverSheetsThreadCommentPlugin } from '@univerjs/sheets-thread-comment import { UniverDebuggerPlugin } from '@univerjs/debugger'; import { UniverSheetsHyperLinkUIPlugin } from '@univerjs/sheets-hyper-link-ui'; import { FUniver } from '@univerjs/facade'; -import { IThreadCommentMentionDataService } from '@univerjs/thread-comment-ui'; -import { UniverDrawingPlugin } from '@univerjs/drawing'; -import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui'; -import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing'; +import { IThreadCommentMentionDataService, UniverThreadCommentUIPlugin } from '@univerjs/thread-comment-ui'; import { UniverSheetsDrawingUIPlugin } from '@univerjs/sheets-drawing-ui'; -import { UniverDocsDrawingPlugin } from '@univerjs/docs-drawing'; import { DEFAULT_WORKBOOK_DATA_DEMO } from '../data/sheets/demo/default-workbook-data-demo'; import { enUS, ruRU, zhCN } from '../locales'; @@ -74,8 +69,6 @@ univer.registerPlugin(UniverUIPlugin, { container: 'app', }); -univer.registerPlugin(UniverDrawingPlugin); - univer.registerPlugin(UniverDocsUIPlugin); univer.registerPlugin(UniverSheetsPlugin, { @@ -98,7 +91,6 @@ univer.registerPlugin(UniverRPCMainThreadPlugin, { univer.registerPlugin(UniverSheetsHyperLinkUIPlugin); // find replace -univer.registerPlugin(UniverFindReplacePlugin); univer.registerPlugin(UniverSheetsFindReplacePlugin); // data validation @@ -112,9 +104,6 @@ univer.registerPlugin(UniverSheetsFilterPlugin); univer.registerPlugin(UniverSheetsConditionalFormattingUIPlugin); // drawing -univer.registerPlugin(UniverDocsDrawingPlugin); -univer.registerPlugin(UniverSheetsDrawingPlugin); -univer.registerPlugin(UniverDrawingUIPlugin); univer.registerPlugin(UniverSheetsDrawingUIPlugin); // create univer sheet instance @@ -151,9 +140,10 @@ class CustomMentionDataService implements IThreadCommentMentionDataService { } } -univer.registerPlugin(UniverSheetsThreadCommentPlugin, { +univer.registerPlugin(UniverThreadCommentUIPlugin, { overrides: [[IThreadCommentMentionDataService, { useClass: CustomMentionDataService }]], }); +univer.registerPlugin(UniverSheetsThreadCommentPlugin); // debugger plugin univer.registerPlugin(UniverDebuggerPlugin); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 13c44cb236..312ba35b13 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,7 +20,6 @@ export { DEFAULT_DOCUMENT_SUB_COMPONENT_ID } from './docs/data-model/subdocument export { type UnitType, UnitModel, UniverInstanceType } from './common/unit'; export { Registry, RegistryAsMap } from './common/registry'; export { Univer } from './univer'; -export { PluginHolder } from './services/plugin/plugin-holder'; export { shallowEqual, isRangesEqual, isUnitRangesEqual } from './common/equal'; export { isNumeric, isSafeNumeric } from './common/number'; export { isBooleanString } from './common/boolean'; @@ -55,7 +54,7 @@ export type { JSONXActions, JSONXPath } from './docs/data-model/json-x/json-x'; export { replaceInDocumentBody } from './docs/data-model/replacement'; export * from './observer'; export { Plugin } from './services/plugin/plugin'; -export { PluginService } from './services/plugin/plugin.service'; +export { PluginService, DependentOn } from './services/plugin/plugin.service'; export { type CommandListener, CommandService, diff --git a/packages/core/src/services/plugin/plugin-holder.ts b/packages/core/src/services/plugin/plugin-holder.ts deleted file mode 100644 index 1424347174..0000000000 --- a/packages/core/src/services/plugin/plugin-holder.ts +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright 2023-present DreamNum Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* eslint-disable ts/no-explicit-any */ - -import type { Ctor } from '@wendellhu/redi'; -import { Inject, Injector } from '@wendellhu/redi'; - -import { finalize } from 'rxjs'; -import { LifecycleStages } from '../lifecycle/lifecycle'; -import { LifecycleInitializerService, LifecycleService } from '../lifecycle/lifecycle.service'; -import { Disposable } from '../../shared/lifecycle'; -import { ILogService } from '../log/log.service'; -import { type Plugin, type PluginCtor, PluginRegistry, PluginStore } from './plugin'; - -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( - @ILogService protected readonly _logService: ILogService, - @Inject(Injector) protected readonly _injector: Injector, - @Inject(LifecycleService) protected readonly _lifecycleService: LifecycleService, - @Inject(LifecycleInitializerService) protected readonly _lifecycleInitializerService: LifecycleInitializerService - ) { - super(); - } - - override dispose(): void { - super.dispose(); - - this._pluginStore.forEachPlugin((plugin) => plugin.dispose()); - this._pluginStore.removePlugins(); - this._pluginRegistry.removePlugins(); - this._pluginRegistered.clear(); - } - - 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.`); - return; - } - - this._pluginRegistered.add(pluginName); - this._pluginRegistry.registerPlugin(pluginCtor, config); - } - - start(): void { - if (this._started) return; - this._started = true; - - this.flush(); - } - - flush(): void { - if (!this._started) return; - - const plugins = this._pluginRegistry.getRegisterPlugins().map(({ plugin, options }) => this._initPlugin(plugin, options)); - this._pluginRegistry.removePlugins(); - - const subscription = this.disposeWithMe(this._lifecycleService.subscribeWithPrevious() - // It has to been async because the finalize may execute synchronously after we - // make the subscription. For example, the lifecycle service is already in stage "steady". - .pipe(finalize(() => { Promise.resolve().then(() => subscription.dispose()); })) - .subscribe((stage) => { this._pluginsRunLifecycle(plugins, stage); })); - } - - protected _pluginsRunLifecycle(plugins: Plugin[], lifecycle: LifecycleStages): void { - plugins.forEach((p) => { - switch (lifecycle) { - case LifecycleStages.Starting: - p.onStarting(this._injector); - break; - case LifecycleStages.Ready: - p.onReady(); - break; - case LifecycleStages.Rendered: - p.onRendered(); - break; - case LifecycleStages.Steady: - p.onSteady(); - break; - } - }); - - this._lifecycleInitializerService.initModulesOnStage(lifecycle); - } - - protected _initPlugin(plugin: PluginCtor, options: any): Plugin { - const pluginInstance: Plugin = this._injector.createInstance(plugin as unknown as Ctor, options); - return pluginInstance; - } -} diff --git a/packages/core/src/services/plugin/plugin.service.ts b/packages/core/src/services/plugin/plugin.service.ts index 3d6abba425..4116cb7599 100644 --- a/packages/core/src/services/plugin/plugin.service.ts +++ b/packages/core/src/services/plugin/plugin.service.ts @@ -14,25 +14,53 @@ * limitations under the License. */ -import type { IDisposable } from '@wendellhu/redi'; +import type { Ctor, IDisposable } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { finalize } from 'rxjs'; + +import { Disposable } from '../../shared/lifecycle'; import { type UnitType, UniverInstanceType } from '../../common/unit'; -import { PluginHolder } from './plugin-holder'; -import type { Plugin, PluginCtor } from './plugin'; +import { LifecycleStages } from '../lifecycle/lifecycle'; +import { LifecycleInitializerService, LifecycleService } from '../lifecycle/lifecycle.service'; +import { ILogService } from '../log/log.service'; +import { DependentOnSymbol, type Plugin, type PluginCtor, PluginRegistry, PluginStore } from './plugin'; const INIT_LAZY_PLUGINS_TIMEOUT = 4; +/** + * Use this decorator to declare dependencies among plugins. If a dependent plugin is not registered yet, + * Univer will automatically register it with no configuration. + * + * For example: + * + * ```ts + * ⁣@DependentOn(UniverDrawingPlugin, UniverDrawingUIPlugin, UniverSheetsDrawingPlugin) + * export class UniverSheetsDrawingUIPlugin extends Plugin { + * } + * ``` + */ +export function DependentOn(...plugins: PluginCtor[]) { + return function (target: PluginCtor) { + target[DependentOnSymbol] = plugins; + }; +} + /** * This service manages plugin registration. */ export class PluginService implements IDisposable { private readonly _pluginHolderForUniver: PluginHolder; private readonly _pluginHoldersForTypes = new Map(); + private readonly _seenPlugins = new Set(); constructor( @Inject(Injector) private readonly _injector: Injector ) { - this._pluginHolderForUniver = this._injector.createInstance(PluginHolder); + this._pluginHolderForUniver = this._injector.createInstance(PluginHolder, + this._checkPluginSeen.bind(this), + this._immediateInitPlugin.bind(this) + ); + this._pluginHolderForUniver.start(); } @@ -47,19 +75,18 @@ export class PluginService implements IDisposable { } /** Register a plugin into univer. */ - registerPlugin>(plugin: T, config?: ConstructorParameters[0]): void { - this._assertPluginValid(plugin); - + registerPlugin(ctor: T, config?: ConstructorParameters[0]): void { + this._assertPluginValid(ctor); this._scheduleInitPlugin(); - const { type } = plugin; + const { type } = ctor; if (type === UniverInstanceType.UNIVER_UNKNOWN) { - this._pluginHolderForUniver.registerPlugin(plugin, config); + this._pluginHolderForUniver.register(ctor, config); this._pluginHolderForUniver.flush(); } 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); + holder.register(ctor, config); } } @@ -68,9 +95,12 @@ export class PluginService implements IDisposable { holder.start(); } - _ensurePluginHolderForType(type: UnitType): PluginHolder { + private _ensurePluginHolderForType(type: UnitType): PluginHolder { if (!this._pluginHoldersForTypes.has(type)) { - const pluginHolder = this._injector.createInstance(PluginHolder); + const pluginHolder = this._injector.createInstance(PluginHolder, + this._checkPluginSeen.bind(this), + this._immediateInitPlugin.bind(this) + ); this._pluginHoldersForTypes.set(type, pluginHolder); return pluginHolder; } @@ -78,16 +108,33 @@ export class PluginService implements IDisposable { return this._pluginHoldersForTypes.get(type)!; } - private _assertPluginValid(plugin: PluginCtor): void { - const { type, pluginName } = plugin; + private _immediateInitPlugin(ctor: PluginCtor): void { + this._seenPlugins.add(ctor.pluginName); + + const holder = this._ensurePluginHolderForType(ctor.type); + holder.immediateInitPlugin(ctor); + } + + private _checkPluginSeen(ctor: PluginCtor): boolean { + return this._seenPlugins.has(ctor.pluginName); + } + + private _assertPluginValid(ctor: PluginCtor): void { + const { type, pluginName } = ctor; if (type === UniverInstanceType.UNRECOGNIZED) { - throw new Error(`[PluginService]: invalid plugin type for ${plugin}. Please assign a "type" to your plugin.`); + throw new Error(`[PluginService]: invalid plugin type for ${ctor}. Please assign a "type" to your plugin.`); } if (pluginName === '') { - throw new Error(`[PluginService]: no plugin name for ${plugin}. Please assign a "pluginName" to your plugin.`); + throw new Error(`[PluginService]: no plugin name for ${ctor}. Please assign a "pluginName" to your plugin.`); } + + if (this._seenPlugins.has(pluginName)) { + throw new Error(`[PluginService]: duplicate plugin name for "${pluginName}".`); + } + + this._seenPlugins.add(ctor.pluginName); } private _flushTimer?: number; @@ -123,3 +170,118 @@ export class PluginService implements IDisposable { } } } + +export class PluginHolder extends Disposable { + protected _started: boolean = false; + get started(): boolean { return this._started; } + + /** Plugin constructors waiting to be initialized. */ + protected readonly _pluginRegistry = new PluginRegistry(); + /** Stores initialized plugin instances. */ + protected readonly _pluginStore = new PluginStore(); + + constructor( + private _checkPluginRegistered: (pluginCtor: PluginCtor) => boolean, + private _registerPlugin: (plugin: T, config?: ConstructorParameters[0]) => void, + @ILogService protected readonly _logService: ILogService, + @Inject(Injector) protected readonly _injector: Injector, + @Inject(LifecycleService) protected readonly _lifecycleService: LifecycleService, + @Inject(LifecycleInitializerService) protected readonly _lifecycleInitializerService: LifecycleInitializerService + ) { + super(); + } + + override dispose(): void { + super.dispose(); + + this._pluginStore.forEachPlugin((plugin) => plugin.dispose()); + this._pluginStore.removePlugins(); + + this._pluginRegistry.removePlugins(); + } + + register>(pluginCtor: T, config?: ConstructorParameters[0]): void { + this._pluginRegistry.registerPlugin(pluginCtor, config); + } + + immediateInitPlugin(plugin: PluginCtor): void { + const p = this._initPlugin(plugin, undefined); + this._pluginsRunLifecycle([p]); + } + + start(): void { + if (this._started) return; + this._started = true; + + this.flush(); + } + + flush(): void { + if (!this._started) { + return; + }; + + const plugins = this._pluginRegistry.getRegisterPlugins().map(({ plugin, options }) => this._initPlugin(plugin, options)); + this._pluginsRunLifecycle(plugins); + this._pluginRegistry.removePlugins(); + } + + // eslint-disable-next-line ts/no-explicit-any + private _initPlugin(plugin: PluginCtor, options: any): Plugin { + const dependents = plugin[DependentOnSymbol]; + if (dependents) { + const exhaustUnregisteredDependents = () => { + const NotRegistered = dependents.find((d) => !this._checkPluginRegistered(d)); + if (NotRegistered) { + this._logService.warn( + '[PluginService]', + `plugin "${plugin.pluginName}" depends on "${NotRegistered.pluginName}" which is not registered. Univer will automatically register it with default configuration.` + ); + + this._registerPlugin(NotRegistered, undefined); + return true; + } + + return false; + }; + + while (exhaustUnregisteredDependents()) { + continue; + } + } + + // eslint-disable-next-line ts/no-explicit-any + const pluginInstance: Plugin = this._injector.createInstance(plugin as unknown as Ctor, options); + this._pluginStore.addPlugin(pluginInstance); + + return pluginInstance; + } + + protected _pluginsRunLifecycle(plugins: Plugin[]): void { + const run = (lifecycle: LifecycleStages) => { + plugins.forEach((p) => { + switch (lifecycle) { + case LifecycleStages.Starting: + p.onStarting(this._injector); + break; + case LifecycleStages.Ready: + p.onReady(); + break; + case LifecycleStages.Rendered: + p.onRendered(); + break; + case LifecycleStages.Steady: + p.onSteady(); + break; + } + this._lifecycleInitializerService.initModulesOnStage(lifecycle); + }); + }; + + const subscription = this.disposeWithMe(this._lifecycleService.subscribeWithPrevious() + // It has to been async because the finalize may execute synchronously after we + // make the subscription. For example, the lifecycle service is already in stage "steady". + .pipe(finalize(() => { Promise.resolve().then(() => subscription.dispose()); })) + .subscribe((stage) => { run(stage); })); + } +} diff --git a/packages/core/src/services/plugin/plugin.ts b/packages/core/src/services/plugin/plugin.ts index 2accf2f527..e568324f6c 100644 --- a/packages/core/src/services/plugin/plugin.ts +++ b/packages/core/src/services/plugin/plugin.ts @@ -18,7 +18,13 @@ import type { Ctor, Injector } from '@wendellhu/redi'; import { Disposable } from '../../shared'; import { UniverInstanceType } from '../../common/unit'; -export type PluginCtor = Ctor & { type: UniverInstanceType; pluginName: string }; +export const DependentOnSymbol = Symbol('DependentOn'); + +export type PluginCtor = Ctor & { + type: UniverInstanceType; + pluginName: string; + [DependentOnSymbol]?: PluginCtor[]; +}; /** * Plug-in base class, all plug-ins must inherit from this base class. Provide basic methods. @@ -30,7 +36,8 @@ export abstract class Plugin extends Disposable { protected abstract _injector: Injector; - onStarting(_injector: Injector): void { + // eslint-disable-next-line unused-imports/no-unused-vars + onStarting(injector: Injector): void { // empty } diff --git a/packages/data-validation/src/plugin.ts b/packages/data-validation/src/plugin.ts index 5bf651022e..d9af8e6c77 100644 --- a/packages/data-validation/src/plugin.ts +++ b/packages/data-validation/src/plugin.ts @@ -24,7 +24,7 @@ import { AddDataValidationMutation, RemoveDataValidationMutation, UpdateDataVali import { DataValidationResourceController } from './controllers/dv-resource.controller'; import { DataValidationSheetController } from './controllers/dv-sheet.controller'; -const PLUGIN_NAME = 'data-validation'; +const PLUGIN_NAME = 'UNIVER_DATA_VALIDATION_PLUGIN'; export class UniverDataValidationPlugin extends Plugin { static override pluginName = PLUGIN_NAME; diff --git a/packages/engine-render/src/render-engine.ts b/packages/engine-render/src/render-engine.ts index 9bedccbc95..e8f60f8259 100644 --- a/packages/engine-render/src/render-engine.ts +++ b/packages/engine-render/src/render-engine.ts @@ -25,7 +25,7 @@ import { IRenderManagerService, RenderManagerService } from './render-manager/re */ export const IRenderingEngine = createIdentifier('univer.render-engine'); -const PLUGIN_NAME = 'render-engine'; +const PLUGIN_NAME = 'RENDER_ENGINE_PLUGIN'; export class UniverRenderEnginePlugin extends Plugin { static override pluginName = PLUGIN_NAME; diff --git a/packages/facade/src/apis/facade.ts b/packages/facade/src/apis/facade.ts index 74b9e41265..22070e30b8 100644 --- a/packages/facade/src/apis/facade.ts +++ b/packages/facade/src/apis/facade.ts @@ -288,6 +288,8 @@ export class FUniver { }); } + // #endregion + /** * Execute command * @param id Command id @@ -368,6 +370,4 @@ export class FUniver { ); }, 10); } - - // @endregion } diff --git a/packages/sheets-data-validation/src/plugin.ts b/packages/sheets-data-validation/src/plugin.ts index 5bc8dba5d0..c89a99692d 100644 --- a/packages/sheets-data-validation/src/plugin.ts +++ b/packages/sheets-data-validation/src/plugin.ts @@ -14,8 +14,11 @@ * limitations under the License. */ -import { ICommandService, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, ICommandService, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import { type Dependency, Inject, Injector } from '@wendellhu/redi'; +import { UniverDataValidationPlugin } from '@univerjs/data-validation'; +import { UniverSheetsPlugin } from '@univerjs/sheets'; +import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui'; import type { IUniverSheetsDataValidation } from './controllers/dv-render.controller'; import { DataValidationRenderController, DefaultSheetsDataValidation } from './controllers/dv-render.controller'; import { DataValidationController } from './controllers/dv.controller'; @@ -37,6 +40,7 @@ import { DataValidationPanelService } from './services/data-validation-panel.ser import { DataValidationFormulaController } from './controllers/dv-formula.controller'; import { DataValidationPermissionController } from './controllers/dv-permission.controller'; +@DependentOn(UniverDataValidationPlugin, UniverSheetsPlugin, UniverSheetsUIPlugin) export class UniverSheetsDataValidationPlugin extends Plugin { static override pluginName = DATA_VALIDATION_PLUGIN_NAME; static override type = UniverInstanceType.UNIVER_SHEET; diff --git a/packages/sheets-drawing-ui/src/plugin.ts b/packages/sheets-drawing-ui/src/plugin.ts index 4b3821cec9..4adc8c6e79 100644 --- a/packages/sheets-drawing-ui/src/plugin.ts +++ b/packages/sheets-drawing-ui/src/plugin.ts @@ -14,9 +14,12 @@ * limitations under the License. */ -import { LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverDrawingUIPlugin } from '@univerjs/drawing-ui'; +import { UniverSheetsDrawingPlugin } from '@univerjs/sheets-drawing'; +import { UniverDrawingPlugin } from '@univerjs/drawing'; import { DrawingPopupMenuController } from './controllers/drawing-popup-menu.controller'; import { SheetDrawingUpdateController } from './controllers/sheet-drawing-update.controller'; import type { IUniverSheetsDrawingConfig } from './controllers/sheet-drawing.controller'; @@ -24,8 +27,9 @@ import { DefaultSheetsDrawingConfig, SheetDrawingUIController } from './controll import { SheetDrawingTransformAffectedController } from './controllers/sheet-drawing-transform-affected.controller'; import { SheetCanvasFloatDomManagerService } from './services/canvas-float-dom-manager.service'; -const PLUGIN_NAME = 'SHEETS_IMAGE_UI_PLUGIN'; +const PLUGIN_NAME = 'SHEET_IMAGE_UI_PLUGIN'; +@DependentOn(UniverDrawingPlugin, UniverDrawingUIPlugin, UniverSheetsDrawingPlugin) export class UniverSheetsDrawingUIPlugin extends Plugin { static override type = UniverInstanceType.UNIVER_SHEET; static override pluginName = PLUGIN_NAME; diff --git a/packages/sheets-drawing/src/plugin.ts b/packages/sheets-drawing/src/plugin.ts index 5b2e755931..a5ab69c5b7 100644 --- a/packages/sheets-drawing/src/plugin.ts +++ b/packages/sheets-drawing/src/plugin.ts @@ -25,6 +25,7 @@ export class UniverSheetsDrawingPlugin extends Plugin { static override type = UniverInstanceType.UNIVER_SHEET; constructor( + private readonly _config: unknown, @Inject(Injector) override readonly _injector: Injector ) { super(); diff --git a/packages/sheets-filter-ui/src/plugin.ts b/packages/sheets-filter-ui/src/plugin.ts index aa43d96412..dd983c577c 100644 --- a/packages/sheets-filter-ui/src/plugin.ts +++ b/packages/sheets-filter-ui/src/plugin.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -import { LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverSheetsFilterPlugin } from '@univerjs/sheets-filter'; import type { IUniverSheetsFilterUIConfig } from './controllers/sheets-filter-ui.controller'; import { DefaultSheetFilterUiConfig, SheetsFilterUIController } from './controllers/sheets-filter-ui.controller'; @@ -25,6 +26,7 @@ import { SheetsFilterPermissionController } from './controllers/sheets-filter-pe const NAME = 'SHEET_FILTER_UI_PLUGIN'; +@DependentOn(UniverSheetsFilterPlugin) export class UniverSheetsFilterUIPlugin extends Plugin { static override type = UniverInstanceType.UNIVER_SHEET; static override pluginName = NAME; diff --git a/packages/sheets-find-replace/src/plugin.ts b/packages/sheets-find-replace/src/plugin.ts index 477a9824c9..e193de6dc4 100644 --- a/packages/sheets-find-replace/src/plugin.ts +++ b/packages/sheets-find-replace/src/plugin.ts @@ -14,26 +14,25 @@ * limitations under the License. */ -import { Plugin, PluginService, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, Plugin, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; import { UniverFindReplacePlugin } from '@univerjs/find-replace'; +import { UniverSheetsPlugin } from '@univerjs/sheets'; import { SheetsFindReplaceController } from './controllers/sheet-find-replace.controller'; const NAME = 'SHEET_FIND_REPLACE_PLUGIN'; +@DependentOn(UniverSheetsPlugin, UniverSheetsPlugin, UniverFindReplacePlugin) export class UniverSheetsFindReplacePlugin extends Plugin { static override pluginName = NAME; static override type = UniverInstanceType.UNIVER_SHEET; constructor( _config: unknown, - @Inject(Injector) protected readonly _injector: Injector, - @Inject(PluginService) private readonly _pluginService: PluginService + @Inject(Injector) protected readonly _injector: Injector ) { super(); - - this._pluginService.registerPlugin(UniverFindReplacePlugin); } override onStarting(injector: Injector): void { diff --git a/packages/sheets-formula/src/formula-ui-plugin.ts b/packages/sheets-formula/src/formula-ui-plugin.ts index 41552f99ab..267b771186 100644 --- a/packages/sheets-formula/src/formula-ui-plugin.ts +++ b/packages/sheets-formula/src/formula-ui-plugin.ts @@ -14,10 +14,11 @@ * limitations under the License. */ -import { LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'; import { FORMULA_UI_PLUGIN_NAME } from './common/plugin-name'; import { ActiveDirtyController } from './controllers/active-dirty.controller'; import { ArrayFormulaDisplayController } from './controllers/array-formula-display.controller'; @@ -46,6 +47,7 @@ import { FormulaRenderController } from './controllers/formula-render.controller /** * The configuration of the formula UI plugin. */ +@DependentOn(UniverFormulaEnginePlugin) export class UniverSheetsFormulaPlugin extends Plugin { static override pluginName = FORMULA_UI_PLUGIN_NAME; static override type = UniverInstanceType.UNIVER_SHEET; diff --git a/packages/sheets-hyper-link-ui/src/controllers/auto-fill.controller.ts b/packages/sheets-hyper-link-ui/src/controllers/auto-fill.controller.ts index 8bc011a254..b3b69ff585 100644 --- a/packages/sheets-hyper-link-ui/src/controllers/auto-fill.controller.ts +++ b/packages/sheets-hyper-link-ui/src/controllers/auto-fill.controller.ts @@ -20,7 +20,7 @@ import { AddHyperLinkMutation, HyperLinkModel, RemoveHyperLinkMutation } from '@ import type { IAutoFillLocation, ISheetAutoFillHook } from '@univerjs/sheets-ui'; import { APPLY_TYPE, getAutoFillRepeatRange, IAutoFillService, virtualizeDiscreteRanges } from '@univerjs/sheets-ui'; import { Inject } from '@wendellhu/redi'; -import { SHEETS_HYPER_LINK_UI_PLUGIN } from '../types/const'; +import { SHEET_HYPER_LINK_UI_PLUGIN } from '../types/const'; @OnLifecycle(LifecycleStages.Ready, SheetsHyperLinkAutoFillController) export class SheetsHyperLinkAutoFillController extends Disposable { @@ -145,7 +145,7 @@ export class SheetsHyperLinkAutoFillController extends Disposable { }; }; const hook: ISheetAutoFillHook = { - id: SHEETS_HYPER_LINK_UI_PLUGIN, + id: SHEET_HYPER_LINK_UI_PLUGIN, onFillData: (location, direction, applyType) => { if ( applyType === APPLY_TYPE.COPY || diff --git a/packages/sheets-hyper-link-ui/src/controllers/copy-paste.controller.ts b/packages/sheets-hyper-link-ui/src/controllers/copy-paste.controller.ts index d8022e1f9e..d238417348 100644 --- a/packages/sheets-hyper-link-ui/src/controllers/copy-paste.controller.ts +++ b/packages/sheets-hyper-link-ui/src/controllers/copy-paste.controller.ts @@ -21,7 +21,7 @@ import type { IDiscreteRange, ISheetDiscreteRangeLocation } from '@univerjs/shee import { COPY_TYPE, getRepeatRange, ISheetClipboardService, PREDEFINED_HOOK_NAME, rangeToDiscreteRange, virtualizeDiscreteRanges } from '@univerjs/sheets-ui'; import { Inject, Injector } from '@wendellhu/redi'; import { SPECIAL_PASTE_FORMULA } from '@univerjs/sheets-formula'; -import { SHEETS_HYPER_LINK_UI_PLUGIN } from '../types/const'; +import { SHEET_HYPER_LINK_UI_PLUGIN } from '../types/const'; import { isLegalLink, serializeUrl } from '../common/util'; import { SheetsHyperLinkResolverService } from '../services/resolver.service'; @@ -46,7 +46,7 @@ export class SheetsHyperLinkCopyPasteController extends Disposable { // eslint-disable-next-line max-lines-per-function private _initCopyPaste() { this._sheetClipboardService.addClipboardHook({ - id: SHEETS_HYPER_LINK_UI_PLUGIN, + id: SHEET_HYPER_LINK_UI_PLUGIN, onBeforeCopy: (unitId, subUnitId, range) => this._collect(unitId, subUnitId, range), onPasteCells: (pasteFrom, pasteTo, data, payload) => { const { copyType = COPY_TYPE.COPY, pasteType } = payload; diff --git a/packages/sheets-hyper-link-ui/src/plugin.ts b/packages/sheets-hyper-link-ui/src/plugin.ts index 2506d5366f..dc55350c29 100644 --- a/packages/sheets-hyper-link-ui/src/plugin.ts +++ b/packages/sheets-hyper-link-ui/src/plugin.ts @@ -16,7 +16,7 @@ import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; -import { UniverInstanceType } from '@univerjs/core'; +import { DependentOn, Plugin, UniverInstanceType } from '@univerjs/core'; import { UniverSheetsHyperLinkPlugin } from '@univerjs/sheets-hyper-link'; import { SheetsHyperLinkRemoveSheetController } from './controllers/remove-sheet.controller'; import { SheetsHyperLinkRefRangeController } from './controllers/ref-range.controller'; @@ -27,25 +27,25 @@ import { SheetHyperLinkSetRangeController } from './controllers/set-range.contro import { SheetsHyperLinkPopupController } from './controllers/popup.controller'; import type { IUniverSheetsHyperLinkUIConfig } from './controllers/ui.controller'; import { SheetsHyperLinkUIController } from './controllers/ui.controller'; -import { SHEETS_HYPER_LINK_UI_PLUGIN } from './types/const'; +import { SHEET_HYPER_LINK_UI_PLUGIN } from './types/const'; import { SheetsHyperLinkAutoFillController } from './controllers/auto-fill.controller'; import { SheetsHyperLinkCopyPasteController } from './controllers/copy-paste.controller'; import { SheetHyperLinkUrlController } from './controllers/url.controller'; import { SheetsHyperLinkPermissionController } from './controllers/hyper-link-permission.controller'; -export class UniverSheetsHyperLinkUIPlugin extends UniverSheetsHyperLinkPlugin { - static override pluginName: string = SHEETS_HYPER_LINK_UI_PLUGIN; +@DependentOn(UniverSheetsHyperLinkPlugin) +export class UniverSheetsHyperLinkUIPlugin extends Plugin { + static override pluginName: string = SHEET_HYPER_LINK_UI_PLUGIN; static override type = UniverInstanceType.UNIVER_SHEET; constructor( private _config: IUniverSheetsHyperLinkUIConfig, @Inject(Injector) protected override _injector: Injector ) { - super(_config, _injector); + super(); } override onStarting(injector: Injector): void { - super.onStarting(injector); const dependencies: Dependency[] = [ [SheetsHyperLinkResolverService], [SheetsHyperLinkPopupService], diff --git a/packages/sheets-hyper-link-ui/src/types/const.ts b/packages/sheets-hyper-link-ui/src/types/const.ts index 1ae494cceb..8a2f6419c3 100644 --- a/packages/sheets-hyper-link-ui/src/types/const.ts +++ b/packages/sheets-hyper-link-ui/src/types/const.ts @@ -14,6 +14,6 @@ * limitations under the License. */ -export const SHEETS_HYPER_LINK_UI_PLUGIN = 'SHEETS_HYPER_LINK_UI_PLUGIN'; +export const SHEET_HYPER_LINK_UI_PLUGIN = 'SHEET_HYPER_LINK_UI_PLUGIN'; export const ERROR_RANGE = 'err'; diff --git a/packages/sheets-numfmt/src/numfmt-plugin.ts b/packages/sheets-numfmt/src/numfmt-plugin.ts index 68f2e315e2..fc4db77445 100644 --- a/packages/sheets-numfmt/src/numfmt-plugin.ts +++ b/packages/sheets-numfmt/src/numfmt-plugin.ts @@ -14,9 +14,11 @@ * limitations under the License. */ -import { Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverSheetsPlugin } from '@univerjs/sheets'; +import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui'; import { SHEET_NUMFMT_PLUGIN } from './base/const/PLUGIN_NAME'; import { NumfmtCellContent } from './controllers/numfmt.cell-content.controller'; import { NumfmtController } from './controllers/numfmt.controller'; @@ -27,6 +29,7 @@ import { DefaultSheetNumfmtConfig, NumfmtMenuController } from './controllers/nu import { INumfmtController } from './controllers/type'; import { UserHabitController } from './controllers/user-habit.controller'; +@DependentOn(UniverSheetsPlugin, UniverSheetsUIPlugin) export class UniverSheetsNumfmtPlugin extends Plugin { static override pluginName = SHEET_NUMFMT_PLUGIN; static override type = UniverInstanceType.UNIVER_SHEET; diff --git a/packages/sheets-thread-comment/src/plugin.ts b/packages/sheets-thread-comment/src/plugin.ts index 7083f69fd0..e088e366c3 100644 --- a/packages/sheets-thread-comment/src/plugin.ts +++ b/packages/sheets-thread-comment/src/plugin.ts @@ -16,7 +16,7 @@ import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; -import { ICommandService, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, ICommandService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import { UniverThreadCommentUIPlugin } from '@univerjs/thread-comment-ui'; import type { IUniverSheetsThreadCommentConfig } from './controllers/sheets-thread-comment.controller'; import { DefaultSheetsThreadCommentConfig, SheetsThreadCommentController } from './controllers/sheets-thread-comment.controller'; @@ -30,7 +30,8 @@ import { SheetsThreadCommentCopyPasteController } from './controllers/sheets-thr import { SheetsThreadCommentHoverController } from './controllers/sheets-thread-comment-hover.controller'; import { ThreadCommentRemoveSheetsController } from './controllers/sheets-thread-comment-remove.controller'; -export class UniverSheetsThreadCommentPlugin extends UniverThreadCommentUIPlugin { +@DependentOn(UniverThreadCommentUIPlugin) +export class UniverSheetsThreadCommentPlugin extends Plugin { static override pluginName = SHEETS_THREAD_COMMENT; static override type = UniverInstanceType.UNIVER_SHEET; @@ -39,15 +40,14 @@ export class UniverSheetsThreadCommentPlugin extends UniverThreadCommentUIPlugin constructor( config: Partial = {}, @Inject(Injector) protected override _injector: Injector, - @Inject(ICommandService) protected override _commandService: ICommandService + @Inject(ICommandService) protected _commandService: ICommandService ) { - super(config, _injector, _commandService); + super(); this._pluginConfig = Tools.deepMerge({}, DefaultSheetsThreadCommentConfig, config); } override onStarting(injector: Injector): void { - super.onStarting(injector); ([ [SheetsThreadCommentModel], [ @@ -63,7 +63,7 @@ export class UniverSheetsThreadCommentPlugin extends UniverThreadCommentUIPlugin [ThreadCommentRemoveSheetsController], [SheetsThreadCommentPopupService], ] as Dependency[]).forEach((dep) => { - this._injector.add(dep); + injector.add(dep); }); [ShowAddSheetCommentModalOperation].forEach((command) => { diff --git a/packages/sheets-ui/src/sheets-ui-plugin.ts b/packages/sheets-ui/src/sheets-ui-plugin.ts index 0b4e70d3b0..5496948686 100644 --- a/packages/sheets-ui/src/sheets-ui-plugin.ts +++ b/packages/sheets-ui/src/sheets-ui-plugin.ts @@ -15,13 +15,14 @@ */ import type { Workbook } from '@univerjs/core'; -import { IUniverInstanceService, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, IUniverInstanceService, LocaleService, Plugin, Tools, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; import { filter } from 'rxjs/operators'; import { IRenderManagerService } from '@univerjs/engine-render'; -import { WorksheetProtectionRenderService } from '@univerjs/sheets'; +import { UniverSheetsPlugin, WorksheetProtectionRenderService } from '@univerjs/sheets'; +import { UniverUIPlugin } from '@univerjs/ui'; import { ActiveWorksheetController } from './controllers/active-worksheet/active-worksheet.controller'; import { AutoHeightController } from './controllers/auto-height.controller'; import { SheetClipboardController } from './controllers/clipboard/clipboard.controller'; @@ -84,6 +85,7 @@ import { SheetPermissionPanelModel } from './services/permission/sheet-permissio import { SheetPermissionUserManagerService } from './services/permission/sheet-permission-user-list.service'; import { PermissionRenderService } from './services/permission/permission-render.service'; +@DependentOn(UniverSheetsPlugin, UniverUIPlugin) export class UniverSheetsUIPlugin extends Plugin { static override pluginName = 'SHEET_UI_PLUGIN'; static override type = UniverInstanceType.UNIVER_SHEET; diff --git a/packages/sheets/src/sheets-plugin.ts b/packages/sheets/src/sheets-plugin.ts index e1d5582975..75acb32d70 100644 --- a/packages/sheets/src/sheets-plugin.ts +++ b/packages/sheets/src/sheets-plugin.ts @@ -15,10 +15,11 @@ */ import type { DependencyOverride } from '@univerjs/core'; -import { ICommandService, IConfigService, LocaleService, mergeOverrideWithDependencies, Plugin, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, ICommandService, IConfigService, LocaleService, mergeOverrideWithDependencies, Plugin, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverFormulaEnginePlugin } from '@univerjs/engine-formula'; import { BasicWorksheetController } from './controllers/basic-worksheet.controller'; import { CalculateResultApplyController } from './controllers/calculate-result-apply.controller'; import { FeatureCalculationController } from './controllers/feature-calculation.controller'; @@ -56,6 +57,7 @@ export interface IUniverSheetsConfig { /** * The main sheet base, construct the sheet container and layout, mount the rendering engine */ +@DependentOn(UniverFormulaEnginePlugin) export class UniverSheetsPlugin extends Plugin { static override pluginName = PLUGIN_NAME; static override type = UniverInstanceType.UNIVER_SHEET; diff --git a/packages/thread-comment-ui/src/plugin.ts b/packages/thread-comment-ui/src/plugin.ts index 0282f4585c..4d13dec1f9 100644 --- a/packages/thread-comment-ui/src/plugin.ts +++ b/packages/thread-comment-ui/src/plugin.ts @@ -16,7 +16,7 @@ import { UniverThreadCommentPlugin } from '@univerjs/thread-comment'; import type { DependencyOverride } from '@univerjs/core'; -import { ICommandService, mergeOverrideWithDependencies, UniverInstanceType } from '@univerjs/core'; +import { DependentOn, ICommandService, mergeOverrideWithDependencies, Plugin, UniverInstanceType } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; import { PLUGIN_NAME } from './types/const'; @@ -29,31 +29,25 @@ export interface IUniverThreadCommentUIConfig { overrides?: DependencyOverride; } -export class UniverThreadCommentUIPlugin extends UniverThreadCommentPlugin { +@DependentOn(UniverThreadCommentPlugin) +export class UniverThreadCommentUIPlugin extends Plugin { static override pluginName = PLUGIN_NAME; static override type = UniverInstanceType.UNIVER_UNKNOWN; - private _config1: IUniverThreadCommentUIConfig; constructor( - config: IUniverThreadCommentUIConfig, + private readonly _config: IUniverThreadCommentUIConfig | undefined, @Inject(Injector) protected override _injector: Injector, - @ICommandService protected override _commandService: ICommandService + @ICommandService protected _commandService: ICommandService ) { - super( - config, - _injector, - _commandService - ); - this._config1 = config; + super(); } override onStarting(injector: Injector): void { - super.onStarting(injector); (mergeOverrideWithDependencies([ [ThreadCommentUIController], [ThreadCommentPanelService], [IThreadCommentMentionDataService, { useClass: ThreadCommentMentionDataService }], - ], this._config1.overrides) as Dependency[]).forEach((dep) => { + ], this._config?.overrides) as Dependency[]).forEach((dep) => { injector.add(dep); }); diff --git a/packages/thread-comment-ui/src/types/const.ts b/packages/thread-comment-ui/src/types/const.ts index c87a58a7bd..feda6cd5f0 100644 --- a/packages/thread-comment-ui/src/types/const.ts +++ b/packages/thread-comment-ui/src/types/const.ts @@ -18,4 +18,4 @@ export const THREAD_COMMENT_POPUP = 'thread-comment-popup'; export const THREAD_COMMENT_PANEL = 'thread-comment-panel'; -export const PLUGIN_NAME = 'thread-comment-ui-plugin'; +export const PLUGIN_NAME = 'THREAD_COMMENT_UI_PLUGIN'; diff --git a/packages/ui/src/ui-plugin.ts b/packages/ui/src/ui-plugin.ts index 01a341c39c..f87bc2c928 100644 --- a/packages/ui/src/ui-plugin.ts +++ b/packages/ui/src/ui-plugin.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -import { IContextService, ILocalStorageService, LocaleService, mergeOverrideWithDependencies, Plugin, Tools } from '@univerjs/core'; +import { DependentOn, IContextService, ILocalStorageService, LocaleService, mergeOverrideWithDependencies, Plugin, Tools } from '@univerjs/core'; import type { Dependency } from '@wendellhu/redi'; import { Inject, Injector } from '@wendellhu/redi'; +import { UniverRenderEnginePlugin } from '@univerjs/engine-render'; import { CanvasPopupService, ICanvasPopupService } from './services/popup/canvas-popup.service'; import { DesktopGlobalZoneService } from './services/global-zone/desktop-global-zone.service'; @@ -65,6 +66,7 @@ export const DISABLE_AUTO_FOCUS_KEY = 'DISABLE_AUTO_FOCUS'; /** * UI plugin provides basic interaction with users. Including workbench (menus, UI parts, notifications etc.), copy paste, shortcut. */ +@DependentOn(UniverRenderEnginePlugin) export class UniverUIPlugin extends Plugin { static override pluginName = PLUGIN_NAME;