A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 615 lines 26 kB view raw
1import {Constants} from "../constants"; 2import {fetchPost} from "../util/fetch"; 3/// #if !MOBILE 4import {exportLayout} from "../layout/util"; 5/// #endif 6import {getAllEditor, getAllModels} from "../layout/getAll"; 7import {getDockByType} from "../layout/tabUtil"; 8import {Files} from "../layout/dock/Files"; 9/// #if !BROWSER 10import {ipcRenderer} from "electron"; 11/// #endif 12import {hideMessage, showMessage} from "./message"; 13import {Dialog} from "./index"; 14import {isMobile} from "../util/functions"; 15import {confirmDialog} from "./confirmDialog"; 16import {escapeHtml} from "../util/escape"; 17import {getWorkspaceName} from "../util/noRelyPCFunction"; 18import {needSubscribe} from "../util/needSubscribe"; 19import {redirectToCheckAuth, setNoteBook} from "../util/pathName"; 20import {reloadProtyle} from "../protyle/util/reload"; 21import {Tab} from "../layout/Tab"; 22import {setEmpty} from "../mobile/util/setEmpty"; 23import {hideAllElements, hideElements} from "../protyle/ui/hideElements"; 24import {App} from "../index"; 25import {saveScroll} from "../protyle/scroll/saveScroll"; 26import {isInAndroid, isInHarmony, isInIOS, setStorageVal} from "../protyle/util/compatibility"; 27import {Plugin} from "../plugin"; 28 29const updateTitle = (rootID: string, tab: Tab, protyle?: IProtyle) => { 30 fetchPost("/api/block/getDocInfo", { 31 id: rootID 32 }, (response) => { 33 tab.updateTitle(response.data.name); 34 if (protyle && protyle.title) { 35 protyle.title.setTitle(response.data.name); 36 } 37 }); 38}; 39 40export const reloadSync = ( 41 app: App, 42 data: { upsertRootIDs: string[], removeRootIDs: string[] }, 43 hideMsg = true, 44 // 同步的时候需要更新只读状态 https://github.com/siyuan-note/siyuan/issues/11517 45 // 调整大纲的时候需要使用现有状态 https://github.com/siyuan-note/siyuan/issues/11808 46 updateReadonly = true, 47 onlyUpdateDoc = false 48) => { 49 if (hideMsg) { 50 hideMessage(); 51 } 52 /// #if MOBILE 53 if (window.siyuan.mobile.popEditor) { 54 if (data.removeRootIDs.includes(window.siyuan.mobile.popEditor.protyle.block.rootID)) { 55 hideElements(["dialog"]); 56 } else { 57 reloadProtyle(window.siyuan.mobile.popEditor.protyle, false, updateReadonly); 58 } 59 } 60 if (window.siyuan.mobile.editor) { 61 if (data.removeRootIDs.includes(window.siyuan.mobile.editor.protyle.block.rootID)) { 62 setEmpty(app); 63 } else { 64 reloadProtyle(window.siyuan.mobile.editor.protyle, false, updateReadonly); 65 fetchPost("/api/block/getDocInfo", { 66 id: window.siyuan.mobile.editor.protyle.block.rootID 67 }, (response) => { 68 setTitle(response.data.name); 69 window.siyuan.mobile.editor.protyle.title.setTitle(response.data.name); 70 }); 71 } 72 } 73 setNoteBook(() => { 74 window.siyuan.mobile.docks.file.init(false); 75 }); 76 /// #else 77 const allModels = getAllModels(); 78 allModels.editor.forEach(item => { 79 if (data.upsertRootIDs.includes(item.editor.protyle.block.rootID)) { 80 fetchPost("/api/block/getDocInfo", { 81 id: item.editor.protyle.block.rootID, 82 }, (response) => { 83 item.editor.protyle.wysiwyg.renderCustom(response.data.ial); 84 reloadProtyle(item.editor.protyle, false, updateReadonly); 85 updateTitle(item.editor.protyle.block.rootID, item.parent, item.editor.protyle); 86 }); 87 } else if (data.removeRootIDs.includes(item.editor.protyle.block.rootID)) { 88 item.parent.parent.removeTab(item.parent.id, false, false); 89 delete window.siyuan.storage[Constants.LOCAL_FILEPOSITION][item.editor.protyle.block.rootID]; 90 setStorageVal(Constants.LOCAL_FILEPOSITION, window.siyuan.storage[Constants.LOCAL_FILEPOSITION]); 91 } 92 }); 93 allModels.graph.forEach(item => { 94 if (item.type === "local" && data.removeRootIDs.includes(item.rootId)) { 95 item.parent.parent.removeTab(item.parent.id, false, false); 96 } else if (item.type !== "local" || data.upsertRootIDs.includes(item.rootId)) { 97 item.searchGraph(false); 98 if (item.type === "local") { 99 updateTitle(item.rootId, item.parent); 100 } 101 } 102 }); 103 allModels.outline.forEach(item => { 104 if (item.type === "local" && data.removeRootIDs.includes(item.blockId)) { 105 item.parent.parent.removeTab(item.parent.id, false, false); 106 } else if (item.type !== "local" || data.upsertRootIDs.includes(item.blockId)) { 107 fetchPost("/api/outline/getDocOutline", { 108 id: item.blockId, 109 preview: item.isPreview 110 }, response => { 111 item.update(response); 112 }); 113 if (item.type === "local") { 114 updateTitle(item.blockId, item.parent); 115 } 116 } 117 }); 118 allModels.backlink.forEach(item => { 119 if (item.type === "local" && data.removeRootIDs.includes(item.rootId)) { 120 item.parent.parent.removeTab(item.parent.id, false, false); 121 } else { 122 item.refresh(); 123 if (item.type === "local") { 124 updateTitle(item.rootId, item.parent); 125 } 126 } 127 }); 128 if (!onlyUpdateDoc) { 129 allModels.files.forEach(item => { 130 setNoteBook(() => { 131 item.init(false); 132 }); 133 }); 134 } 135 allModels.bookmark.forEach(item => { 136 item.update(); 137 }); 138 allModels.tag.forEach(item => { 139 item.update(); 140 }); 141 // NOTE asset 无法获取推送地址,先不处理 142 allModels.search.forEach(item => { 143 item.parent.panelElement.querySelector("#searchInput").dispatchEvent(new CustomEvent("input")); 144 }); 145 allModels.custom.forEach(item => { 146 if (item.update) { 147 item.update(); 148 } 149 }); 150 /// #endif 151}; 152 153export const setRefDynamicText = (data: { 154 "blockID": string, 155 "defBlockID": string, 156 "refText": string, 157 "rootID": string 158}) => { 159 getAllEditor().forEach(editor => { 160 // 不能对比 rootId,否则嵌入块中的锚文本无法更新 161 editor.protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${data.blockID}"] span[data-type~="block-ref"][data-subtype="d"][data-id="${data.defBlockID}"]`).forEach(item => { 162 item.innerHTML = data.refText; 163 }); 164 }); 165}; 166 167export const setDefRefCount = (data: { 168 "blockID": string, 169 "refCount": number, 170 "rootRefCount": number, 171 "rootID": string 172}) => { 173 getAllEditor().forEach(editor => { 174 if (editor.protyle.block.rootID === data.rootID && editor.protyle.title) { 175 const attrElement = editor.protyle.title.element.querySelector(".protyle-attr"); 176 const countElement = attrElement.querySelector(".protyle-attr--refcount"); 177 if (countElement) { 178 if (data.rootRefCount === 0) { 179 countElement.remove(); 180 } else { 181 countElement.textContent = data.rootRefCount.toString(); 182 } 183 } else if (data.rootRefCount > 0) { 184 attrElement.insertAdjacentHTML("beforeend", `<div class="protyle-attr--refcount popover__block">${data.rootRefCount}</div>`); 185 } 186 } 187 if (data.rootID === data.blockID) { 188 return; 189 } 190 // 不能对比 rootId,否则嵌入块中的锚文本无法更新 191 editor.protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${data.blockID}"]`).forEach(item => { 192 // 不能直接查询,否则列表中会获取到第一个列表项的 attr https://github.com/siyuan-note/siyuan/issues/12738 193 const countElement = item.lastElementChild.querySelector(".protyle-attr--refcount"); 194 if (countElement) { 195 if (data.refCount === 0) { 196 countElement.remove(); 197 } else { 198 countElement.textContent = data.refCount.toString(); 199 } 200 } else if (data.refCount > 0) { 201 const attrElement = item.lastElementChild; 202 if (attrElement.childElementCount > 0) { 203 attrElement.lastElementChild.insertAdjacentHTML("afterend", `<div class="protyle-attr--refcount popover__block">${data.refCount}</div>`); 204 } else { 205 attrElement.innerHTML = `<div class="protyle-attr--refcount popover__block">${data.refCount}</div>${Constants.ZWSP}`; 206 } 207 } 208 if (data.refCount === 0) { 209 item.removeAttribute("refcount"); 210 } else { 211 item.setAttribute("refcount", data.refCount.toString()); 212 } 213 }); 214 }); 215 216 let liElement; 217 /// #if MOBILE 218 liElement = window.siyuan.mobile.docks.file.element.querySelector(`li[data-node-id="${data.rootID}"]`); 219 /// #else 220 liElement = (getDockByType("file").data.file as Files).element.querySelector(`li[data-node-id="${data.rootID}"]`); 221 /// #endif 222 if (liElement) { 223 const counterElement = liElement.querySelector(".counter"); 224 if (counterElement) { 225 if (data.rootRefCount === 0) { 226 counterElement.remove(); 227 } else { 228 counterElement.textContent = data.rootRefCount.toString(); 229 } 230 } else if (data.rootRefCount > 0) { 231 liElement.insertAdjacentHTML("beforeend", `<span class="popover__block counter b3-tooltips b3-tooltips__nw" aria-label="${window.siyuan.languages.ref}">${data.rootRefCount}</span>`); 232 } 233 } 234}; 235 236export const lockScreen = (app: App) => { 237 if (window.siyuan.config.readonly) { 238 return; 239 } 240 app.plugins.forEach(item => { 241 item.eventBus.emit("lock-screen"); 242 }); 243 /// #if BROWSER 244 fetchPost("/api/system/logoutAuth", {}, () => { 245 redirectToCheckAuth(); 246 }); 247 /// #else 248 ipcRenderer.send(Constants.SIYUAN_SEND_WINDOWS, {cmd: "lockscreen"}); 249 /// #endif 250}; 251 252export const kernelError = () => { 253 if (document.querySelector("#errorLog")) { 254 return; 255 } 256 let title = `💔 ${window.siyuan.languages.kernelFault0} <small>v${Constants.SIYUAN_VERSION}</small>`; 257 let body = `<div>${window.siyuan.languages.kernelFault1}</div><div class="fn__hr"></div><div>${window.siyuan.languages.kernelFault2}</div>`; 258 if (isInIOS()) { 259 title = `🍵 ${window.siyuan.languages.pleaseWait} <small>v${Constants.SIYUAN_VERSION}</small>`; 260 body = `<div>${window.siyuan.languages.reconnectPrompt}</div><div class="fn__hr"></div><div class="fn__flex"><div class="fn__flex-1"></div><button class="b3-button">${window.siyuan.languages.retry}</button></div>`; 261 } 262 const dialog = new Dialog({ 263 disableClose: true, 264 title: title, 265 width: isMobile() ? "92vw" : "520px", 266 content: `<div class="b3-dialog__content"> 267<div class="ft__breakword"> 268 ${body} 269</div> 270</div>` 271 }); 272 dialog.element.id = "errorLog"; 273 dialog.element.setAttribute("data-key", Constants.DIALOG_KERNELFAULT); 274 const restartElement = dialog.element.querySelector(".b3-button"); 275 if (restartElement) { 276 restartElement.addEventListener("click", () => { 277 dialog.destroy(); 278 window.webkit.messageHandlers.startKernelFast.postMessage("startKernelFast"); 279 }); 280 } 281}; 282 283export const exitSiYuan = async () => { 284 hideAllElements(["util"]); 285 /// #if MOBILE 286 if (window.siyuan.mobile.editor) { 287 await saveScroll(window.siyuan.mobile.editor.protyle); 288 } 289 /// #endif 290 fetchPost("/api/system/exit", {force: false}, (response) => { 291 if (response.code === 1) { // 同步执行失败 292 const msgId = showMessage(response.msg, response.data.closeTimeout, "error"); 293 const buttonElement = document.querySelector(`#message [data-id="${msgId}"] button`); 294 if (buttonElement) { 295 buttonElement.addEventListener("click", () => { 296 fetchPost("/api/system/exit", {force: true}, () => { 297 /// #if !BROWSER 298 ipcRenderer.send(Constants.SIYUAN_QUIT, location.port); 299 /// #else 300 if (isInIOS() || isInAndroid() || isInHarmony()) { 301 window.location.href = "siyuan://api/system/exit"; 302 } 303 /// #endif 304 }); 305 }); 306 } 307 } else if (response.code === 2) { // 提示新安装包 308 hideMessage(); 309 310 if ("std" === window.siyuan.config.system.container) { 311 ipcRenderer.send(Constants.SIYUAN_SHOW_WINDOW); 312 } 313 314 confirmDialog(window.siyuan.languages.tip, response.msg, () => { 315 fetchPost("/api/system/exit", { 316 force: true, 317 execInstallPkg: 2 // 0:默认检查新版本,1:不执行新版本安装,2:执行新版本安装 318 }, () => { 319 /// #if !BROWSER 320 // 桌面端退出拉起更新安装时有时需要重启两次 https://github.com/siyuan-note/siyuan/issues/6544 321 // 这里先将主界面隐藏 322 setTimeout(() => { 323 ipcRenderer.send(Constants.SIYUAN_CMD, "hide"); 324 }, 2000); 325 // 然后等待一段时间后再退出,避免界面主进程退出以后内核子进程被杀死 326 setTimeout(() => { 327 ipcRenderer.send(Constants.SIYUAN_QUIT, location.port); 328 }, 4000); 329 /// #endif 330 }); 331 }, () => { 332 fetchPost("/api/system/exit", { 333 force: true, 334 execInstallPkg: 1 // 0:默认检查新版本,1:不执行新版本安装,2:执行新版本安装 335 }, () => { 336 /// #if !BROWSER 337 ipcRenderer.send(Constants.SIYUAN_QUIT, location.port); 338 /// #endif 339 }); 340 }); 341 } else { // 正常退出 342 /// #if !BROWSER 343 ipcRenderer.send(Constants.SIYUAN_QUIT, location.port); 344 /// #else 345 if (isInIOS() || isInAndroid() || isInHarmony()) { 346 window.location.href = "siyuan://api/system/exit"; 347 } 348 /// #endif 349 } 350 }); 351}; 352 353export const transactionError = () => { 354 if (document.getElementById("transactionError")) { 355 return; 356 } 357 const dialog = new Dialog({ 358 disableClose: true, 359 title: `${window.siyuan.languages.stateExcepted} v${Constants.SIYUAN_VERSION}`, 360 content: `<div class="b3-dialog__content" id="transactionError">${window.siyuan.languages.rebuildIndexTip}</div> 361<div class="b3-dialog__action"> 362 <button class="b3-button b3-button--text">${window.siyuan.languages._kernel[97]}</button> 363 <div class="fn__space"></div> 364 <button class="b3-button">${window.siyuan.languages.rebuildIndex}</button> 365</div>`, 366 width: isMobile() ? "92vw" : "520px", 367 }); 368 dialog.element.setAttribute("data-key", Constants.DIALOG_STATEEXCEPTED); 369 const btnsElement = dialog.element.querySelectorAll(".b3-button"); 370 btnsElement[0].addEventListener("click", () => { 371 /// #if MOBILE 372 exitSiYuan(); 373 /// #else 374 exportLayout({ 375 errorExit: true, 376 cb: exitSiYuan 377 }); 378 /// #endif 379 }); 380 btnsElement[1].addEventListener("click", () => { 381 refreshFileTree(); 382 dialog.destroy(); 383 }); 384}; 385 386export const refreshFileTree = (cb?: () => void) => { 387 window.siyuan.storage[Constants.LOCAL_FILEPOSITION] = {}; 388 setStorageVal(Constants.LOCAL_FILEPOSITION, window.siyuan.storage[Constants.LOCAL_FILEPOSITION]); 389 fetchPost("/api/system/rebuildDataIndex", {}, () => { 390 if (cb) { 391 cb(); 392 } 393 }); 394}; 395 396let statusTimeout: number; 397export const progressStatus = (data: IWebSocketData) => { 398 const statusElement = document.querySelector("#status") as HTMLElement; 399 if (!statusElement) { 400 return; 401 } 402 403 if (isMobile()) { 404 if (!document.querySelector("#keyboardToolbar").classList.contains("fn__none")) { 405 return; 406 } 407 clearTimeout(statusTimeout); 408 statusElement.innerHTML = data.msg; 409 statusElement.style.bottom = "0"; 410 statusTimeout = window.setTimeout(() => { 411 statusElement.style.bottom = ""; 412 }, 12000); 413 } else { 414 const msgElement = statusElement.querySelector(".status__msg"); 415 if (msgElement) { 416 clearTimeout(statusTimeout); 417 msgElement.innerHTML = data.msg; 418 statusTimeout = window.setTimeout(() => { 419 msgElement.innerHTML = ""; 420 }, 12000); 421 } 422 } 423}; 424 425export const progressLoading = (data: IWebSocketData) => { 426 let progressElement = document.getElementById("progress"); 427 if (!progressElement) { 428 document.body.insertAdjacentHTML("beforeend", `<div id="progress" style="z-index: ${++window.siyuan.zIndex}"></div>`); 429 progressElement = document.getElementById("progress"); 430 } 431 // code 0: 有进度;1: 无进度;2: 关闭 432 if (data.code === 2) { 433 progressElement.remove(); 434 return; 435 } 436 if (data.code === 0) { 437 progressElement.innerHTML = `<div class="b3-dialog__scrim" style="opacity: 1"></div> 438<div class="b3-dialog__loading"> 439 <div style="text-align: right">${data.data.current}/${data.data.total}</div> 440 <div style="margin: 8px 0;height: 8px;border-radius: var(--b3-border-radius);overflow: hidden;background-color:#fff;"><div style="width: ${data.data.current / data.data.total * 100}%;transition: var(--b3-transition);background-color: var(--b3-theme-primary);height: 8px;"></div></div> 441 <div class="ft__breakword">${data.msg}</div> 442</div>`; 443 } else if (data.code === 1) { 444 if (progressElement.lastElementChild) { 445 progressElement.lastElementChild.lastElementChild.innerHTML = data.msg; 446 } else { 447 progressElement.innerHTML = `<div class="b3-dialog__scrim" style="opacity: 1"></div> 448<div class="b3-dialog__loading"> 449 <div style="margin: 8px 0;height: 8px;border-radius: var(--b3-border-radius);overflow: hidden;background-color:#fff;"><div style="background-color: var(--b3-theme-primary);height: 8px;background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);animation: stripMove 450ms linear infinite;background-size: 50px 50px;"></div></div> 450 <div class="ft__breakword">${data.msg}</div> 451</div>`; 452 } 453 } 454}; 455 456export const progressBackgroundTask = (tasks: { action: string }[]) => { 457 const backgroundTaskElement = document.querySelector(".status__backgroundtask"); 458 if (!backgroundTaskElement) { 459 return; 460 } 461 if (tasks.length === 0) { 462 backgroundTaskElement.classList.add("fn__none"); 463 if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && 464 window.siyuan.menus.menu.element.getAttribute("data-name") === Constants.MENU_STATUS_BACKGROUND_TASK) { 465 window.siyuan.menus.menu.remove(); 466 } 467 } else { 468 backgroundTaskElement.classList.remove("fn__none"); 469 backgroundTaskElement.setAttribute("data-tasks", JSON.stringify(tasks)); 470 backgroundTaskElement.innerHTML = tasks[0].action + "<div><div></div></div>"; 471 } 472}; 473 474export const bootSync = () => { 475 fetchPost("/api/sync/getBootSync", {}, response => { 476 if (response.code === 1) { 477 const dialog = new Dialog({ 478 width: isMobile() ? "92vw" : "50vw", 479 title: "🌩️ " + window.siyuan.languages.bootSyncFailed, 480 content: `<div class="b3-dialog__content">${response.msg}</div> 481<div class="b3-dialog__action"> 482 <button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div> 483 <button class="b3-button b3-button--text">${window.siyuan.languages.syncNow}</button> 484</div>` 485 }); 486 dialog.element.setAttribute("data-key", Constants.DIALOG_BOOTSYNCFAILED); 487 const btnsElement = dialog.element.querySelectorAll(".b3-button"); 488 btnsElement[0].addEventListener("click", () => { 489 dialog.destroy(); 490 }); 491 btnsElement[1].addEventListener("click", () => { 492 if (btnsElement[1].getAttribute("disabled")) { 493 return; 494 } 495 btnsElement[1].setAttribute("disabled", "disabled"); 496 fetchPost("/api/sync/performBootSync", {}, (syncResponse) => { 497 if (syncResponse.code === 0) { 498 dialog.destroy(); 499 } 500 btnsElement[1].removeAttribute("disabled"); 501 }); 502 }); 503 } 504 }); 505}; 506 507export const setTitle = (title: string) => { 508 const dragElement = document.getElementById("drag"); 509 const workspaceName = getWorkspaceName(); 510 if (title === window.siyuan.languages.siyuanNote) { 511 const versionTitle = `${workspaceName} - ${window.siyuan.languages.siyuanNote} v${Constants.SIYUAN_VERSION}`; 512 document.title = versionTitle; 513 if (dragElement) { 514 dragElement.textContent = versionTitle; 515 dragElement.setAttribute("title", versionTitle); 516 } 517 } else { 518 title = title || window.siyuan.languages.untitled; 519 document.title = `${title} - ${workspaceName} - ${window.siyuan.languages.siyuanNote} v${Constants.SIYUAN_VERSION}`; 520 if (!dragElement) { 521 return; 522 } 523 dragElement.setAttribute("title", title); 524 dragElement.innerHTML = escapeHtml(title); 525 } 526}; 527 528export const downloadProgress = (data: { id: string, percent: number }) => { 529 const bazzarSideElement = document.querySelector("#configBazaarReadme .item__side"); 530 if (!bazzarSideElement) { 531 return; 532 } 533 if (data.id !== JSON.parse(bazzarSideElement.getAttribute("data-obj")).repoURL) { 534 return; 535 } 536 const btnElement = bazzarSideElement.querySelector('[data-type="install"]') as HTMLElement; 537 if (btnElement) { 538 if (data.percent >= 1) { 539 btnElement.parentElement.classList.add("fn__none"); 540 btnElement.parentElement.nextElementSibling.classList.add("fn__none"); 541 } else { 542 btnElement.classList.add("b3-button--progress"); 543 btnElement.parentElement.nextElementSibling.firstElementChild.classList.add("b3-button--progress"); 544 btnElement.innerHTML = `<span style="width: ${data.percent * 100}%"></span>`; 545 btnElement.parentElement.nextElementSibling.firstElementChild.innerHTML = `<span style="width: ${data.percent * 100}%"></span>`; 546 } 547 } 548}; 549 550export const processSync = (data?: IWebSocketData, plugins?: Plugin[]) => { 551 /// #if MOBILE 552 const menuSyncUseElement = document.querySelector("#menuSyncNow use"); 553 const barSyncUseElement = document.querySelector("#toolbarSync use"); 554 if (!data) { 555 if (!window.siyuan.config.sync.enabled || (0 === window.siyuan.config.sync.provider && needSubscribe(""))) { 556 menuSyncUseElement?.setAttribute("xlink:href", "#iconCloudOff"); 557 barSyncUseElement.setAttribute("xlink:href", "#iconCloudOff"); 558 } else { 559 menuSyncUseElement?.setAttribute("xlink:href", "#iconCloudSucc"); 560 barSyncUseElement.setAttribute("xlink:href", "#iconCloudSucc"); 561 } 562 return; 563 } 564 menuSyncUseElement?.parentElement.classList.remove("fn__rotate"); 565 barSyncUseElement.parentElement.classList.remove("fn__rotate"); 566 if (data.code === 0) { // syncing 567 menuSyncUseElement?.parentElement.classList.add("fn__rotate"); 568 barSyncUseElement.parentElement.classList.add("fn__rotate"); 569 menuSyncUseElement?.setAttribute("xlink:href", "#iconRefresh"); 570 barSyncUseElement.setAttribute("xlink:href", "#iconRefresh"); 571 } else if (data.code === 2) { // error 572 menuSyncUseElement?.setAttribute("xlink:href", "#iconCloudError"); 573 barSyncUseElement.setAttribute("xlink:href", "#iconCloudError"); 574 } else if (data.code === 1) { // success 575 menuSyncUseElement?.setAttribute("xlink:href", "#iconCloudSucc"); 576 barSyncUseElement.setAttribute("xlink:href", "#iconCloudSucc"); 577 } 578 /// #else 579 const iconElement = document.querySelector("#barSync"); 580 if (!iconElement) { 581 return; 582 } 583 const useElement = iconElement.querySelector("use"); 584 if (!data) { 585 iconElement.classList.remove("toolbar__item--active"); 586 if (!window.siyuan.config.sync.enabled || (0 === window.siyuan.config.sync.provider && needSubscribe(""))) { 587 useElement.setAttribute("xlink:href", "#iconCloudOff"); 588 } else { 589 useElement.setAttribute("xlink:href", "#iconCloudSucc"); 590 } 591 return; 592 } 593 iconElement.firstElementChild.classList.remove("fn__rotate"); 594 if (data.code === 0) { // syncing 595 iconElement.classList.add("toolbar__item--active"); 596 iconElement.firstElementChild.classList.add("fn__rotate"); 597 useElement.setAttribute("xlink:href", "#iconRefresh"); 598 } else if (data.code === 2) { // error 599 iconElement.classList.remove("toolbar__item--active"); 600 useElement.setAttribute("xlink:href", "#iconCloudError"); 601 } else if (data.code === 1) { // success 602 iconElement.classList.remove("toolbar__item--active"); 603 useElement.setAttribute("xlink:href", "#iconCloudSucc"); 604 } 605 /// #endif 606 plugins.forEach((item) => { 607 if (data.code === 0) { 608 item.eventBus.emit("sync-start", data); 609 } else if (data.code === 1) { 610 item.eventBus.emit("sync-end", data); 611 } else if (data.code === 2) { 612 item.eventBus.emit("sync-fail", data); 613 } 614 }); 615};