A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 246 lines 13 kB view raw
1import {getAllEditor, getAllModels} from "../../layout/getAll"; 2import {isWindow} from "../../util/functions"; 3import {hasClosestBlock, hasClosestByClassName, hasClosestByTag} from "../../protyle/util/hasClosest"; 4import {getColIndex} from "../../protyle/util/table"; 5 6const getRightBlock = (element: HTMLElement, x: number, y: number) => { 7 let index = 1; 8 let nodeElement = element; 9 if (nodeElement && nodeElement.classList.contains("protyle-action")) { 10 return nodeElement; 11 } 12 while (nodeElement && (nodeElement.classList.contains("list") || nodeElement.classList.contains("li"))) { 13 nodeElement = document.elementFromPoint(x + 73 * index, y) as HTMLElement; 14 nodeElement = hasClosestBlock(nodeElement) as HTMLElement; 15 index++; 16 } 17 return nodeElement; 18}; 19 20export const windowMouseMove = (event: MouseEvent, mouseIsEnter: boolean) => { 21 if (document.body.classList.contains("body--blur") || document.getElementById("progress")) { 22 // 非激活状态下不执行 https://ld246.com/article/1693474547631 23 return; 24 } 25 // https://github.com/siyuan-note/siyuan/pull/8793 26 const coordinates = window.siyuan.coordinates ?? (window.siyuan.coordinates = { 27 pageX: 0, 28 pageY: 0, 29 clientX: 0, 30 clientY: 0, 31 screenX: 0, 32 screenY: 0, 33 }); 34 coordinates.pageX = event.pageX; 35 coordinates.pageY = event.pageY; 36 coordinates.clientX = event.clientX; 37 coordinates.clientY = event.clientY; 38 coordinates.screenX = event.screenX; 39 coordinates.screenY = event.screenY; 40 41 // breadcrumb 42 if (window.siyuan.hideBreadcrumb) { 43 window.siyuan.hideBreadcrumb = false; 44 getAllEditor().forEach(item => { 45 if (item.protyle.breadcrumb?.element.classList.contains("protyle-breadcrumb__bar--hide")) { 46 item.protyle.breadcrumb.element.classList.remove("protyle-breadcrumb__bar--hide"); 47 item.protyle.breadcrumb.render(item.protyle, true); 48 } 49 }); 50 } 51 const target = event.target as Element; 52 // Dock 53 if (!mouseIsEnter && 54 event.buttons === 0 && // 鼠标按键被按下时不触发 55 window.siyuan.layout.bottomDock && 56 !isWindow()) { 57 if (event.clientX < Math.max(document.getElementById("dockLeft").clientWidth + 1, 16)) { 58 if (!window.siyuan.layout.leftDock.pin && window.siyuan.layout.leftDock.layout.element.clientWidth > 0 && 59 // 隐藏停靠栏会导致点击两侧内容触发浮动面板弹出,因此需减小鼠标范围 60 (window.siyuan.layout.leftDock.element.clientWidth > 0 || (window.siyuan.layout.leftDock.element.clientWidth === 0 && event.clientX < 8))) { 61 if (event.clientY > document.getElementById("toolbar").clientHeight && 62 event.clientY < window.innerHeight - document.getElementById("status").clientHeight - document.getElementById("dockBottom").clientHeight) { 63 if (!hasClosestByClassName(target, "b3-menu") && 64 !hasClosestByClassName(target, "protyle-toolbar") && 65 !hasClosestByClassName(target, "protyle-util") && 66 !hasClosestByClassName(target, "b3-dialog", true) && 67 !hasClosestByClassName(target, "layout--float")) { 68 window.siyuan.layout.leftDock.showDock(); 69 } 70 } else { 71 window.siyuan.layout.leftDock.hideDock(); 72 } 73 } 74 } else if (event.clientX > window.innerWidth - Math.max(document.getElementById("dockRight").clientWidth - 2, 16)) { 75 if (!window.siyuan.layout.rightDock.pin && window.siyuan.layout.rightDock.layout.element.clientWidth > 0 && 76 (window.siyuan.layout.rightDock.element.clientWidth > 0 || (window.siyuan.layout.rightDock.element.clientWidth === 0 && event.clientX > window.innerWidth - 8))) { 77 if (event.clientY > document.getElementById("toolbar").clientHeight && 78 event.clientY < window.innerHeight - document.getElementById("status").clientHeight - document.getElementById("dockBottom").clientHeight) { 79 if (!hasClosestByClassName(target, "b3-menu") && 80 !hasClosestByClassName(target, "layout--float") && 81 !hasClosestByClassName(target, "protyle-toolbar") && 82 !hasClosestByClassName(target, "protyle-util") && 83 !hasClosestByClassName(target, "b3-dialog", true)) { 84 window.siyuan.layout.rightDock.showDock(); 85 } 86 } else { 87 window.siyuan.layout.rightDock.hideDock(); 88 } 89 } 90 } 91 if (event.clientY > Math.min(window.innerHeight - 10, window.innerHeight - (window.siyuan.config.uiLayout.hideDock ? 0 : document.getElementById("dockBottom").clientHeight) - document.querySelector("#status").clientHeight)) { 92 window.siyuan.layout.bottomDock.showDock(); 93 } 94 } 95 96 // gutter 97 const eventPath0 = event.composedPath()[0] as HTMLElement; 98 if (eventPath0 && eventPath0.nodeType !== 3 && eventPath0.classList.contains("protyle-wysiwyg") && eventPath0.style.paddingLeft) { 99 // 光标在编辑器右边也需要进行显示 100 const mouseElement = document.elementFromPoint(eventPath0.getBoundingClientRect().left + parseInt(eventPath0.style.paddingLeft) + 13, event.clientY); 101 const blockElement = hasClosestBlock(mouseElement); 102 if (blockElement) { 103 const targetBlockElement = getRightBlock(blockElement, blockElement.getBoundingClientRect().left + 1, event.clientY); 104 if (!targetBlockElement) { 105 return; 106 } 107 let rowElement: Element; 108 if (targetBlockElement.classList.contains("av")) { 109 rowElement = hasClosestByClassName(mouseElement, "av__row") as HTMLElement; 110 } 111 const allModels = getAllModels(); 112 let findNode = false; 113 allModels.editor.find(item => { 114 if (item.editor.protyle.wysiwyg.element === eventPath0) { 115 item.editor.protyle.gutter.render(item.editor.protyle, targetBlockElement, item.editor.protyle.wysiwyg.element, rowElement); 116 findNode = true; 117 return true; 118 } 119 }); 120 if (!findNode) { 121 window.siyuan.blockPanels.find(item => { 122 item.editors.find(eItem => { 123 if (eItem.protyle.wysiwyg.element.contains(eventPath0)) { 124 eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element, rowElement); 125 findNode = true; 126 return true; 127 } 128 }); 129 if (findNode) { 130 return true; 131 } 132 }); 133 } 134 if (!findNode) { 135 allModels.backlink.find(item => { 136 item.editors.find(eItem => { 137 if (eItem.protyle.wysiwyg.element === eventPath0) { 138 eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element, rowElement); 139 findNode = true; 140 return true; 141 } 142 }); 143 if (findNode) { 144 return true; 145 } 146 }); 147 } 148 } 149 return; 150 } 151 if (eventPath0 && eventPath0.nodeType !== 3 && ( 152 eventPath0.classList.contains("li") || 153 eventPath0.classList.contains("list") || 154 (eventPath0.classList.contains("protyle-action") && eventPath0.getAttribute("data-type") === "NodeListItem") 155 )) { 156 // 光标在列表下部应显示右侧的元素,而不是列表本身 157 const targetBlockElement = getRightBlock(eventPath0, eventPath0.getBoundingClientRect().left + 1, event.clientY); 158 if (!targetBlockElement) { 159 return; 160 } 161 const allModels = getAllModels(); 162 let findNode = false; 163 allModels.editor.find(item => { 164 if (item.editor.protyle.wysiwyg.element.contains(eventPath0)) { 165 item.editor.protyle.gutter.render(item.editor.protyle, targetBlockElement, item.editor.protyle.wysiwyg.element); 166 findNode = true; 167 return true; 168 } 169 }); 170 if (!findNode) { 171 window.siyuan.blockPanels.find(item => { 172 item.editors.find(eItem => { 173 if (eItem.protyle.wysiwyg.element.contains(eventPath0)) { 174 eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element); 175 findNode = true; 176 return true; 177 } 178 }); 179 if (findNode) { 180 return true; 181 } 182 }); 183 } 184 if (!findNode) { 185 allModels.backlink.find(item => { 186 item.editors.find(eItem => { 187 if (eItem.protyle.wysiwyg.element.contains(eventPath0)) { 188 eItem.protyle.gutter.render(eItem.protyle, targetBlockElement, eItem.protyle.wysiwyg.element); 189 findNode = true; 190 return true; 191 } 192 }); 193 if (findNode) { 194 return true; 195 } 196 }); 197 } 198 return; 199 } 200 201 if (eventPath0 && eventPath0.nodeType !== 3 && eventPath0.classList.contains("av")) { 202 // 数据库居中时光标在数据库侧边 https://github.com/siyuan-note/siyuan/issues/13853 203 if (eventPath0.getAttribute("data-type") === "NodeAttributeView") { 204 const rowElement = hasClosestByClassName(document.elementFromPoint(eventPath0.firstElementChild.getBoundingClientRect().left + 10, event.clientY), "av__row"); 205 if (rowElement && !rowElement.classList.contains("av__row--header")) { 206 getAllEditor().find(item => { 207 if (item.protyle.wysiwyg.element.contains(eventPath0)) { 208 item.protyle.gutter.render(item.protyle, eventPath0, item.protyle.wysiwyg.element, rowElement); 209 return true; 210 } 211 }); 212 return; 213 } 214 } 215 } 216 217 if (!hasClosestByClassName(target, "protyle", true)) { 218 document.querySelectorAll(".protyle-gutters").forEach(item => { 219 item.classList.add("fn__none"); 220 item.innerHTML = ""; 221 }); 222 } 223 224 const blockElement = hasClosestByClassName(target, "table"); 225 if (blockElement && blockElement.style.cursor !== "col-resize" && !hasClosestByClassName(blockElement, "protyle-wysiwyg__embed")) { 226 const cellElement = (hasClosestByTag(target, "TH") || hasClosestByTag(target, "TD")) as HTMLTableCellElement; 227 const tableElement = blockElement.querySelector("table"); 228 if (cellElement && tableElement && tableElement.getAttribute("contenteditable") === "true") { 229 const tableHeight = blockElement.querySelector("table").clientHeight; 230 const resizeElement = blockElement.querySelector(".table__resize"); 231 if (blockElement.style.textAlign === "center" || blockElement.style.textAlign === "right") { 232 resizeElement.parentElement.style.left = tableElement.offsetLeft + "px"; 233 } else { 234 resizeElement.parentElement.style.left = ""; 235 } 236 const rect = cellElement.getBoundingClientRect(); 237 if (rect.right - event.clientX < 3 && rect.right - event.clientX > 0) { 238 resizeElement.setAttribute("data-col-index", (getColIndex(cellElement) + cellElement.colSpan - 1).toString()); 239 resizeElement.setAttribute("style", `height:${tableHeight}px;left: ${Math.round(cellElement.offsetWidth + cellElement.offsetLeft - blockElement.firstElementChild.scrollLeft - 3)}px;display:block`); 240 } else if (event.clientX - rect.left < 3 && event.clientX - rect.left > 0 && cellElement.previousElementSibling) { 241 resizeElement.setAttribute("data-col-index", (getColIndex(cellElement) - 1).toString()); 242 resizeElement.setAttribute("style", `height:${tableHeight}px;left: ${Math.round(cellElement.offsetLeft - blockElement.firstElementChild.scrollLeft - 3)}px;display:block`); 243 } 244 } 245 } 246};