From 1ac623ebb1a272ffdc63a8d02f9f6916669b4005 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Tue, 16 May 2023 00:04:25 +0800 Subject: [PATCH] :art: fix https://github.com/siyuan-note/siyuan/issues/8258 --- app/src/config/bazaar.ts | 26 +++++++++---------- app/src/layout/dock/index.ts | 13 ++++++++-- app/src/plugin/index.ts | 2 ++ app/src/plugin/uninstall.ts | 48 ++++++++++++++++++++++++++++++++++++ app/src/util/fetch.ts | 7 ++++-- 5 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 app/src/plugin/uninstall.ts diff --git a/app/src/config/bazaar.ts b/app/src/config/bazaar.ts index b8f682026..cdfeeec44 100644 --- a/app/src/config/bazaar.ts +++ b/app/src/config/bazaar.ts @@ -15,6 +15,7 @@ import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasC import {Plugin} from "../plugin"; import {App} from "../index"; import {escapeAttr} from "../util/escape"; +import {uninstall} from "../plugin/uninstall"; export const bazaar = { element: undefined as Element, @@ -571,12 +572,7 @@ export const bazaar = { this._genMyHTML(bazaarType, app); bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType)); if (bazaarType === "plugins") { - // TODO destroy plugin - exportLayout({ - reload: true, - onlyData: false, - errorExit: false, - }); + uninstall(app, packageName); } }); }); @@ -641,16 +637,20 @@ export const bazaar = { } else if (type === "plugin-enable") { const itemElement = hasClosestByClassName(target, "b3-card"); if (itemElement) { + const enabled = (target as HTMLInputElement).checked fetchPost("/api/petal/setPetalEnabled", { packageName: dataObj.name, - enabled: (target as HTMLInputElement).checked + enabled, }, () => { - // TODO destroy plugin - exportLayout({ - reload: true, - onlyData: false, - errorExit: false, - }); + if (enabled) { + exportLayout({ + reload: true, + onlyData: false, + errorExit: false, + }); + } else { + uninstall(app, dataObj.name); + } }); } event.stopPropagation(); diff --git a/app/src/layout/dock/index.ts b/app/src/layout/dock/index.ts index e4f5d2b74..c1d23918e 100644 --- a/app/src/layout/dock/index.ts +++ b/app/src/layout/dock/index.ts @@ -17,6 +17,7 @@ import {resetFloatDockSize} from "./util"; import {hasClosestByClassName} from "../../protyle/util/hasClosest"; import {App} from "../../index"; import {Plugin} from "../../plugin"; +import {Custom} from "./Custom"; export class Dock { public element: HTMLElement; @@ -267,7 +268,7 @@ export class Dock { this.layout.element.querySelector(".layout__tab--active")?.classList.remove("layout__tab--active"); } - public toggleModel(type: string, show = false, close = false) { + public toggleModel(type: string, show = false, close = false, hide = false) { if (!type) { return; } @@ -277,7 +278,7 @@ export class Dock { } const index = parseInt(target.getAttribute("data-index")); const wnd = this.layout.children[index] as Wnd; - if (target.classList.contains("dock__item--active")) { + if (target.classList.contains("dock__item--active") || hide) { if (!close) { let needFocus = false; Array.from(wnd.element.querySelector(".layout-tab-container").children).find(item => { @@ -544,6 +545,14 @@ export class Dock { } } + public remove(key: string) { + 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); + delete this.data[key]; + } + private getClassDirect(index: number) { let direct = "e"; switch (this.position) { diff --git a/app/src/plugin/index.ts b/app/src/plugin/index.ts index d95f8fb5f..7f678b6bc 100644 --- a/app/src/plugin/index.ts +++ b/app/src/plugin/index.ts @@ -14,6 +14,7 @@ export class Plugin { public eventBus: EventBus; public data: any; public name: string; + public topBarIcons: Element[] = []; public models: { /// #if !MOBILE [key: string]: (options: { tab: Tab, data: any }) => Custom @@ -65,6 +66,7 @@ export class Plugin { iconElement.addEventListener("click", options.callback); document.querySelector("#" + (options.position === "right" ? "barSearch" : "drag")).before(iconElement); } + this.topBarIcons.push(iconElement); return iconElement; } diff --git a/app/src/plugin/uninstall.ts b/app/src/plugin/uninstall.ts new file mode 100644 index 000000000..66095ae67 --- /dev/null +++ b/app/src/plugin/uninstall.ts @@ -0,0 +1,48 @@ +import {App} from "../index"; +import {Plugin} from "../plugin"; +import {getAllModels} from "../layout/getAll"; +import {exportLayout} from "../layout/util"; + +export const uninstall = (app: App, name: string) => { + app.plugins.find((plugin: Plugin, index) => { + if (plugin.name === name) { + // rm tab + const modelsKeys = Object.keys(plugin.models) + getAllModels().custom.forEach(custom => { + if (modelsKeys.includes(custom.type)) { + custom.parent.parent.removeTab(custom.parent.id) + } + }) + // rm topbar + plugin.topBarIcons.forEach(item => { + item.remove(); + }) + // rm dock + const docksKeys = Object.keys(plugin.docks) + docksKeys.forEach(key => { + if (Object.keys(window.siyuan.layout.leftDock.data).includes(key)) { + window.siyuan.layout.leftDock.remove(key) + } else if (Object.keys(window.siyuan.layout.rightDock.data).includes(key)) { + window.siyuan.layout.rightDock.remove(key) + } else if (Object.keys(window.siyuan.layout.bottomDock.data).includes(key)) { + window.siyuan.layout.bottomDock.remove(key) + } + }) + exportLayout({ + reload: false, + onlyData: false, + errorExit: false + }); + // rm listen + Array.from(document.childNodes).find(item => { + if (item.nodeType === 8 && item.textContent === name) { + item.remove(); + return true; + } + }) + // rm plugin + app.plugins.splice(index, 1) + return true + } + }) +} diff --git a/app/src/util/fetch.ts b/app/src/util/fetch.ts index 61779838e..83194ffc8 100644 --- a/app/src/util/fetch.ts +++ b/app/src/util/fetch.ts @@ -29,11 +29,11 @@ export const fetchPost = (url: string, data?: any, cb?: (response: IWebSocketDat } fetch(url, init).then((response) => { if (response.status === 404) { - cb({ + return { data: null, msg: response.statusText, code: response.status, - }); + }; } else { if (response.headers.get("content-type").indexOf("application/json") > -1) { return response.json(); @@ -48,6 +48,9 @@ export const fetchPost = (url: string, data?: any, cb?: (response: IWebSocketDat } return; } + if (typeof response.msg === "undefined") { + return; + } if (["/api/search/searchRefBlock", "/api/graph/getGraph", "/api/graph/getLocalGraph"].includes(url)) { if (response.data.reqId && window.siyuan.reqIds[url] && window.siyuan.reqIds[url] > response.data.reqId) { return;