✨ enable plugin
This commit is contained in:
parent
f3d1acd166
commit
85496345ef
4 changed files with 105 additions and 41 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkey="${item.hotkey || ""}" data-hotkeyLangId="${item.hotkeyLangId || ""}" data-title="${item.title}" class="dock__item${item.show ? " dock__item--active" : ""} b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${item.title} ${item.hotkey ? updateHotkeyTip(item.hotkey) : ""}${window.siyuan.languages.dockTip}">
|
||||
|
@ -612,11 +614,19 @@ export class Dock {
|
|||
this.data[item.type] = true;
|
||||
});
|
||||
if (index === 0) {
|
||||
this.element.firstElementChild.innerHTML = `${html}<span class="dock__item dock__item--pin b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${this.pin ? window.siyuan.languages.unpin : window.siyuan.languages.pin}">
|
||||
if (append) {
|
||||
this.element.firstElementChild.lastElementChild.insertAdjacentHTML("beforebegin", html);
|
||||
} else {
|
||||
this.element.firstElementChild.innerHTML = `${html}<span class="dock__item dock__item--pin b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${this.pin ? window.siyuan.languages.unpin : window.siyuan.languages.pin}">
|
||||
<svg><use xlink:href="#iconPin"></use></svg>
|
||||
</span>`;
|
||||
}
|
||||
} else {
|
||||
this.element.lastElementChild.innerHTML = html;
|
||||
if (append) {
|
||||
this.element.lastElementChild.insertAdjacentHTML("beforeend", html);
|
||||
} else {
|
||||
this.element.lastElementChild.innerHTML = html;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
});
|
||||
};
|
||||
|
|
7
app/src/types/index.d.ts
vendored
7
app/src/types/index.d.ts
vendored
|
@ -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 },
|
||||
|
|
Loading…
Add table
Reference in a new issue