import {appearance} from "./appearance"; import {showMessage} from "../dialog/message"; import {fetchPost} from "../util/fetch"; import {confirmDialog} from "../dialog/confirmDialog"; import {highlightRender} from "../protyle/render/highlightRender"; import {exportLayout, saveLayout} from "../layout/util"; import {Constants} from "../constants"; /// #if !BROWSER import * as path from "path"; /// #endif import {getFrontend, isBrowser} from "../util/functions"; import {setStorageVal} from "../protyle/util/compatibility"; import {hasClosestByAttribute, hasClosestByClassName} from "../protyle/util/hasClosest"; import {Plugin} from "../plugin"; import {App} from "../index"; import {escapeAttr} from "../util/escape"; import {uninstall} from "../plugin/uninstall"; import {afterLoadPlugin, loadPlugin, loadPlugins, reloadPlugin} from "../plugin/loader"; import {loadAssets} from "../util/assets"; import {addScript} from "../protyle/util/addScript"; import {useShell} from "../util/pathName"; export const bazaar = { element: undefined as Element, genHTML() { if (!window.siyuan.config.bazaar.trust) { return `
${window.siyuan.languages.bazaarTrust}
${window.siyuan.languages.bazaarTrust3}
${window.siyuan.languages.bazaarTrustCodeReview}
${window.siyuan.languages.bazaarTrustCodeReviewTip}
${window.siyuan.languages.bazaarTrustOpenSource}
${window.siyuan.languages.bazaarTrustOpenSourceTip}
${window.siyuan.languages.bazaarCommunityReview}
${window.siyuan.languages.bazaarPeerReviewTip}
${window.siyuan.languages.bazaarUserReport}
${window.siyuan.languages.bazaarUserReportTip}
${window.siyuan.languages.bazaarTrust1}
${window.siyuan.languages.bazaarTrust2}
`; } const localSort = window.siyuan.storage[Constants.LOCAL_BAZAAR]; const loadingHTML = `
`; return `
${window.siyuan.languages.downloaded}
${window.siyuan.languages.plugin}
${window.siyuan.languages.theme}
${window.siyuan.languages.icon}
${window.siyuan.languages.template}
${window.siyuan.languages.widget}
${loadingHTML}
${loadingHTML}
${loadingHTML}
${loadingHTML}
${loadingHTML}
${loadingHTML}
`; }, _genCardHTML(item: IBazaarItem, bazaarType: TBazaarType) { let hide = false; let themeMode = ""; if (bazaarType === "themes") { const themeValue = (bazaar.element.querySelector("#bazaarSelect") as HTMLSelectElement).value; if ((themeValue === "0" && item.modes.includes("dark")) || themeValue === "1" && item.modes.includes("light")) { hide = true; } themeMode = item.modes.toString(); } let showSwitch = false; if (["icons", "themes"].includes(bazaarType)) { showSwitch = true; } const dataObj = { bazaarType, themeMode: themeMode, updated: item.updated, name: item.name, repoURL: item.repoURL, repoHash: item.repoHash, downloads: item.downloads, downloaded: false, }; return `
${item.preferredName} ${item.name}
${item.preferredDesc || ""}
${item.downloads} ${item.preferredFunding ? `` : ""}
`; }, _genUpdateItemHTML(item: IBazaarItem, bazaarType: TBazaarType) { const dataObj = { bazaarType, themeMode: item.modes?.toString(), updated: item.updated, name: item.name, repoURL: item.repoURL, repoHash: item.repoHash, downloaded: true }; return `
${item.preferredName} ${item.name}
${item.preferredDesc || ""}
${item.incompatible ? `${window.siyuan.languages.incompatible}` : ""} ${item.preferredFunding ? `` : ""}
`; }, _getUpdate() { fetchPost("/api/bazaar/getUpdatedPackage", {frontend: getFrontend()}, (response) => { let html = ""; response.data.plugins.forEach((item: IBazaarItem) => { html += this._genUpdateItemHTML(item, "plugins"); }); response.data.themes.forEach((item: IBazaarItem) => { html += this._genUpdateItemHTML(item, "themes"); }); response.data.icons.forEach((item: IBazaarItem) => { html += this._genUpdateItemHTML(item, "icons"); }); response.data.templates.forEach((item: IBazaarItem) => { html += this._genUpdateItemHTML(item, "templates"); }); response.data.widgets.forEach((item: IBazaarItem) => { html += this._genUpdateItemHTML(item, "widgets"); }); this._data.update = response.data; const allCount = response.data.themes.length + response.data.icons.length + response.data.widgets.length + response.data.plugins.length + response.data.templates.length; if (allCount === 0) { this.element.querySelector('[data-type="downloaded-update"]').innerHTML = ""; return; } this.element.querySelector('[data-type="downloaded-update"]').innerHTML = `
${allCount}
${html}
`; }); }, _genMyHTML(bazaarType: TBazaarType, app: App, updateUpdate = true) { if (updateUpdate) { this._getUpdate(); } const contentElement = bazaar.element.querySelector("#configBazaarDownloaded"); if (contentElement.getAttribute("data-loading") === "true" || contentElement.previousElementSibling.querySelector(`[data-type="my${bazaarType.replace(bazaarType[0], bazaarType[0].toUpperCase()).substring(0, bazaarType.length - 1)}"]`).classList.contains("b3-button--outline")) { return; } contentElement.setAttribute("data-loading", "true"); let url = "/api/bazaar/getInstalledTheme"; if (bazaarType === "icons") { url = "/api/bazaar/getInstalledIcon"; } else if (bazaarType === "widgets") { url = "/api/bazaar/getInstalledWidget"; } else if (bazaarType === "templates") { url = "/api/bazaar/getInstalledTemplate"; } else if (bazaarType === "plugins") { url = "/api/bazaar/getInstalledPlugin"; } fetchPost(url, { frontend: getFrontend(), keyword: (contentElement.previousElementSibling.querySelector(".b3-text-field") as HTMLInputElement)?.value || "", }, response => { contentElement.removeAttribute("data-loading"); let html = ""; let showSwitch = false; if (["icons", "themes"].includes(bazaarType)) { showSwitch = true; } const counterElement = contentElement.previousElementSibling.querySelector(".counter"); if (response.data.packages.length === 0) { counterElement.classList.add("fn__none"); } else { counterElement.classList.remove("fn__none"); counterElement.textContent = response.data.packages.length; response.data.packages.forEach((item: IBazaarItem) => { const dataObj = { bazaarType, themeMode: item.modes?.toString(), updated: item.updated, name: item.name, repoURL: item.repoURL, repoHash: item.repoHash, downloaded: true }; let hasSetting = false; if (bazaarType === "plugins") { app.plugins.find((item: Plugin) => { if (item.name === dataObj.name) { // @ts-ignore hasSetting = item.setting || item.__proto__.hasOwnProperty("openSetting"); return true; } }); } html += `
${item.preferredName} ${item.name}
${item.preferredDesc || ""}
${item.incompatible ? `${window.siyuan.languages.incompatible}` : ""} ${item.preferredFunding ? `` : ""}
`; }); } bazaar._data.downloaded = response.data.packages; const checkElement = contentElement.parentElement.querySelector(".b3-switch"); if (bazaarType === "plugins") { checkElement.classList.remove("fn__none"); } else { checkElement.classList.add("fn__none"); } contentElement.innerHTML = html ? html : `
`; }); }, _data: { themes: [] as IBazaarItem[], templates: [] as IBazaarItem[], icons: [] as IBazaarItem[], widgets: [] as IBazaarItem[], plugins: [] as IBazaarItem[], downloaded: [] as IBazaarItem[], update: { themes: [] as IBazaarItem[], templates: [] as IBazaarItem[], icons: [] as IBazaarItem[], widgets: [] as IBazaarItem[], plugins: [] as IBazaarItem[], } }, _renderReadme(bazaarType: TBazaarType, data: IBazaarItem, downloaded: boolean) { const readmeElement = bazaar.element.querySelector("#configBazaarReadme") as HTMLElement; const urls = data.repoURL.split("/"); urls.pop(); let navTitle = window.siyuan.languages.icon; if (bazaarType === "themes") { navTitle = window.siyuan.languages.theme; } else if (bazaarType === "widgets") { navTitle = window.siyuan.languages.widget; } else if (bazaarType === "templates") { navTitle = window.siyuan.languages.template; } else if (bazaarType === "plugins") { navTitle = window.siyuan.languages.plugin; } const dataObj1 = { bazaarType, themeMode: data.modes?.toString(), name: data.name, repoURL: data.repoURL, repoHash: data.repoHash, downloaded }; readmeElement.innerHTML = `
${navTitle}
${data.preferredName}
${data.name}
${data.preferredFunding ? `` : `` } ${data.author}
${window.siyuan.languages.currentVer}
v${data.version}
${downloaded ? window.siyuan.languages.installDate : window.siyuan.languages.releaseDate}
${downloaded ? data.hInstallDate : data.hUpdated}
${window.siyuan.languages.pkgSize}
${data.hSize}
${window.siyuan.languages.installSize}
${data.hInstallSize}
${window.siyuan.languages.feedback}
Repo ${data.stars} ${data.openIssues} ${data.downloads}

