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 = `
${data.name}
${window.siyuan.languages.currentVer}
v${data.version}
${window.siyuan.languages.releaseDate}
${data.hUpdated}
${window.siyuan.languages.pkgSize}
${data.hSize}
`;
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);
}
}
};