A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 122 lines 6.5 kB view raw
1import {Constants} from "../../constants"; 2import {hideElements} from "../ui/hideElements"; 3import {fetchPost} from "../../util/fetch"; 4import {onGet} from "../util/onGet"; 5import {isMobile} from "../../util/functions"; 6import {hasClosestBlock, hasClosestByClassName} from "../util/hasClosest"; 7import {stickyRow} from "../render/av/row"; 8 9let getIndexTimeout: number; 10export const scrollEvent = (protyle: IProtyle, element: HTMLElement) => { 11 element.addEventListener("scroll", () => { 12 const elementRect = element.getBoundingClientRect(); 13 if (!protyle.toolbar.element.classList.contains("fn__none")) { 14 const initY = protyle.toolbar.element.getAttribute("data-inity").split(Constants.ZWSP); 15 const top = parseInt(initY[0]) + (parseInt(initY[1]) - element.scrollTop); 16 if (top < elementRect.top - protyle.toolbar.toolbarHeight || top > elementRect.bottom - protyle.toolbar.toolbarHeight) { 17 protyle.toolbar.element.style.display = "none"; 18 } else { 19 protyle.toolbar.element.style.top = top + "px"; 20 protyle.toolbar.element.style.display = ""; 21 } 22 } 23 24 protyle.wysiwyg.element.querySelectorAll(".av").forEach((item: HTMLElement) => { 25 if (item.dataset.render !== "true") { 26 return; 27 } 28 stickyRow(item, elementRect, "all"); 29 }); 30 31 if (!protyle.element.classList.contains("block__edit") && !isMobile()) { 32 protyle.contentElement.setAttribute("data-scrolltop", element.scrollTop.toString()); 33 } 34 35 if (!window.siyuan.dragElement) { // https://ld246.com/article/1649638389841 36 hideElements(["gutterOnly"], protyle); 37 } 38 39 if (protyle.scroll && !protyle.scroll.element.classList.contains("fn__none")) { 40 clearTimeout(getIndexTimeout); 41 getIndexTimeout = window.setTimeout(() => { 42 let targetElement = document.elementFromPoint(elementRect.left + elementRect.width / 2, elementRect.top + 10); 43 if (targetElement.classList.contains("protyle-wysiwyg")) { 44 // 恰好定位到块的中间时 45 targetElement = document.elementFromPoint(elementRect.left + elementRect.width / 2, elementRect.top + 20); 46 } 47 const blockElement = hasClosestBlock(targetElement); 48 if (!blockElement) { 49 if ((protyle.wysiwyg.element.firstElementChild.getAttribute("data-eof") === "1" || 50 // goHome 时 data-eof 不为 1 51 protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-index") === "0") && 52 (hasClosestByClassName(targetElement, "protyle-background") || hasClosestByClassName(targetElement, "protyle-title"))) { 53 const inputElement = protyle.scroll.element.querySelector(".b3-slider") as HTMLInputElement; 54 inputElement.value = "1"; 55 protyle.scroll.element.setAttribute("aria-label", `Blocks 1/${protyle.block.blockCount}`); 56 } 57 return; 58 } 59 protyle.scroll.updateIndex(protyle, blockElement.getAttribute("data-node-id")); 60 }, Constants.TIMEOUT_LOAD); 61 } 62 63 if (protyle.wysiwyg.element.getAttribute("data-top") || protyle.block.showAll || 64 (protyle.scroll && protyle.scroll.element.classList.contains("fn__none")) || !protyle.scroll || 65 protyle.scroll.lastScrollTop === element.scrollTop || protyle.scroll.lastScrollTop === -1 || 66 // 移动端跳转的时候会设置 wysiwyg.element.innerHTML = ""; 67 !protyle.wysiwyg.element.firstElementChild) { 68 return; 69 } 70 if (protyle.scroll.lastScrollTop > element.scrollTop) { 71 if (element.scrollTop === 0) { 72 // 使用鼠标拖拽滚动条中无法准确获取 scrollTop,在此忽略 73 return; 74 } 75 if (element.scrollTop < element.clientHeight && 76 protyle.wysiwyg.element.firstElementChild.getAttribute("data-eof") !== "1") { 77 // 禁用滚动时会产生抖动 https://ld246.com/article/1666717094418 78 protyle.contentElement.style.width = (protyle.contentElement.offsetWidth) + "px"; 79 protyle.contentElement.style.overflow = "hidden"; 80 protyle.wysiwyg.element.setAttribute("data-top", element.scrollTop.toString()); 81 fetchPost("/api/filetree/getDoc", { 82 id: protyle.wysiwyg.element.firstElementChild.getAttribute("data-node-id"), 83 mode: 1, 84 size: window.siyuan.config.editor.dynamicLoadBlocks, 85 }, getResponse => { 86 protyle.contentElement.style.overflow = ""; 87 protyle.contentElement.style.width = ""; 88 onGet({ 89 data: getResponse, 90 protyle, 91 action: [Constants.CB_GET_BEFORE, Constants.CB_GET_UNCHANGEID], 92 }); 93 }); 94 } 95 } else if ((element.scrollTop > element.scrollHeight - element.clientHeight * 1.8) && 96 protyle.wysiwyg.element.lastElementChild && 97 protyle.wysiwyg.element.lastElementChild.getAttribute("data-eof") !== "2") { 98 if (protyle.scroll.lastScrollTop > 768 && element.scrollTop > protyle.scroll.lastScrollTop * 2) { 99 // 使用鼠标拖拽滚动条时导致加载需进行矫正 100 element.scrollTop = protyle.scroll.lastScrollTop; 101 return; 102 } 103 protyle.wysiwyg.element.setAttribute("data-top", element.scrollTop.toString()); 104 fetchPost("/api/filetree/getDoc", { 105 id: protyle.wysiwyg.element.lastElementChild.getAttribute("data-node-id"), 106 mode: 2, 107 size: window.siyuan.config.editor.dynamicLoadBlocks, 108 }, getResponse => { 109 onGet({ 110 data: getResponse, 111 protyle, 112 action: [Constants.CB_GET_APPEND, Constants.CB_GET_UNCHANGEID], 113 }); 114 }); 115 } 116 protyle.scroll.lastScrollTop = Math.max(element.scrollTop, 0); 117 }, { 118 capture: false, 119 passive: true, 120 once: false 121 }); 122};