A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 245 lines 12 kB view raw
1import {matchHotKey} from "../../util/hotKey"; 2import {deleteRow, insertRows, selectRow} from "./row"; 3import {addDragFill, cellScrollIntoView, popTextCell, updateCellsValue} from "./cell"; 4import {avContextmenu} from "./action"; 5import {hasClosestByClassName} from "../../util/hasClosest"; 6import {Constants} from "../../../constants"; 7import {upDownHint} from "../../../util/upDownHint"; 8import {clearSelect} from "../../util/clearSelect"; 9 10export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyle: IProtyle) => { 11 if (!nodeElement.classList.contains("av") || !window.siyuan.menus.menu.element.classList.contains("fn__none")) { 12 return false; 13 } 14 if (event.isComposing) { 15 return true; 16 } 17 // 避免浏览器默认快捷键 18 if (matchHotKey("⌘B", event) || matchHotKey("⌘I", event) || matchHotKey("⌘U", event)) { 19 event.preventDefault(); 20 return true; 21 } 22 const selectCellElement = nodeElement.querySelector(".av__cell--select") as HTMLElement; 23 if (selectCellElement) { 24 const rowElement = hasClosestByClassName(selectCellElement, "av__row"); 25 if (!rowElement || rowElement.dataset.type === "ghost") { 26 return false; 27 } 28 const avPanelElement = document.querySelector(".av__panel"); 29 if (avPanelElement && 30 (event.key === "Backspace" || event.key === "Delete" || event.key === "Escape" || 31 event.key.startsWith("ArrowLeft") || event.key === "Enter" || matchHotKey("⇥", event) || 32 matchHotKey("⇧⇥", event))) { 33 avPanelElement.remove(); 34 event.preventDefault(); 35 event.stopPropagation(); 36 return true; 37 } 38 // 需在 avPanelElement 之后,否则点击资源单元格后删除,资源面板不会更新 39 if (event.key === "Backspace" || event.key === "Delete") { 40 updateCellsValue(protyle, nodeElement, undefined, Array.from(nodeElement.querySelectorAll(".av__cell--active, .av__cell--select"))); 41 event.preventDefault(); 42 return true; 43 } 44 if (event.key === "Escape") { 45 clearSelect(["cell"], nodeElement); 46 selectRow(rowElement.querySelector(".av__firstcol"), "select"); 47 event.preventDefault(); 48 return true; 49 } 50 if (event.key === "Enter") { 51 popTextCell(protyle, [selectCellElement]); 52 event.preventDefault(); 53 return true; 54 } 55 let newCellElement; 56 if (event.key === "ArrowLeft" || matchHotKey("⇧⇥", event)) { 57 const previousRowElement = rowElement.previousElementSibling; 58 if (selectCellElement.previousElementSibling && !selectCellElement.previousElementSibling.classList.contains("av__firstcol")) { 59 if (selectCellElement.previousElementSibling.classList.contains("av__colsticky")) { 60 newCellElement = selectCellElement.previousElementSibling.lastElementChild; 61 if (newCellElement.classList.contains("av__firstcol")) { 62 newCellElement = undefined; 63 } 64 } else if (selectCellElement.previousElementSibling.classList.contains("av__cell")) { 65 newCellElement = selectCellElement.previousElementSibling; 66 } 67 } 68 if (!newCellElement && previousRowElement && !previousRowElement.classList.contains("av__row--header")) { 69 const previousCellElements = previousRowElement.querySelectorAll(".av__cell"); 70 newCellElement = previousCellElements[previousCellElements.length - 1]; 71 } 72 if (newCellElement) { 73 clearSelect(["cell"], nodeElement); 74 newCellElement.classList.add("av__cell--select"); 75 addDragFill(newCellElement); 76 cellScrollIntoView(nodeElement, newCellElement, false); 77 } 78 event.preventDefault(); 79 return true; 80 } 81 if (event.key === "ArrowRight" || matchHotKey("⇥", event)) { 82 const nextRowElement = rowElement.nextElementSibling; 83 if (selectCellElement.nextElementSibling && selectCellElement.nextElementSibling.classList.contains("av__cell")) { 84 newCellElement = selectCellElement.nextElementSibling; 85 } else if (!selectCellElement.nextElementSibling && selectCellElement.parentElement.nextElementSibling) { 86 // pin 87 newCellElement = selectCellElement.parentElement.nextElementSibling; 88 } else if (nextRowElement && !nextRowElement.classList.contains("av__row--footer")) { 89 newCellElement = nextRowElement.querySelector(".av__cell"); 90 } 91 if (newCellElement) { 92 clearSelect(["cell"], nodeElement); 93 newCellElement.classList.add("av__cell--select"); 94 addDragFill(newCellElement); 95 cellScrollIntoView(nodeElement, newCellElement, false); 96 } else if (event.key !== "ArrowRight") { 97 clearSelect(["cell"], nodeElement); 98 insertRows({ 99 blockElement: nodeElement, 100 protyle, 101 count: 1, 102 previousID: rowElement.getAttribute("data-id"), 103 groupID: rowElement.parentElement.getAttribute("data-group-id") 104 }); 105 } 106 event.preventDefault(); 107 return true; 108 } 109 if (event.key === "ArrowUp") { 110 const previousRowElement = rowElement.previousElementSibling; 111 if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) { 112 newCellElement = previousRowElement.querySelector(`.av__cell[data-col-id="${selectCellElement.dataset.colId}"]`); 113 } 114 if (newCellElement) { 115 clearSelect(["cell"], nodeElement); 116 newCellElement.classList.add("av__cell--select"); 117 addDragFill(newCellElement); 118 cellScrollIntoView(nodeElement, newCellElement); 119 } 120 event.preventDefault(); 121 return true; 122 } 123 if (event.key === "ArrowDown") { 124 const nextRowElement = rowElement.nextElementSibling; 125 if (nextRowElement && !nextRowElement.classList.contains("av__row--footer")) { 126 newCellElement = nextRowElement.querySelector(`.av__cell[data-col-id="${selectCellElement.dataset.colId}"]`); 127 } 128 if (newCellElement) { 129 clearSelect(["cell"], nodeElement); 130 newCellElement.classList.add("av__cell--select"); 131 addDragFill(newCellElement); 132 cellScrollIntoView(nodeElement, newCellElement); 133 } 134 event.preventDefault(); 135 return true; 136 } 137 138 if (!Constants.KEYCODELIST[event.keyCode] || 139 (Constants.KEYCODELIST[event.keyCode].length === 1 && 140 !event.metaKey && !event.ctrlKey && 141 !["⇧", "⌃", "⌥", "⌘"].includes(Constants.KEYCODELIST[event.keyCode]))) { 142 if (!selectCellElement.style.backgroundColor) { 143 popTextCell(protyle, [selectCellElement]); 144 } else { 145 event.preventDefault(); 146 } 147 return true; 148 } 149 } 150 const selectRowElements = nodeElement.querySelectorAll(".av__row--select:not(.av__row--header)"); 151 if (selectRowElements.length > 0) { 152 if (matchHotKey("⌘/", event)) { 153 event.stopPropagation(); 154 event.preventDefault(); 155 avContextmenu(protyle, selectRowElements[0] as HTMLElement, { 156 x: nodeElement.querySelector(".layout-tab-bar").getBoundingClientRect().left, 157 y: selectRowElements[0].getBoundingClientRect().bottom 158 }); 159 return true; 160 } 161 if (event.key === "Escape") { 162 event.preventDefault(); 163 selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); 164 return true; 165 } 166 if (event.key === "Backspace") { 167 event.preventDefault(); 168 deleteRow(nodeElement, protyle); 169 return true; 170 } 171 if (event.key === "Enter") { 172 selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); 173 popTextCell(protyle, [selectRowElements[0].querySelector(".av__cell")]); 174 event.preventDefault(); 175 return true; 176 } 177 // TODO event.shiftKey 178 if (event.key === "ArrowUp") { 179 const previousRowElement = selectRowElements[0].previousElementSibling; 180 selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); 181 if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) { 182 selectRow(previousRowElement.querySelector(".av__firstcol"), "select"); 183 cellScrollIntoView(nodeElement, previousRowElement); 184 } else { 185 nodeElement.classList.add("protyle-wysiwyg--select"); 186 } 187 event.preventDefault(); 188 return true; 189 } 190 if (event.key === "ArrowDown") { 191 const nextRowElement = selectRowElements[selectRowElements.length - 1].nextElementSibling; 192 selectRow(selectRowElements[0].querySelector(".av__firstcol"), "unselectAll"); 193 if (nextRowElement && !nextRowElement.classList.contains("av__row--util")) { 194 selectRow(nextRowElement.querySelector(".av__firstcol"), "select"); 195 cellScrollIntoView(nodeElement, nextRowElement); 196 } else { 197 nodeElement.classList.add("protyle-wysiwyg--select"); 198 } 199 event.preventDefault(); 200 return true; 201 } 202 } 203 return false; 204}; 205 206export const bindAVPanelKeydown = (event: KeyboardEvent) => { 207 const avPanelElement = document.querySelector(".av__panel"); 208 if (avPanelElement && window.siyuan.menus.menu.element.classList.contains("fn__none")) { 209 if ((avPanelElement.querySelector('[data-type="goSearchRollupCol"]') && !avPanelElement.querySelector(".b3-text-field")) || 210 avPanelElement.querySelector('[data-type="addAssetExist"]')) { 211 const menuElement = avPanelElement.querySelector(".b3-menu__items"); 212 if (event.key === "Enter") { 213 const currentElement = menuElement.querySelector(".b3-menu__item--current"); 214 if (currentElement) { 215 const editElement = currentElement.querySelector('[data-type="editAssetItem"]'); 216 const uploadElement = currentElement.querySelector(".b3-form__upload"); 217 if (editElement) { 218 avPanelElement.dispatchEvent(new CustomEvent("click", { 219 detail: { 220 type: editElement.getAttribute("data-type"), 221 target: editElement 222 } 223 })); 224 } else if (uploadElement) { 225 uploadElement.dispatchEvent(new MouseEvent("click", {bubbles: true})); 226 } else { 227 avPanelElement.dispatchEvent(new CustomEvent("click", { 228 detail: { 229 type: currentElement.getAttribute("data-type"), 230 target: currentElement 231 } 232 })); 233 } 234 return true; 235 } 236 } else if (event.key === "Escape") { 237 avPanelElement.dispatchEvent(new CustomEvent("click", {detail: "close"})); 238 return true; 239 } else if (upDownHint(menuElement, event, "b3-menu__item--current", menuElement.firstElementChild)) { 240 return true; 241 } 242 } 243 } 244 return false; 245};