packages/lowcode-plugin-inject/src/appInject.tsx (137 lines of code) (raw):
import { IPublicModelPluginContext, IPublicEnumPluginRegisterLevel } from '@alilc/lowcode-types';
import { getInjectedResource, injectAssets, type InjectOptions } from './utils';
import Icon from './icon';
import { Pane } from './pane';
import React from 'react';
import { InjectConfig } from './controller';
const injectConfig = new InjectConfig();
let injectedPluginConfigMap = null;
let injectedPlugins = [];
export async function getInjectedPlugin(name: string, ctx: IPublicModelPluginContext, injectOptions?: InjectOptions) {
if (!injectedPluginConfigMap) {
injectedPluginConfigMap = {};
injectedPlugins = await getInjectedResource('plugin', injectOptions);
if (injectedPlugins && injectedPlugins.length > 0) {
injectedPlugins.forEach((item: any) => {
const config = item.module(ctx);
injectedPluginConfigMap[config.name || item.module.pluginName] = item.module;
});
}
}
return injectedPluginConfigMap[name];
}
export function AppInject(ctx: IPublicModelPluginContext, options: any) {
const { workspace } = ctx;
const getInjectPlugin = async (plugin: any, pluginOptions: any, ctx?: IPublicModelPluginContext) => {
let pluginName = plugin.pluginName;
if (!pluginName) {
const pluginConfig = plugin(ctx, pluginOptions);
pluginName = pluginConfig.name;
}
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx, options);
const resourceName = ctx.editorWindow?.resource?.name;
const viewName = (ctx?.editorWindow?.currentEditorView as any)?.viewName;
const isGlobal = ctx?.registerLevel === IPublicEnumPluginRegisterLevel.Workspace;
if (!injectedSameNamePlugin) {
return plugin;
}
if (isGlobal) {
if (injectConfig.has(pluginName, 'global')) {
return injectConfig.get(pluginName, 'global') ? injectedSameNamePlugin : plugin;
}
injectConfig.set(pluginName, 'global', undefined, true)
return injectedSameNamePlugin;
}
if (!viewName || !resourceName) {
return injectedSameNamePlugin;
}
if (injectConfig.has(pluginName, resourceName, viewName)) {
return injectConfig.get(pluginName, resourceName, viewName) ? injectedSameNamePlugin : plugin;
}
injectConfig.set(pluginName, resourceName, viewName, true);
return injectedSameNamePlugin;
}
ctx.config.set('customPluginTransducer', async (originPlugin: any, ctx: IPublicModelPluginContext, options) => {
const injectedSameNamePlugin = await getInjectPlugin(originPlugin, options, ctx);
return injectedSameNamePlugin;
});
return {
// 插件名,注册环境下唯一
name: 'LowcodePluginInjectAlt',
// 依赖的插件(插件名数组)
dep: [],
async init() {
const subPluginName = '___injectPlugins___';
const subPlugin = (ctx: IPublicModelPluginContext) => {
injectAssets(ctx, options)
return {
async init() {
}
}
}
subPlugin.pluginName = subPluginName;
subPlugin.meta = {
dependencies: [],
engines: {
lowcodeEngine: '^1.0.0', // 插件需要配合 ^1.0.0 的引擎才可运行
},
};
workspace.onChangeActiveWindow(async () => {
for (const pluginName in injectedPluginConfigMap) {
const injectedSameNamePlugin = await getInjectedPlugin(pluginName, ctx, options);
if (!injectedSameNamePlugin) {
continue;
}
const resourceName = workspace.window?.resource?.name;
const currentEditorView = workspace.window?.currentEditorView;
const viewName = (currentEditorView as any)?.viewName;
if (injectConfig.get(pluginName, resourceName, viewName) && !currentEditorView?.plugins.has(pluginName)) {
await currentEditorView?.plugins.register(injectedPluginConfigMap[pluginName], {
autoInit: true,
});
}
if (injectConfig.get(pluginName, 'global') && !workspace.plugins.has(pluginName)) {
await workspace.plugins.register(injectedPluginConfigMap[pluginName], {
autoInit: true,
});
}
}
if (workspace.window?.currentEditorView && !workspace.window?.currentEditorView.plugins?.has(subPlugin.pluginName)) {
await workspace.window?.currentEditorView.plugins.register(subPlugin)
}
});
await getInjectedPlugin(undefined, ctx, options);
ctx.skeleton.add({
area: 'leftArea',
name: 'inject-pane',
type: 'PanelDock',
props: {
icon: <Icon />,
description: '调试',
className: 'inject-pane-icon',
},
index: 2,
panelProps: {
width: '600px',
canSetFixed: false,
},
content: (props) => {
return <Pane {...props} injectConfig={injectConfig} />
},
contentProps: {
pluginContext: ctx,
injectConfig,
injectedPluginConfigMap,
getInjectInfo: async () => {
const injectedSetters = await getInjectedResource('vs', options);
return {
injectedSetters,
}
},
updateInjectConfig: (pluginName: string, resourceName: string, viewName: string, check: boolean) => {
injectConfig.set(pluginName, resourceName, viewName, check)
injectConfig.save()
}
},
});
}
}
}