diff --git a/app/src/index.ts b/app/src/index.ts index 8d377a5a3..5c1d1d9ae 100644 --- a/app/src/index.ts +++ b/app/src/index.ts @@ -54,6 +54,9 @@ export class App { id: genUUID(), type: "main", msgCallback: (data) => { + this.plugins.forEach((plugin) => { + plugin.eventBus.emit("ws-main", data); + }); if (data) { switch (data.cmd) { case "syncMergeResult": @@ -167,8 +170,8 @@ export class App { bootSync(); fetchPost("/api/setting/getCloudUser", {}, userResponse => { window.siyuan.user = userResponse.data; - onGetConfig(response.data.start); loadPlugins(siyuanApp); + onGetConfig(response.data.start); account.onSetaccount(); resizeDrag(); setTitle(window.siyuan.languages.siyuanNote); diff --git a/app/src/mobile/index.ts b/app/src/mobile/index.ts index c1fe48880..4e8d8c042 100644 --- a/app/src/mobile/index.ts +++ b/app/src/mobile/index.ts @@ -22,8 +22,11 @@ import {getSearch} from "../util/functions"; import {initRightMenu} from "./menu"; import {openChangelog} from "../boot/openChangelog"; import {registerServiceWorker} from "../util/serviceWorker"; +import {loadPlugins} from "../plugin/loader"; class App { + public plugins: import("../plugin").Plugin[] = []; + constructor() { if (!window.webkit?.messageHandlers && !window.JSAndroid) { registerServiceWorker(`${Constants.SERVICE_WORKER_PATH}?v=${Constants.SIYUAN_VERSION}`); @@ -41,7 +44,10 @@ class App { ws: new Model({ id: genUUID(), type: "main", - msgCallback(data) { + msgCallback: (data)=> { + this.plugins.forEach((plugin) => { + plugin.eventBus.emit("ws-main", data); + }); onMessage(data); } }) @@ -66,6 +72,7 @@ class App { initAssets(); fetchPost("/api/setting/getCloudUser", {}, userResponse => { window.siyuan.user = userResponse.data; + loadPlugins(siyuanApp); fetchPost("/api/system/getEmojiConf", {}, emojiResponse => { window.siyuan.emojis = emojiResponse.data as IEmoji[]; initFramework(); @@ -85,7 +92,7 @@ class App { } } -new App(); +const siyuanApp = new App(); window.goBack = goBack; window.showKeyboardToolbar = (height) => { diff --git a/app/src/plugin/API.ts b/app/src/plugin/API.ts new file mode 100644 index 000000000..1a55a0444 --- /dev/null +++ b/app/src/plugin/API.ts @@ -0,0 +1,9 @@ +import {confirmDialog} from "../dialog/confirmDialog"; +import {Plugin} from "./index"; +import {showMessage} from "../dialog/message"; + +export const API = { + Plugin: Plugin, + Confirm: confirmDialog, + Message: showMessage +}; diff --git a/app/src/plugin/EventBus.ts b/app/src/plugin/EventBus.ts new file mode 100644 index 000000000..72abacd93 --- /dev/null +++ b/app/src/plugin/EventBus.ts @@ -0,0 +1,23 @@ +export class EventBus { + private eventTarget: EventTarget; + + constructor(name = "") { + this.eventTarget = document.appendChild(document.createComment(name)); + } + + on(type: TEventBus, listener: (event: CustomEvent) => void) { + this.eventTarget.addEventListener(type, listener); + } + + once(type: TEventBus, listener: (event: CustomEvent) => void) { + this.eventTarget.addEventListener(type, listener, {once: true}); + } + + off(type: TEventBus, listener: (event: CustomEvent) => void) { + this.eventTarget.removeEventListener(type, listener); + } + + emit(type: TEventBus, detail?: DetailType) { + return this.eventTarget.dispatchEvent(new CustomEvent(type, {detail})); + } +} diff --git a/app/src/plugin/index.ts b/app/src/plugin/index.ts index 0b13e72fe..21bcbf08e 100644 --- a/app/src/plugin/index.ts +++ b/app/src/plugin/index.ts @@ -1,14 +1,18 @@ import {App} from "../index"; +import {EventBus} from "./EventBus"; export class Plugin { public i18n: IObject; + public eventBus: EventBus; constructor(options: { app: App, id: string, + name: string, i18n: IObject }) { this.i18n = options.i18n; + this.eventBus = new EventBus(options.name); } public getData() { diff --git a/app/src/plugin/loader.ts b/app/src/plugin/loader.ts index 412698fa8..d83166081 100644 --- a/app/src/plugin/loader.ts +++ b/app/src/plugin/loader.ts @@ -1,12 +1,11 @@ import {fetchPost} from "../util/fetch"; import {App} from "../index"; import {Plugin} from "./index"; +import {API} from "./API"; const getObject = (key: string) => { const api = { - siyuan: { - Plugin: Plugin - } + siyuan: API }; // @ts-ignore return api[key]; @@ -37,7 +36,12 @@ export const loadPlugins = (app: App) => { console.error(`plugin ${item.name} does not extends Plugin`); return; } - const plugin = new pluginClass({app, id: item.id, i18n: item.i18n}); + const plugin = new pluginClass({ + app, + name: item.name, + id: item.id, + i18n: item.i18n + }); app.plugins.push(plugin); plugin.onload(); css += item.css || "" + "\n"; diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts index 0427cf0eb..784b70186 100644 --- a/app/src/types/index.d.ts +++ b/app/src/types/index.d.ts @@ -31,6 +31,8 @@ type TOperation = | "removeFlashcards" type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins" type TCardType = "doc" | "notebook" | "all" +type TEventBus = "ws-main" + declare module "blueimp-md5" interface Window { diff --git a/app/src/window/index.ts b/app/src/window/index.ts index a289d4a6e..09fc9ac37 100644 --- a/app/src/window/index.ts +++ b/app/src/window/index.ts @@ -21,8 +21,11 @@ import {getAllTabs} from "../layout/getAll"; import {getLocalStorage} from "../protyle/util/compatibility"; import {init} from "../window/init"; import {positionPDF, switchTabById} from "./global/function"; +import {loadPlugins} from "../plugin/loader"; class App { + public plugins: import("../plugin").Plugin[] = []; + constructor() { addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript"); addScript(`${Constants.PROTYLE_CDN}/js/protyle-html.js?v=${Constants.SIYUAN_VERSION}`, "protyleWcHtmlScript"); @@ -40,6 +43,9 @@ class App { id: genUUID(), type: "main", msgCallback: (data) => { + this.plugins.forEach((plugin) => { + plugin.eventBus.emit("ws-main", data); + }); if (data) { switch (data.cmd) { case "syncMergeResult": @@ -128,6 +134,7 @@ class App { window.siyuan.menus = new Menus(); fetchPost("/api/setting/getCloudUser", {}, userResponse => { window.siyuan.user = userResponse.data; + loadPlugins(siyuanApp); init(); setTitle(window.siyuan.languages.siyuanNote); initMessage(); @@ -141,7 +148,7 @@ class App { } } -new App(); +const siyuanApp = new App(); // 再次点击新窗口已打开的 PDF 时,需进行定位 window.newWindow = {