diff --git a/app/src/config/bazaar.ts b/app/src/config/bazaar.ts index 7c5874d29..42836846d 100644 --- a/app/src/config/bazaar.ts +++ b/app/src/config/bazaar.ts @@ -16,6 +16,7 @@ import {Plugin} from "../plugin"; import {App} from "../index"; import {escapeAttr} from "../util/escape"; import {uninstall} from "../plugin/uninstall"; +import {loadPlugin} from "../plugin/loader"; export const bazaar = { element: undefined as Element, @@ -635,19 +636,16 @@ export const bazaar = { event.stopPropagation(); break; } else if (type === "plugin-enable") { - const itemElement = hasClosestByClassName(target, "b3-card"); - if (itemElement) { + if (!target.getAttribute("disabled")) { + target.setAttribute("disabled", "disabled"); const enabled = (target as HTMLInputElement).checked; fetchPost("/api/petal/setPetalEnabled", { packageName: dataObj.name, enabled, - }, () => { + }, (response) => { + target.removeAttribute("disabled"); if (enabled) { - exportLayout({ - reload: true, - onlyData: false, - errorExit: false, - }); + loadPlugin(app, response.data); } else { uninstall(app, dataObj.name); } diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts index c1d23918e..b703c3a66 100644 --- a/app/src/layout/dock/index.ts +++ b/app/src/layout/dock/index.ts @@ -549,7 +549,9 @@ export class Dock { this.toggleModel(key, false, true, true); this.element.querySelector(`[data-type="${key}"]`).remove(); const custom = this.data[key] as Custom; - custom.parent.parent.removeTab(custom.parent.id); + if (custom.parent) { + custom.parent.parent.removeTab(custom.parent.id); + } delete this.data[key]; } @@ -603,7 +605,7 @@ export class Dock { return max; } - private genButton(data: IDockTab[], index: number) { + public genButton(data: IDockTab[], index: number, append = false) { let html = ""; data.forEach(item => { html += ` @@ -612,11 +614,19 @@ export class Dock { this.data[item.type] = true; }); if (index === 0) { - this.element.firstElementChild.innerHTML = `${html} + if (append) { + this.element.firstElementChild.lastElementChild.insertAdjacentHTML("beforebegin", html); + } else { + this.element.firstElementChild.innerHTML = `${html} `; + } } else { - this.element.lastElementChild.innerHTML = html; + if (append) { + this.element.lastElementChild.insertAdjacentHTML("beforeend", html); + } else { + this.element.lastElementChild.innerHTML = html; + } } } } diff --git a/app/src/plugin/loader.ts b/app/src/plugin/loader.ts index 32fc8c106..160a79596 100644 --- a/app/src/plugin/loader.ts +++ b/app/src/plugin/loader.ts @@ -2,6 +2,7 @@ import {fetchPost} from "../util/fetch"; import {App} from "../index"; import {Plugin} from "./index"; import {API} from "./API"; +import {exportLayout} from "../layout/util"; const getObject = (key: string) => { const api = { @@ -18,35 +19,8 @@ const runCode = (code: string, sourceURL: string) => { export const loadPlugins = (app: App) => { fetchPost("/api/petal/loadPetals", {}, response => { let css = ""; - response.data.forEach((item: { name: string, js: string, css: string, i18n: IObject }) => { - const exportsObj: { [key: string]: any } = {}; - const moduleObj = {exports: exportsObj}; - try { - runCode(item.js, "plugin:" + encodeURIComponent(item.name))(getObject, moduleObj, exportsObj); - } catch (e) { - console.error(`eval plugin ${item.name} error:`, e); - return; - } - const pluginClass = (moduleObj.exports || exportsObj).default || moduleObj.exports; - if (typeof pluginClass !== "function") { - console.error(`plugin ${item.name} has no export`); - return; - } - if (!(pluginClass.prototype instanceof Plugin)) { - console.error(`plugin ${item.name} does not extends Plugin`); - return; - } - const plugin = new pluginClass({ - app, - name: item.name, - i18n: item.i18n - }); - app.plugins.push(plugin); - try { - plugin.onload(); - } catch (e) { - console.error(`plugin ${item.name} load error:`, e); - } + response.data.forEach((item: IPluginData) => { + loadPluginJS(app, item); css += item.css || "" + "\n"; }); const styleElement = document.createElement("style"); @@ -54,3 +28,78 @@ export const loadPlugins = (app: App) => { document.head.append(styleElement); }); }; + +const loadPluginJS = (app: App, item: IPluginData) => { + const exportsObj: { [key: string]: any } = {}; + const moduleObj = {exports: exportsObj}; + try { + runCode(item.js, "plugin:" + encodeURIComponent(item.name))(getObject, moduleObj, exportsObj); + } catch (e) { + console.error(`eval plugin ${item.name} error:`, e); + return; + } + const pluginClass = (moduleObj.exports || exportsObj).default || moduleObj.exports; + if (typeof pluginClass !== "function") { + console.error(`plugin ${item.name} has no export`); + return; + } + if (!(pluginClass.prototype instanceof Plugin)) { + console.error(`plugin ${item.name} does not extends Plugin`); + return; + } + const plugin = new pluginClass({ + app, + name: item.name, + i18n: item.i18n + }); + app.plugins.push(plugin); + try { + plugin.onload(); + } catch (e) { + console.error(`plugin ${item.name} load error:`, e); + } + return plugin; +} + +export const loadPlugin = (app: App, item: IPluginData) => { + const plugin = loadPluginJS(app, item); + Object.keys(plugin.docks).forEach(key => { + const dock = plugin.docks[key]; + if (dock.config.position.startsWith("Left")) { + window.siyuan.layout.leftDock.genButton([{ + type: key, + size: dock.config.size, + show: false, + icon: dock.config.icon, + title: dock.config.title, + hotkey: dock.config.hotkey + }], dock.config.position === "LeftBottom" ? 1 : 0, true) + } else if (dock.config.position.startsWith("Bottom")) { + window.siyuan.layout.bottomDock.genButton([{ + type: key, + size: dock.config.size, + show: false, + icon: dock.config.icon, + title: dock.config.title, + hotkey: dock.config.hotkey + }], dock.config.position === "BottomRight" ? 1 : 0, true) + } else if (dock.config.position.startsWith("Right")) { + window.siyuan.layout.rightDock.genButton([{ + type: key, + size: dock.config.size, + show: false, + icon: dock.config.icon, + title: dock.config.title, + hotkey: dock.config.hotkey + }], dock.config.position === "RightBottom" ? 1 : 0, true) + } + }); + const styleElement = document.createElement("style"); + styleElement.textContent = item.css; + document.head.append(styleElement); + exportLayout({ + reload: false, + onlyData: false, + errorExit: false + }); +}; diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index 2868ea487..799b735c8 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -298,6 +298,13 @@ declare interface IDockTab { hotkeyLangId?: string // 常量中无法存变量 } +declare interface IPluginData { + name: string, + js: string, + css: string, + i18n: IObject +} + declare interface IPluginDockTab { position: TPluginDockPosition, size: { width: number, height: number },