/// #if !BROWSER
import {ipcRenderer, shell} from "electron";
import * as path from "path";
/// #endif
import {Constants} from "../constants";
import {exportLayout} from "../layout/util";
import * as Pickr from "@simonwep/pickr";
import {isBrowser} from "../util/functions";
import {fetchPost} from "../util/fetch";
import {loadAssets, renderSnippet} from "../util/assets";
import {genOptions} from "../util/genOptions";
import {hasClosestByClassName} from "../protyle/util/hasClosest";
export const appearance = {
element: undefined as Element,
genHTML: () => {
return `
${window.siyuan.languages.appearance1}
`;
},
onGetcustomcss: (data: Record>) => {
let customHTML = '';
Object.keys(data).forEach((item) => {
customHTML += `${window.siyuan.languages[item]}
`;
Object.keys(data[item]).forEach(subItem => {
customHTML += `
${window.siyuan.languages[subItem]}
`;
});
});
appearance.element.querySelector("#appearanceCustomPanel").innerHTML = customHTML;
const pickrs: Record> = {};
appearance.element.querySelectorAll("#appearanceCustomPanel .colorPicker").forEach((item: HTMLInputElement) => {
// @ts-ignore
const pickr = Pickr.create({
container: "#appearanceCustomPanel",
el: item,
theme: "nano",
default: item.getAttribute("data-value"),
comparison: false,
components: {
preview: true,
opacity: true,
hue: true,
interaction: {
input: true,
}
}
});
pickr.on("hide", () => {
appearance._sendCustomcss(pickrs);
});
pickr.on("changestop", () => {
appearance._sendCustomcss(pickrs);
});
const key = item.getAttribute("data-key");
if (!pickrs[key]) {
pickrs[key] = {};
}
pickrs[key][item.getAttribute("data-subkey")] = pickr;
});
},
_sendCustomcss: (pickrs: Record>) => {
const css: Record> = {};
Object.keys(pickrs).forEach((item) => {
css[item] = {};
Object.keys(pickrs[item]).forEach(subItem => {
css[item][subItem] = pickrs[item][subItem].getColor().toRGBA().toString(0);
});
});
fetchPost("/api/setting/setCustomCSS", {
theme: appearance.element.querySelector("#appearanceCustomName").textContent,
css
});
},
_send: () => {
const themeLight = (appearance.element.querySelector("#themeLight") as HTMLSelectElement).value;
const themeDark = (appearance.element.querySelector("#themeDark") as HTMLSelectElement).value;
const modeElementValue = parseInt((appearance.element.querySelector("#mode") as HTMLSelectElement).value);
fetchPost("/api/setting/setAppearance", {
icon: (appearance.element.querySelector("#icon") as HTMLSelectElement).value,
mode: modeElementValue === 2 ? window.siyuan.config.appearance.mode : modeElementValue,
modeOS: modeElementValue === 2,
codeBlockThemeDark: (appearance.element.querySelector("#codeBlockThemeDark") as HTMLSelectElement).value,
codeBlockThemeLight: (appearance.element.querySelector("#codeBlockThemeLight") as HTMLSelectElement).value,
themeDark,
themeLight,
darkThemes: window.siyuan.config.appearance.darkThemes,
lightThemes: window.siyuan.config.appearance.lightThemes,
icons: window.siyuan.config.appearance.icons,
lang: (appearance.element.querySelector("#lang") as HTMLSelectElement).value,
customCSS: window.siyuan.config.appearance.customCSS,
closeButtonBehavior: (appearance.element.querySelector("#closeButtonBehavior") as HTMLInputElement).checked ? 1 : 0,
nativeEmoji: (appearance.element.querySelector("#nativeEmoji") as HTMLInputElement).checked,
hideStatusBar: (appearance.element.querySelector("#hideStatusBar") as HTMLInputElement).checked,
}, response => {
if ((
window.siyuan.config.appearance.themeJS && !response.data.modeOS &&
(
response.data.mode !== window.siyuan.config.appearance.mode ||
window.siyuan.config.appearance.themeLight !== response.data.themeLight ||
window.siyuan.config.appearance.themeDark !== response.data.themeDark
)
) ||
(response.data.modeOS && !window.siyuan.config.appearance.modeOS)
) {
exportLayout(true);
return;
}
appearance.onSetappearance(response.data);
if (response.data.hideStatusBar) {
document.getElementById("status").classList.add("fn__none");
} else {
document.getElementById("status").classList.remove("fn__none");
}
});
},
_bindSnippet: (element: HTMLElement) => {
const itemContentElement = hasClosestByClassName(element, "b3-label");
if (!itemContentElement) {
return
}
fetchPost("/api/snippet/setSnippet", {
id: itemContentElement.getAttribute("data-id"),
name: itemContentElement.querySelector("input").value,
type: itemContentElement.querySelector(".b3-chip").textContent,
content: itemContentElement.querySelector("textarea").value,
enabled: (itemContentElement.querySelector(".b3-switch") as HTMLInputElement).checked
}, (response) => {
itemContentElement.setAttribute("data-id", response.data.id)
renderSnippet();
})
},
_genSnippet: (options: ISnippet) => {
return ``
},
bindEvent: () => {
if (window.siyuan.config.appearance.customCSS) {
fetchPost("/api/setting/getCustomCSS", {
theme: appearance.element.querySelector("#appearanceCustomName").textContent
}, response => {
appearance.onGetcustomcss(response.data);
});
}
const codeSnippetPanelElement = appearance.element.querySelector("#codeSnippetPanel");
const codeSnippetElement = appearance.element.querySelector("#codeSnippet");
codeSnippetElement.addEventListener("click", () => {
if (codeSnippetPanelElement.innerHTML) {
codeSnippetPanelElement.innerHTML = "";
return;
}
fetchPost("/api/snippet/getSnippet", {type: "all", enabled: 2}, (response) => {
let html = `
`;
response.data.snippets.forEach((item: ISnippet) => {
html += appearance._genSnippet(item);
});
codeSnippetPanelElement.innerHTML = html;
response.data.snippets.forEach((item: ISnippet) => {
const nameElement = (codeSnippetPanelElement.querySelector(`[data-id="${item.id}"] input`) as HTMLInputElement)
nameElement.value = item.name;
const contentElement = codeSnippetPanelElement.querySelector(`[data-id="${item.id}"] textarea`) as HTMLTextAreaElement;
contentElement.textContent = item.content;
nameElement.addEventListener("blur", (event) => {
appearance._bindSnippet(nameElement);
})
contentElement.addEventListener("blur", (event) => {
appearance._bindSnippet(contentElement);
})
codeSnippetPanelElement.querySelector(`[data-id="${item.id}"] .b3-switch`).addEventListener("change", (event) => {
appearance._bindSnippet(contentElement);
})
});
});
});
codeSnippetPanelElement.addEventListener("click", (event) => {
const target = event.target as HTMLElement;
if (target.id === "addCodeSnippetCSS" || target.id === "addCodeSnippetJS") {
target.parentElement.insertAdjacentHTML("afterend", appearance._genSnippet({
type: target.id === "addCodeSnippetCSS" ? "css" : "js",
name: "",
content: "",
enabled: false
}))
codeSnippetPanelElement.querySelector(".b3-text-field").addEventListener("blur", (event) => {
appearance._bindSnippet(event.target as HTMLElement);
})
codeSnippetPanelElement.querySelector("textarea.b3-text-field").addEventListener("blur", (event) => {
appearance._bindSnippet(event.target as HTMLElement);
})
codeSnippetPanelElement.querySelector('.b3-switch').addEventListener("change", (event) => {
appearance._bindSnippet(event.target as HTMLElement);
})
return;
}
const removeElement = hasClosestByClassName(target, "b3-tooltips")
if (removeElement) {
const id = removeElement.parentElement.parentElement.getAttribute("data-id");
removeElement.parentElement.parentElement.remove();
if (!id) {
return;
}
fetchPost("/api/snippet/removeSnippet", {
id
}, (response) => {
const exitElement = document.getElementById(`snippet${response.data.type === "css" ? "CSS" : "JS"}${response.data.id}`) as HTMLScriptElement;
if (exitElement) {
exitElement.remove();
}
})
}
})
const appearanceCustomElement = appearance.element.querySelector("#appearanceCustom");
appearanceCustomElement.addEventListener("click", () => {
if (window.siyuan.config.appearance.customCSS) {
window.siyuan.config.appearance.customCSS = false;
appearanceCustomElement.textContent = window.siyuan.languages.open;
appearance.element.querySelector("#appearanceCustomPanel").innerHTML = "";
} else {
window.siyuan.config.appearance.customCSS = true;
fetchPost("/api/setting/getCustomCSS", {
theme: appearance.element.querySelector("#appearanceCustomName").textContent
}, response => {
appearance.onGetcustomcss(response.data);
});
appearanceCustomElement.textContent = window.siyuan.languages.close;
}
appearance._send();
});
appearance.element.querySelector("#resetLayout").addEventListener("click", () => {
fetchPost("/api/system/setUILayout", {layout: {}}, () => {
window.location.reload();
});
});
/// #if !BROWSER
appearance.element.querySelector("#appearanceOpenIcon").addEventListener("click", () => {
shell.openPath(path.join(window.siyuan.config.system.confDir, "appearance", "icons"));
});
appearance.element.querySelector("#appearanceOpenTheme").addEventListener("click", () => {
shell.openPath(path.join(window.siyuan.config.system.confDir, "appearance", "themes"));
});
appearance.element.querySelector("#appearanceOpenEmoji").addEventListener("click", () => {
shell.openPath(path.join(window.siyuan.config.system.dataDir, "emojis"));
});
appearance.element.querySelector("#appearanceRefresh").addEventListener("click", () => {
exportLayout(true);
});
/// #endif
appearance.element.querySelectorAll("select").forEach(item => {
item.addEventListener("change", () => {
appearance._send();
});
});
appearance.element.querySelectorAll(".b3-switch").forEach((item) => {
item.addEventListener("change", () => {
appearance._send();
});
});
},
onSetappearance(data: IAppearance, needLoadAsset = true) {
if (data.lang !== window.siyuan.config.appearance.lang || data.nativeEmoji !== window.siyuan.config.appearance.nativeEmoji) {
exportLayout(true);
return;
}
window.siyuan.config.appearance = data;
if (appearance.element) {
const theme = data.mode === 0 ? data.themeLight : data.themeDark;
const modeElement = appearance.element.querySelector("#mode") as HTMLSelectElement;
if (modeElement) {
if (data.modeOS) {
modeElement.value = "2";
} else {
modeElement.value = data.mode === 0 ? "0" : "1";
}
appearance.element.querySelector("#appearanceCustomName").textContent = theme;
}
const themeLightElement = appearance.element.querySelector("#themeLight") as HTMLSelectElement;
if (themeLightElement) {
themeLightElement.innerHTML = genOptions(window.siyuan.config.appearance.lightThemes, window.siyuan.config.appearance.themeLight);
}
const themeDarkElement = appearance.element.querySelector("#themeDark") as HTMLSelectElement;
if (themeDarkElement) {
themeDarkElement.innerHTML = genOptions(window.siyuan.config.appearance.darkThemes, window.siyuan.config.appearance.themeDark);
}
const iconElement = appearance.element.querySelector("#icon") as HTMLSelectElement;
if (iconElement) {
iconElement.innerHTML = genOptions(window.siyuan.config.appearance.icons, window.siyuan.config.appearance.icon);
}
if (data.customCSS) {
fetchPost("/api/setting/getCustomCSS", {
theme
}, response => {
appearance.onGetcustomcss(response.data);
});
}
}
/// #if !BROWSER
ipcRenderer.send(Constants.SIYUAN_CONFIG_THEME, data.modeOS ? "system" : (data.mode === 1 ? "dark" : "light"));
ipcRenderer.send(Constants.SIYUAN_CONFIG_CLOSE, data.closeButtonBehavior);
/// #endif
if (needLoadAsset) {
loadAssets(data);
}
document.querySelector("#barMode use").setAttribute("xlink:href", `#icon${window.siyuan.config.appearance.modeOS ? "Mode" : (window.siyuan.config.appearance.mode === 0 ? "Light" : "Dark")}`);
}
};