import {appearance} from "./appearance"; import {showMessage} from "../dialog/message"; import {fetchPost} from "../util/fetch"; import {hasClosestByClassName} from "../protyle/util/hasClosest"; import {confirmDialog} from "../dialog/confirmDialog"; import {highlightRender} from "../protyle/markdown/highlightRender"; import {exportLayout} from "../layout/util"; import {Constants} from "../constants"; export const bazaar = { element: undefined as Element, genHTML() { const localSortString = localStorage.getItem(Constants.LOCAL_BAZAAR); let localSort; if (!localSortString) { localSort = { theme: "0", template: "0", icon: "0", widget: "0", }; localStorage.setItem(Constants.LOCAL_BAZAAR, JSON.stringify(localSort)); } else { localSort = JSON.parse(localSortString); } const loadingHTML = `
`; return `
${window.siyuan.languages.theme}
${window.siyuan.languages.template}
${window.siyuan.languages.icon}
${window.siyuan.languages.widget}
${loadingHTML}
${loadingHTML}
${loadingHTML}
${loadingHTML}
`; }, getHTML(item: IBazaarItem, bazaarType: TBazaarType) { let hide = false; let type = ""; 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; } type = item.modes.toString(); } let showSwitch = false; if (["icons", "themes"].includes(bazaarType)) { showSwitch = true; } return `
${item.name} ${item.downloads}
`; }, data: { themes: [] as IBazaarItem[], templates: [] as IBazaarItem[], icons: [] as IBazaarItem[], widgets: [] as IBazaarItem[], }, renderReadme(cardElement: HTMLElement, bazaarType: TBazaarType) { const repoURL = cardElement.querySelector(".b3-card__actions").getAttribute("data-url"); let data: IBazaarItem; bazaar.data[bazaarType].find((item: IBazaarItem) => { if (item.repoURL === repoURL) { data = item; return true; } }); const readmeElement = bazaar.element.querySelector("#configBazaarReadme") as HTMLElement; const urls = data.repoURL.split("/"); urls.pop(); let navTitle = window.siyuan.languages.icon; if (bazaarType === "themes") { if (data.modes.includes("dark")) { navTitle = window.siyuan.languages.themeDark + " " + window.siyuan.languages.theme; } else { navTitle = window.siyuan.languages.themeLight + " " + window.siyuan.languages.theme; } } else if (bazaarType === "widgets") { navTitle = window.siyuan.languages.widget; } else if (bazaarType === "templates") { navTitle = window.siyuan.languages.template; } readmeElement.innerHTML = `
${navTitle}
${data.name}
Made with ❤️ by
${data.author}
${window.siyuan.languages.currentVer}
v${data.version}
${window.siyuan.languages.releaseDate}
${data.hUpdated}
${window.siyuan.languages.pkgSize}
${data.hSize}
Repo ${data.stars} ${data.openIssues} ${data.downloads}
`; fetchPost("/api/bazaar/getBazaarPackageREAME", { repoURL: data.repoURL, repoHash: data.repoHash, }, response => { const mdElement = readmeElement.querySelector(".item__readme"); mdElement.innerHTML = response.data.html; highlightRender(mdElement); }); readmeElement.style.right = "0"; }, bindEvent() { fetchPost("/api/bazaar/getBazaarTheme", {}, response => { bazaar.onBazaar(response, "themes", false); bazaar.data.themes = response.data.packages; }); bazaar.element.addEventListener("click", (event) => { let target = event.target as HTMLElement; while (target && !target.isEqualNode(bazaar.element)) { const type = target.getAttribute("data-type"); if (type === "goBack") { const readmeElement = bazaar.element.querySelector("#configBazaarReadme") as HTMLElement; readmeElement.style.right = "-100%"; event.preventDefault(); event.stopPropagation(); break; } else if (type === "install") { if (!target.classList.contains("b3-button--progress")) { const bazaarType = target.getAttribute("data-bazaar") 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"; } fetchPost(url, { repoURL: target.getAttribute("data-url"), packageName: target.getAttribute("data-name"), repoHash: target.getAttribute("data-hash"), mode: target.parentElement.getAttribute("data-type") === "dark" ? 1 : 0, }, response => { if (window.siyuan.config.appearance.themeJS && bazaarType === "themes") { exportLayout(true); return; } bazaar.onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType)); }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "install-t") { confirmDialog(window.siyuan.languages.update, window.siyuan.languages.exportTplTip, () => { const cardElement = hasClosestByClassName(target, "b3-card"); let bazaarType: TBazaarType = "themes"; if (cardElement) { bazaarType = cardElement.getAttribute("data-bazaar") 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"; } target.parentElement.insertAdjacentHTML("afterend", ""); fetchPost(url, { repoURL: target.parentElement.getAttribute("data-url"), packageName: target.parentElement.getAttribute("data-name"), repoHash: target.parentElement.getAttribute("data-hash"), mode: target.parentElement.parentElement.getAttribute("data-type") === "dark" ? 1 : 0, update: true, }, response => { // 更新主题后不需要对该主题进行切换 https://github.com/siyuan-note/siyuan/issues/4966 bazaar.onBazaar(response, bazaarType, ["icons"].includes(bazaarType)); }); }); event.preventDefault(); event.stopPropagation(); break; } else if (type === "uninstall") { const cardElement = hasClosestByClassName(target, "b3-card"); let bazaarType: TBazaarType = "themes"; if (cardElement) { bazaarType = cardElement.getAttribute("data-bazaar") 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"; } const packageName = target.parentElement.getAttribute("data-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 { fetchPost(url, { packageName }, response => { bazaar.onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType)); }); } event.preventDefault(); event.stopPropagation(); break; } else if (type === "switch") { const packageName = target.parentElement.getAttribute("data-name"); const cardElement = hasClosestByClassName(target, "b3-card"); let bazaarType: TBazaarType = "themes"; let mode: number; if (cardElement) { bazaarType = cardElement.getAttribute("data-bazaar") as TBazaarType; mode = cardElement.getAttribute("data-type") === "dark" ? 1 : 0; } if (bazaarType === "icons") { fetchPost("/api/setting/setAppearance", { icon: packageName, mode: window.siyuan.config.appearance.mode, codeBlockThemeDark: window.siyuan.config.appearance.codeBlockThemeDark, codeBlockThemeLight: window.siyuan.config.appearance.codeBlockThemeLight, themeDark: window.siyuan.config.appearance.themeDark, themeLight: window.siyuan.config.appearance.themeLight, darkThemes: window.siyuan.config.appearance.darkThemes, lightThemes: window.siyuan.config.appearance.lightThemes, icons: window.siyuan.config.appearance.icons, lang: window.siyuan.config.appearance.lang, customCSS: window.siyuan.config.appearance.customCSS, closeButtonBehavior: window.siyuan.config.appearance.closeButtonBehavior, nativeEmoji: window.siyuan.config.appearance.nativeEmoji, }, response => { appearance.onSetappearance(response.data); }); } else if (bazaarType === "themes") { fetchPost("/api/setting/setAppearance", { icon: window.siyuan.config.appearance.icon, mode, codeBlockThemeDark: window.siyuan.config.appearance.codeBlockThemeDark, codeBlockThemeLight: window.siyuan.config.appearance.codeBlockThemeLight, themeDark: mode === 1 ? packageName : window.siyuan.config.appearance.themeDark, themeLight: mode === 0 ? packageName : window.siyuan.config.appearance.themeLight, darkThemes: window.siyuan.config.appearance.darkThemes, lightThemes: window.siyuan.config.appearance.lightThemes, icons: window.siyuan.config.appearance.icons, lang: window.siyuan.config.appearance.lang, customCSS: window.siyuan.config.appearance.customCSS, closeButtonBehavior: window.siyuan.config.appearance.closeButtonBehavior, nativeEmoji: window.siyuan.config.appearance.nativeEmoji, }, response => { 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) { exportLayout(true); } else { appearance.onSetappearance(response.data); } }); } event.preventDefault(); event.stopPropagation(); break; } else if (target.classList.contains("b3-card")) { bazaar.renderReadme(target, target.getAttribute("data-bazaar") as TBazaarType); 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"); const type = target.getAttribute("data-type"); bazaar.element.querySelectorAll(".bazaarPanel").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; }); } 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(".b3-select").forEach((selectElement: HTMLSelectElement) => { selectElement.addEventListener("change", () => { if (selectElement.id === "bazaarSelect") { // theme select bazaar.element.querySelectorAll("#configBazaarTheme .b3-card").forEach((item) => { if (selectElement.value === "0") { if (item.getAttribute("data-type").indexOf("light") > -1) { item.classList.remove("fn__none"); } else { item.classList.add("fn__none"); } } else if (selectElement.value === "1") { if (item.getAttribute("data-type").indexOf("dark") > -1) { item.classList.remove("fn__none"); } else { item.classList.add("fn__none"); } } else { item.classList.remove("fn__none"); } }); } else { // sort const localSort = JSON.parse(localStorage.getItem(Constants.LOCAL_BAZAAR)); const panelElement = selectElement.parentElement.parentElement; let html = ""; if (selectElement.value === "0") { // 更新时间降序 Array.from(panelElement.querySelectorAll(".b3-card")).sort((a, b) => { return b.getAttribute("data-updated") < a.getAttribute("data-updated") ? -1 : 1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "1") { // 更新时间升序 Array.from(panelElement.querySelectorAll(".b3-card")).sort((a, b) => { return b.getAttribute("data-updated") < a.getAttribute("data-updated") ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "2") { // 下载次数降序 Array.from(panelElement.querySelectorAll(".b3-card")).sort((a, b) => { return parseInt(b.querySelector(".b3-card__info").lastElementChild.textContent) < parseInt(a.querySelector(".b3-card__info").lastElementChild.textContent) ? -1 : 1; }).forEach((item) => { html += item.outerHTML; }); } else if (selectElement.value === "3") { // 下载次数升序 Array.from(panelElement.querySelectorAll(".b3-card")).sort((a, b) => { return parseInt(b.querySelector(".b3-card__info").lastElementChild.textContent) < parseInt(a.querySelector(".b3-card__info").lastElementChild.textContent) ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } localSort[selectElement.parentElement.parentElement.getAttribute("data-type")] = selectElement.value; localStorage.setItem(Constants.LOCAL_BAZAAR, JSON.stringify(localSort)); panelElement.querySelector(".b3-cards").innerHTML = html; } }); }); }, onBazaar(response: IWebSocketData, bazaarType: TBazaarType, reload: boolean) { let id = "#configBazaarTemplate"; if (bazaarType === "themes") { id = "#configBazaarTheme"; } else if (bazaarType === "icons") { id = "#configBazaarIcon"; } else if (bazaarType === "widgets") { id = "#configBazaarWidget"; } 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.getHTML(item, bazaarType); }); bazaar.data[bazaarType] = response.data.packages; element.innerHTML = `
${html}
`; const localSort = JSON.parse(localStorage.getItem(Constants.LOCAL_BAZAAR)); if (localSort[bazaarType.replace("s", "")] === "1") { html = ""; Array.from(element.querySelectorAll(".b3-card")).sort((a, b) => { return b.getAttribute("data-updated") < a.getAttribute("data-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 parseInt(b.querySelector(".b3-card__info").lastElementChild.textContent) < parseInt(a.querySelector(".b3-card__info").lastElementChild.textContent) ? -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 parseInt(b.querySelector(".b3-card__info").lastElementChild.textContent) < parseInt(a.querySelector(".b3-card__info").lastElementChild.textContent) ? 1 : -1; }).forEach((item) => { html += item.outerHTML; }); } element.innerHTML = `
${html}
`; if (reload) { appearance.onSetappearance(response.data.appearance); } } };