A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
1import {genUUID} from "../util/genID";
2import {Constants} from "../constants";
3
4export const initMessage = () => {
5 const messageElement = document.getElementById("message");
6 messageElement.innerHTML = '<div class="fn__flex-1"></div>';
7 messageElement.addEventListener("click", (event) => {
8 let target = event.target as HTMLElement;
9 while (target && !target.isEqualNode(messageElement)) {
10 if (target.classList.contains("b3-snackbar__close")) {
11 hideMessage(target.parentElement.getAttribute("data-id"));
12 event.preventDefault();
13 break;
14 } else if (target.tagName === "A" || target.tagName === "BUTTON") {
15 break;
16 } else if (target.classList.contains("b3-snackbar")) {
17 if (getSelection().rangeCount === 0 || !getSelection().getRangeAt(0).toString()) {
18 hideMessage(target.getAttribute("data-id"));
19 }
20 event.preventDefault();
21 event.stopPropagation();
22 break;
23 }
24 target = target.parentElement;
25 }
26 });
27
28 document.querySelectorAll("#tempMessage > div").forEach((item) => {
29 showMessage(item.innerHTML, parseInt(item.getAttribute("data-timeout")), item.getAttribute("data-type"), item.getAttribute("data-message-id"));
30 item.remove();
31 });
32};
33
34// type: info/error; timeout: 0 手动关闭;-1 永不关闭
35export const showMessage = (message: string, timeout = 6000, type = "info", messageId?: string) => {
36 const messagesElement = document.getElementById("message").firstElementChild;
37 if (!messagesElement) {
38 let tempMessages = document.getElementById("tempMessage");
39 if (!tempMessages) {
40 document.body.insertAdjacentHTML("beforeend", `<div style="font-size: 14px;top: 22px;position: fixed;z-index: 100;right: 30px;line-height: 20px;word-break: break-word;display: flex;flex-direction: column;align-items: flex-end;"
41id="tempMessage"></div>`);
42 tempMessages = document.getElementById("tempMessage");
43 }
44 tempMessages.insertAdjacentHTML("beforeend", `<div style="background: white;padding: 8px 16px;border-radius: 6px;margin-bottom: 16px;"
45data-timeout="${timeout}"
46data-type="${type}"
47data-message-id="${messageId || ""}">${message}</div>`);
48 return;
49 }
50 const id = messageId || genUUID();
51 const existElement = messagesElement.querySelector(`.b3-snackbar[data-id="${id}"]`);
52 const messageVersion = message + (type === "error" ? " v" + Constants.SIYUAN_VERSION : "");
53 if (existElement) {
54 window.clearTimeout(parseInt(existElement.getAttribute("data-timeoutid")));
55 existElement.innerHTML = `<div data-type="textMenu" class="b3-snackbar__content${timeout === 0 ? " b3-snackbar__content--close" : ""}">${messageVersion}</div>${timeout === 0 ? '<svg class="b3-snackbar__close"><use xlink:href="#iconCloseRound"></use></svg>' : ""}`;
56 if (type === "error") {
57 existElement.classList.add("b3-snackbar--error");
58 } else {
59 existElement.classList.remove("b3-snackbar--error");
60 }
61 if (timeout > 0) {
62 const timeoutId = window.setTimeout(() => {
63 hideMessage(id);
64 }, timeout);
65 existElement.setAttribute("data-timeoutid", timeoutId.toString());
66 }
67 return;
68 }
69 let messageHTML = `<div data-id="${id}" class="b3-snackbar--hide b3-snackbar${type === "error" ? " b3-snackbar--error" : ""}"><div data-type="textMenu" class="b3-snackbar__content${timeout === 0 ? " b3-snackbar__content--close" : ""}">${messageVersion}</div>`;
70 if (timeout === 0) {
71 messageHTML += '<svg class="b3-snackbar__close"><use xlink:href="#iconCloseRound"></use></svg>';
72 } else if (timeout !== -1) { // -1 时需等待请求完成后手动关闭
73 const timeoutId = window.setTimeout(() => {
74 hideMessage(id);
75 }, timeout);
76 messageHTML = messageHTML.replace("<div data-id", `<div data-timeoutid="${timeoutId}" data-id`);
77 }
78 messagesElement.parentElement.classList.add("b3-snackbars--show");
79 messagesElement.parentElement.style.zIndex = (++window.siyuan.zIndex).toString();
80 messagesElement.insertAdjacentHTML("afterbegin", messageHTML + "</div>");
81 setTimeout(() => {
82 messagesElement.querySelectorAll(".b3-snackbar--hide").forEach(item => {
83 item.classList.remove("b3-snackbar--hide");
84 });
85 });
86 if (messagesElement.firstElementChild.nextElementSibling &&
87 messagesElement.firstElementChild.nextElementSibling.innerHTML === messagesElement.firstElementChild.innerHTML) {
88 messagesElement.firstElementChild.nextElementSibling.remove();
89 }
90 messagesElement.scrollTo({
91 top: 0,
92 behavior: "smooth"
93 });
94 return id;
95};
96
97export const hideMessage = (id?: string) => {
98 const messagesElement = document.getElementById("message").firstElementChild;
99 if (!messagesElement) {
100 return;
101 }
102 if (id) {
103 const messageElement = messagesElement.querySelector(`[data-id="${id}"]`);
104 if (messageElement) {
105 messageElement.classList.add("b3-snackbar--hide");
106 window.clearTimeout(parseInt(messageElement.getAttribute("data-timeoutid")));
107 setTimeout(() => {
108 messageElement.remove();
109 if (messagesElement.childElementCount === 0) {
110 messagesElement.parentElement.classList.remove("b3-snackbars--show");
111 messagesElement.innerHTML = "";
112 }
113 }, Constants.TIMEOUT_INPUT);
114 }
115 let hasShowItem = false;
116 Array.from(messagesElement.children).find(item => {
117 if (!item.classList.contains("b3-snackbar--hide")) {
118 hasShowItem = true;
119 return true;
120 }
121 });
122 if (hasShowItem) {
123 messagesElement.parentElement.classList.add("b3-snackbars--show");
124 } else {
125 messagesElement.parentElement.classList.remove("b3-snackbars--show");
126 }
127 } else {
128 messagesElement.parentElement.classList.remove("b3-snackbars--show");
129 setTimeout(() => {
130 messagesElement.innerHTML = "";
131 }, Constants.TIMEOUT_INPUT);
132 }
133};