${data.preferredDesc || ""}

`; if (downloaded && data.preferredReadme) { const mdElement = readmeElement.querySelector(".item__readme"); mdElement.innerHTML = data.preferredReadme; highlightRender(mdElement); } else { fetchPost("/api/bazaar/getBazaarPackageREAME", { repoURL: data.repoURL, repoHash: data.repoHash, packageType: bazaarType }, response => { const mdElement = readmeElement.querySelector(".item__readme"); mdElement.innerHTML = response.data.html; highlightRender(mdElement); }); } readmeElement.classList.add("config-bazaar__readme--show"); }, bindEvent(app: App) { if (!window.siyuan.config.bazaar.trust) { bazaar.element.querySelector("button").addEventListener("click", () => { fetchPost("/api/setting/setBazaar", { trust: true, petalDisabled: window.siyuan.config.bazaar.petalDisabled }, () => { window.siyuan.config.bazaar.trust = true; bazaar.element.innerHTML = bazaar.genHTML(); bazaar.bindEvent(app); }); }); return; } this._genMyHTML("plugins", app); bazaar.element.firstElementChild.addEventListener("click", (event) => { let target = event.target as HTMLElement; const dataElement = hasClosestByAttribute(target, "data-obj", null); let dataObj: IObject; if (dataElement) { dataObj = JSON.parse(dataElement.getAttribute("data-obj")); } while (target && !target.isEqualNode(bazaar.element)) { const type = target.getAttribute("data-type"); if (target.tagName === "A") { break; } else if (type === "open" && dataObj) { /// #if !BROWSER const dirName = dataObj.bazaarType; if (dirName === "icons" || dirName === "themes") { useShell("openPath", path.join(window.siyuan.config.system.confDir, "appearance", dirName, dataObj.name)); } else { useShell("openPath", path.join(window.siyuan.config.system.dataDir, dirName, dataObj.name)); } /// #endif event.preventDefault(); event.stopPropagation(); break; } else if (["myTheme", "myTemplate", "myIcon", "myWidget", "myPlugin"].includes(type)) { if (target.classList.contains("b3-button--outline") && !bazaar.element.querySelector("#configBazaarDownloaded").getAttribute("data-loading")) { target.parentElement.childNodes.forEach((item: HTMLElement) => { if (item.nodeType !== 3 && item.classList.contains("b3-button")) { item.classList.add("b3-button--outline"); } }); target.classList.remove("b3-button--outline"); this._genMyHTML(type.replace("my", "").toLowerCase() + "s" as TBazaarType, app, false); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "goBack") { bazaar.element.querySelector("#configBazaarReadme").classList.remove("config-bazaar__readme--show"); event.preventDefault(); event.stopPropagation(); break; } else if (type === "install") { if (!target.classList.contains("b3-button--progress")) { const bazaarType = dataObj.bazaarType as TBazaarType; let url = "/api/bazaar/installBazaarTemplate"; if (bazaarType === "themes") { url = "/api/bazaar/installBazaarTheme"; } else if (bazaarType === "icons") { url = "/api/bazaar/installBazaarIcon"; } else if (bazaarType === "widgets") { url = "/api/bazaar/installBazaarWidget"; } else if (bazaarType === "plugins") { url = "/api/bazaar/installBazaarPlugin"; } fetchPost(url, { keyword: (bazaar.element.querySelector(".config-bazaar__panel:not(.fn__none) .b3-form__icon-input") as HTMLInputElement).value, repoURL: dataObj.repoURL, packageName: dataObj.name, repoHash: dataObj.repoHash, mode: dataObj.themeMode === "dark" ? 1 : 0, frontend: getFrontend() }, async response => { if (window.siyuan.config.appearance.themeJS && bazaarType === "themes") { if (window.destroyTheme) { try { await window.destroyTheme(); window.destroyTheme = undefined; document.getElementById("themeScript").remove(); } catch (e) { console.error("destroyTheme error: " + e); } window.siyuan.config.appearance = response.data.appearance; loadAssets(window.siyuan.config.appearance); } else { exportLayout({ cb() { window.location.reload(); }, errorExit: false, }); return; } } bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType)); bazaar._genMyHTML(bazaarType, app, false); if (bazaarType === "plugins") { if (window.siyuan.config.bazaar.petalDisabled) { confirmDialog(window.siyuan.languages.confirm, window.siyuan.languages.enablePluginTip2); } else { confirmDialog("💡 " + window.siyuan.languages.enablePlugin, window.siyuan.languages.enablePluginTip, () => { fetchPost("/api/petal/setPetalEnabled", { packageName: dataObj.name, enabled: true, frontend: getFrontend() }, (response) => { loadPlugin(app, response.data); bazaar._genMyHTML(bazaarType, app, false); }); }); } } }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "install-all") { confirmDialog("⬆️ " + window.siyuan.languages.updateAll, window.siyuan.languages.confirmUpdateAll, () => { fetchPost("/api/bazaar/batchUpdatePackage", {frontend: getFrontend()}); }); event.preventDefault(); event.stopPropagation(); break; } else if (type === "feedback") { event.preventDefault(); event.stopPropagation(); break; } else if (type === "install-t") { if (!target.classList.contains("b3-button--progress")) { confirmDialog("⬆️ " + window.siyuan.languages.update, window.siyuan.languages.confirmUpdate, () => { const bazaarType = dataObj.bazaarType as TBazaarType; let url = "/api/bazaar/installBazaarTemplate"; if (bazaarType === "themes") { url = "/api/bazaar/installBazaarTheme"; } else if (bazaarType === "icons") { url = "/api/bazaar/installBazaarIcon"; } else if (bazaarType === "widgets") { url = "/api/bazaar/installBazaarWidget"; } else if (bazaarType === "plugins") { url = "/api/bazaar/installBazaarPlugin"; } if (!target.classList.contains("b3-button")) { target.parentElement.insertAdjacentHTML("afterend", ''); } fetchPost(url, { keyword: (bazaar.element.querySelector(".config-bazaar__panel:not(.fn__none) .b3-form__icon-input") as HTMLInputElement).value, repoURL: dataObj.repoURL, packageName: dataObj.name, repoHash: dataObj.repoHash, mode: dataObj.themeMode === "dark" ? 1 : 0, update: true, frontend: getFrontend() }, async response => { this._genMyHTML(bazaarType, app); bazaar._onBazaar(response, bazaarType, ["icons"].includes(bazaarType)); // https://github.com/siyuan-note/siyuan/issues/15177 if (bazaarType === "themes" && response.data.appearance?.themeVer) { window.siyuan.config.appearance.themeVer = response.data.appearance.themeVer; } // 更新主题后不需要对该主题进行切换 https://github.com/siyuan-note/siyuan/issues/4966 // https://github.com/siyuan-note/siyuan/issues/5411 if (bazaarType === "themes" && ( (window.siyuan.config.appearance.mode === 0 && window.siyuan.config.appearance.themeLight === dataObj.name) || (window.siyuan.config.appearance.mode === 1 && window.siyuan.config.appearance.themeDark === dataObj.name) )) { const currentTheme = window.siyuan.config.appearance.mode === 1 ? window.siyuan.config.appearance.themeDark : window.siyuan.config.appearance.themeLight; if (window.siyuan.config.appearance.themeJS) { if (window.destroyTheme) { try { await window.destroyTheme(); window.destroyTheme = undefined; document.getElementById("themeScript").remove(); addScript(`/appearance/themes/${currentTheme}/theme.js?v=${response.data.appearance.themeVer}`, "themeScript"); } catch (e) { console.error("destroyTheme error: " + e); } } else { exportLayout({ cb() { window.location.reload(); }, errorExit: false, }); return; } } if ((window.siyuan.config.appearance.mode === 1 && currentTheme === "midnight") || (window.siyuan.config.appearance.mode !== 1 && currentTheme === "daylight")) { (document.getElementById("themeDefaultStyle") as HTMLLinkElement).href = `/appearance/themes/${window.siyuan.config.appearance.mode === 1 ? "midnight" : "daylight"}/theme.css?v=${Constants.SIYUAN_VERSION}`; } else { (document.getElementById("themeStyle") as HTMLLinkElement).href = `/appearance/themes/${currentTheme}/theme.css?v=${response.data.appearance.themeVer}`; } } else if (bazaarType === "plugins") { app.plugins.find((item: Plugin) => { if (item.name === dataObj.name) { reloadPlugin(app, { upsertPlugins: [dataObj.name], removePlugins: [] }); return true; } }); } }); }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "uninstall") { const bazaarType = dataObj.bazaarType as TBazaarType; let url = "/api/bazaar/uninstallBazaarTemplate"; if (bazaarType === "themes") { url = "/api/bazaar/uninstallBazaarTheme"; } else if (bazaarType === "icons") { url = "/api/bazaar/uninstallBazaarIcon"; } else if (bazaarType === "widgets") { url = "/api/bazaar/uninstallBazaarWidget"; } else if (bazaarType === "plugins") { url = "/api/bazaar/uninstallBazaarPlugin"; } const packageName = dataObj.name; if (window.siyuan.config.appearance.themeDark === packageName || window.siyuan.config.appearance.themeLight === packageName || window.siyuan.config.appearance.icon === packageName) { showMessage(window.siyuan.languages.uninstallTip); } else { confirmDialog("⚠️ " + window.siyuan.languages.uninstall, window.siyuan.languages.confirmUninstall.replace("${name}", packageName), () => { fetchPost(url, { packageName, keyword: (bazaar.element.querySelector(".config-bazaar__panel:not(.fn__none) .b3-form__icon-input") as HTMLInputElement).value, frontend: getFrontend() }, response => { this._genMyHTML(bazaarType, app); bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType)); if (bazaarType === "plugins") { uninstall(app, packageName, true); } }); }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "switch") { const bazaarType = dataObj.bazaarType as TBazaarType; const packageName = dataObj.name; const mode = dataObj.themeMode === "dark" ? 1 : 0; if (bazaarType === "icons") { fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, { icon: packageName, }), (appearanceResponse) => { this._genMyHTML(bazaarType, app, false); fetchPost("/api/bazaar/getBazaarIcon", {}, response => { response.data.appearance = appearanceResponse.data; bazaar._onBazaar(response, "icons", true); bazaar._data.icons = response.data.packages; }); }); } else if (bazaarType === "themes") { fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, { mode, modeOS: false, themeDark: mode === 1 ? packageName : window.siyuan.config.appearance.themeDark, themeLight: mode === 0 ? packageName : window.siyuan.config.appearance.themeLight, }), async (appearanceResponse) => { if ((mode !== window.siyuan.config.appearance.mode || (mode === 1 && window.siyuan.config.appearance.themeDark !== packageName) || (mode === 0 && window.siyuan.config.appearance.themeLight !== packageName)) && window.siyuan.config.appearance.themeJS) { if (window.destroyTheme) { try { await window.destroyTheme(); window.destroyTheme = undefined; document.getElementById("themeScript").remove(); } catch (e) { console.error("destroyTheme error: " + e); } window.siyuan.config.appearance = appearanceResponse.data; loadAssets(window.siyuan.config.appearance); } else { exportLayout({ cb() { window.location.reload(); }, errorExit: false, }); return; } } this._genMyHTML("themes", app, false); fetchPost("/api/bazaar/getBazaarTheme", {}, response => { response.data.appearance = appearanceResponse.data; bazaar._onBazaar(response, "themes", true); bazaar._data.themes = response.data.packages; }); }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "setting") { app.plugins.find((item: Plugin) => { if (item.name === dataObj.name) { item.openSetting(); return true; } }); event.preventDefault(); event.stopPropagation(); break; } else if (type === "plugins-enable") { if (!target.getAttribute("disabled")) { target.setAttribute("disabled", "disabled"); window.siyuan.config.bazaar.petalDisabled = !(target as HTMLInputElement).checked; fetchPost("/api/setting/setBazaar", window.siyuan.config.bazaar, () => { target.removeAttribute("disabled"); if (window.siyuan.config.bazaar.petalDisabled) { bazaar.element.querySelectorAll("#configBazaarDownloaded .b3-card").forEach(item => { item.classList.add("b3-card--disabled"); uninstall(app, JSON.parse(item.getAttribute("data-obj")).name); }); } else { bazaar.element.querySelectorAll("#configBazaarDownloaded .b3-card").forEach(item => { item.classList.remove("b3-card--disabled"); }); loadPlugins(app).then(() => { app.plugins.forEach(item => { afterLoadPlugin(item); }); }); saveLayout(); } }); } event.stopPropagation(); break; } else if (type === "plugin-enable") { if (!target.getAttribute("disabled")) { target.setAttribute("disabled", "disabled"); const enabled = (target as HTMLInputElement).checked; fetchPost("/api/petal/setPetalEnabled", { packageName: dataObj.name, enabled, frontend: getFrontend() }, (response) => { target.removeAttribute("disabled"); if (enabled) { loadPlugin(app, response.data).then((plugin: Plugin) => { // @ts-ignore if (plugin.setting || plugin.__proto__.hasOwnProperty("openSetting")) { target.parentElement.querySelector('[data-type="setting"]').classList.remove("fn__none"); } else { target.parentElement.querySelector('[data-type="setting"]').classList.add("fn__none"); } }); } else { uninstall(app, dataObj.name); target.parentElement.querySelector('[data-type="setting"]').classList.add("fn__none"); } }); } event.stopPropagation(); break; } else if (target.classList.contains("b3-card")) { if (!hasClosestByClassName(event.target as HTMLElement, "b3-card__actions--right")) { const dataObj = JSON.parse(target.getAttribute("data-obj")); const bazaarType = (dataObj.bazaarType) as TBazaarType; let data; if (hasClosestByAttribute(target, "data-type", "downloaded-update")) { data = bazaar._data.update[(dataObj.bazaarType) as TBazaarType].find((item: IBazaarItem) => item.repoURL === dataObj.repoURL); } else { data = (dataObj.downloaded ? bazaar._data.downloaded : bazaar._data[bazaarType]).find((item: IBazaarItem) => item.repoURL === dataObj.repoURL); } bazaar._renderReadme(bazaarType, data, dataObj.downloaded); } event.preventDefault(); event.stopPropagation(); break; } else if (target.classList.contains("item") && !target.classList.contains("item--focus")) { // switch tab bazaar.element.querySelector(".layout-tab-bar .item--focus").classList.remove("item--focus"); target.classList.add("item--focus"); bazaar.element.querySelectorAll(".config-bazaar__panel").forEach(item => { if (type === item.getAttribute("data-type")) { item.classList.remove("fn__none"); if (!item.getAttribute("data-init")) { if (type === "template") { fetchPost("/api/bazaar/getBazaarTemplate", {}, response => { bazaar._onBazaar(response, "templates", false); bazaar._data.templates = response.data.packages; }); } else if (type === "icon") { fetchPost("/api/bazaar/getBazaarIcon", {}, response => { bazaar._onBazaar(response, "icons", false); bazaar._data.icons = response.data.packages; }); } else if (type === "widget") { fetchPost("/api/bazaar/getBazaarWidget", {}, response => { bazaar._onBazaar(response, "widgets", false); bazaar._data.widgets = response.data.packages; }); } else if (type === "theme") { fetchPost("/api/bazaar/getBazaarTheme", {}, response => { bazaar._onBazaar(response, "themes", false); bazaar._data.themes = response.data.packages; }); } else if (type === "plugin") { fetchPost("/api/bazaar/getBazaarPlugin", { frontend: getFrontend() }, response => { bazaar._onBazaar(response, "plugins", false); bazaar._data.plugins = response.data.packages; }); } item.setAttribute("data-init", "true"); } } else { item.classList.add("fn__none"); } }); event.preventDefault(); event.stopPropagation(); break; } else if (target.classList.contains("item__preview")) { target.classList.toggle("item__preview--fullscreen"); event.preventDefault(); event.stopPropagation(); break; } target = target.parentElement; } }); bazaar.element.querySelectorAll(".config-bazaar__panel .b3-form__icon > .b3-text-field").forEach((inputElement: HTMLInputElement) => { inputElement.addEventListener("keydown", (event) => { if (event.isComposing) { return; } if (event.key === "Enter") { const keyword = inputElement.value.trim(); const type = (hasClosestByClassName(inputElement, "config-bazaar__panel") as HTMLElement).getAttribute("data-type"); if (type === "template") { fetchPost("/api/bazaar/getBazaarTemplate", {keyword}, response => { bazaar._onBazaar(response, "templates", false); bazaar._data.templates = response.data.packages; }); } else if (type === "icon") { fetchPost("/api/bazaar/getBazaarIcon", {keyword}, response => { bazaar._onBazaar(response, "icons", false); bazaar._data.icons = response.data.packages; }); } else if (type === "widget") { fetchPost("/api/bazaar/getBazaarWidget", {keyword}, response => { bazaar._onBazaar(response, "widgets", false); bazaar._data.widgets = response.data.packages; }); } else if (type === "theme") { fetchPost("/api/bazaar/getBazaarTheme", {keyword}, response => { bazaar._onBazaar(response, "themes", false); bazaar._data.themes = response.data.packages; }); } else if (type === "plugin") { fetchPost("/api/bazaar/getBazaarPlugin", { frontend: getFrontend(), keyword }, response => { bazaar._onBazaar(response, "plugins", false); bazaar._data.plugins = response.data.packages; }); } else if (type === "downloaded") { const bazaarType = inputElement.parentElement.parentElement.querySelector(".b3-button:not(.b3-button--outline)").getAttribute("data-type").replace("my", "").toLowerCase() + "s" as TBazaarType; this._genMyHTML(bazaarType, app); } event.preventDefault(); return; } }); }); bazaar.element.querySelectorAll(".b3-select").forEach((selectElement: HTMLSelectElement) => { selectElement.addEventListener("change", (event) => { if (selectElement.id === "bazaarSelect") { // theme select bazaar.element.querySelectorAll("#configBazaarTheme .b3-card").forEach((item) => { const dataObj = JSON.parse(item.getAttribute("data-obj")); if (selectElement.value === "0") { if (dataObj.themeMode.indexOf("light") > -1) { item.classList.remove("fn__none"); } else { item.classList.add("fn__none"); } } else if (selectElement.value === "1") { if (dataObj.themeMode.indexOf("dark") > -1) { item.classList.remove("fn__none"); } else { item.classList.add("fn__none"); } } else { item.classList.remove("fn__none"); } }); (event.target as HTMLElement).parentElement.querySelector(".counter").textContent = bazaar.element.querySelectorAll("#configBazaarTheme .b3-card:not(.fn__none)").length.toString(); } else { // sort const localSort = window.siyuan.storage[Constants.LOCAL_BAZAAR]; const panelElement = selectElement.parentElement.parentElement; let html = ""; const cardElements = Array.from(panelElement.querySelectorAll(".b3-card")); if (selectElement.value === "0") { // 更新时间降序 cardElements.sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).updated < JSON.parse(a.getAttribute("data-obj")).updated ? -1 : 1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "1") { // 更新时间升序 cardElements.sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).updated < JSON.parse(a.getAttribute("data-obj")).updated ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "2") { // 下载次数降序 cardElements.sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).downloads < JSON.parse(a.getAttribute("data-obj")).downloads ? -1 : 1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "3") { // 下载次数升序 cardElements.sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).downloads < JSON.parse(a.getAttribute("data-obj")).downloads ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } localSort[selectElement.parentElement.parentElement.getAttribute("data-type")] = selectElement.value; setStorageVal(Constants.LOCAL_BAZAAR, window.siyuan.storage[Constants.LOCAL_BAZAAR]); if (cardElements.length > 1) { html += '
'; } panelElement.querySelector(".b3-cards").innerHTML = html; } }); }); }, _onBazaar(response: IWebSocketData, bazaarType: TBazaarType, reload: boolean) { if (bazaar.element.querySelector("#configBazaarReadme").classList.contains("config-bazaar__readme--show")) { const dataObj = JSON.parse(bazaar.element.querySelector("#configBazaarReadme > .item__side").getAttribute("data-obj")); bazaar._renderReadme((dataObj.bazaarType) as TBazaarType, response.data.packages.find((item: IBazaarItem) => item.repoURL === dataObj.repoURL), dataObj.downloaded); } let id = "#configBazaarTemplate"; if (bazaarType === "themes") { id = "#configBazaarTheme"; } else if (bazaarType === "icons") { id = "#configBazaarIcon"; } else if (bazaarType === "widgets") { id = "#configBazaarWidget"; } else if (bazaarType === "plugins") { id = "#configBazaarPlugin"; } const element = bazaar.element.querySelector(id); if (response.code === 1) { showMessage(response.msg); element.querySelectorAll("img[data-type='img-loading']").forEach((item) => { item.remove(); }); } let html = ""; response.data.packages.forEach((item: IBazaarItem) => { html += this._genCardHTML(item, bazaarType); }); bazaar._data[bazaarType] = response.data.packages; element.innerHTML = `
${html}
`; element.parentElement.querySelector(".counter").textContent = element.querySelectorAll(".b3-card:not(.fn__none)").length.toString(); const localSort = window.siyuan.storage[Constants.LOCAL_BAZAAR]; if (localSort[bazaarType.replace("s", "")] === "1") { html = ""; Array.from(element.querySelectorAll(".b3-card")).sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).updated < JSON.parse(a.getAttribute("data-obj")).updated ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } else if (localSort[bazaarType.replace("s", "")] === "2") { // 下载次数降序 html = ""; Array.from(element.querySelectorAll(".b3-card")).sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).downloads < JSON.parse(a.getAttribute("data-obj")).downloads ? -1 : 1; }).forEach((item) => { html += item.outerHTML; }); } else if (localSort[bazaarType.replace("s", "")] === "3") { // 下载次数升序 html = ""; Array.from(element.querySelectorAll(".b3-card")).sort((a, b) => { return JSON.parse(b.getAttribute("data-obj")).downloads < JSON.parse(a.getAttribute("data-obj")).downloads ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } if (response.data.packages.length > 1) { html += '
'; } element.innerHTML = `
${html}
`; if (reload) { appearance.onSetAppearance(response.data.appearance); } } };