A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
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};