A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 240 lines 8.9 kB view raw
1import {isMac, isNotCtrl, isOnlyMeta} from "./compatibility"; 2import {Constants} from "../../constants"; 3 4// 是否匹配辅助键 ⌃⌥⇧⌘ 5export const matchAuxiliaryHotKey = (hotKey: string, event: KeyboardEvent) => { 6 if (hotKey.includes("⌃")) { 7 if (!event.ctrlKey) { 8 return false; 9 } 10 } else { 11 if (isMac() ? event.ctrlKey : (hotKey.includes("⌘") ? !event.ctrlKey : event.ctrlKey)) { 12 return false; 13 } 14 } 15 if (hotKey.includes("⌥")) { 16 if (!event.altKey) { 17 return false; 18 } 19 } else { 20 if (event.altKey) { 21 return false; 22 } 23 } 24 if (hotKey.includes("⇧")) { 25 if (!event.shiftKey) { 26 return false; 27 } 28 } else { 29 if (event.shiftKey) { 30 return false; 31 } 32 } 33 if (hotKey.includes("⌘")) { 34 if (isMac() ? !event.metaKey : !event.ctrlKey) { 35 return false; 36 } 37 } else { 38 if (isMac() ? event.metaKey : (hotKey.includes("⌃") ? !event.ctrlKey : event.ctrlKey)) { 39 return false; 40 } 41 } 42 return true; 43}; 44 45const replaceDirect = (hotKey: string, keyCode: string) => { 46 const hotKeys = hotKey.replace(keyCode, Constants.ZWSP).split(""); 47 hotKeys.forEach((item, index) => { 48 if (item === Constants.ZWSP) { 49 hotKeys[index] = keyCode; 50 } 51 }); 52 return hotKeys; 53}; 54 55export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { 56 if (!hotKey) { 57 return false; 58 } 59 60 // https://github.com/siyuan-note/siyuan/issues/9770 61 if (hotKey.startsWith("⌃") && !isMac()) { 62 if (hotKey === "⌃D") { 63 // https://github.com/siyuan-note/siyuan/issues/9841 64 return false; 65 } 66 hotKey = hotKey.replace("⌘", "").replace("⌃", "⌘") 67 .replace("⌘⇧", "⇧⌘") 68 .replace("⌘⌥⇧", "⌥⇧⌘") 69 .replace("⌘⌥", "⌥⌘"); 70 } 71 72 // [] 73 if (hotKey.indexOf("⇧") === -1 && hotKey.indexOf("⌘") === -1 && hotKey.indexOf("⌥") === -1 && hotKey.indexOf("⌃") === -1) { 74 if (isNotCtrl(event) && !event.altKey && !event.shiftKey && hotKey === Constants.KEYCODELIST[event.keyCode]) { 75 return true; 76 } 77 return false; 78 } 79 80 let hotKeys = hotKey.split(""); 81 if (hotKey.indexOf("F") > -1) { 82 hotKeys.forEach((item, index) => { 83 if (item === "F") { 84 // F1-F12 85 hotKeys[index] = "F" + hotKeys.splice(index + 1, 1); 86 if (hotKeys[index + 1]) { 87 hotKeys[index + 1] += hotKeys.splice(index + 1, 1); 88 } 89 } 90 }); 91 } else if (hotKey.indexOf("PageUp") > -1) { 92 hotKeys = replaceDirect(hotKey, "PageUp"); 93 } else if (hotKey.indexOf("PageDown") > -1) { 94 hotKeys = replaceDirect(hotKey, "PageDown"); 95 } else if (hotKey.indexOf("Home") > -1) { 96 hotKeys = replaceDirect(hotKey, "Home"); 97 } else if (hotKey.indexOf("End") > -1) { 98 hotKeys = replaceDirect(hotKey, "End"); 99 } 100 101 // 是否匹配 ⇧[] 102 if (hotKey.startsWith("⇧") && hotKeys.length === 2) { 103 if (isNotCtrl(event) && !event.altKey && event.shiftKey && hotKeys[1] === Constants.KEYCODELIST[event.keyCode]) { 104 return true; 105 } 106 return false; 107 } 108 109 if (hotKey.startsWith("⌥")) { 110 let keyCode = hotKeys.length === 3 ? hotKeys[2] : hotKeys[1]; 111 if (hotKeys.length === 4) { 112 keyCode = hotKeys[3]; 113 } 114 const isMatchKey = keyCode === Constants.KEYCODELIST[event.keyCode]; 115 // 是否匹配 ⌥[] / ⌥⌘[] 116 if (isMatchKey && event.altKey && !event.shiftKey && hotKeys.length < 4 && 117 (hotKeys.length === 3 ? (isOnlyMeta(event) && hotKey.startsWith("⌥⌘")) : isNotCtrl(event))) { 118 return true; 119 } 120 // ⌥⇧⌘[] 121 if (isMatchKey && hotKey.startsWith("⌥⇧⌘") && hotKeys.length === 4 && 122 event.altKey && event.shiftKey && isOnlyMeta(event)) { 123 return true; 124 } 125 // ⌥⇧[] 126 if (isMatchKey && hotKey.startsWith("⌥⇧") && hotKeys.length === 3 && 127 event.altKey && event.shiftKey && isNotCtrl(event)) { 128 return true; 129 } 130 return false; 131 } 132 133 // 是否匹配 ⌃[] / ⌃⌘[] / ⌃⌥[] / ⌃⇧[]/ ⌃⌥⇧[] 134 if (hotKey.startsWith("⌃")) { 135 if (!isMac()) { 136 return false; 137 } 138 let keyCode = hotKeys.length === 3 ? hotKeys[2] : hotKeys[1]; 139 if (hotKeys.length === 4) { 140 keyCode = hotKeys[3]; 141 } else if (hotKeys.length === 5) { 142 keyCode = hotKeys[4]; 143 } 144 145 const isMatchKey = keyCode === Constants.KEYCODELIST[event.keyCode]; 146 // 是否匹配 ⌃[] / ⌃⌘[] 147 if (isMatchKey && event.ctrlKey && !event.altKey && !event.shiftKey && hotKeys.length < 4 && 148 (hotKeys.length === 3 ? (event.metaKey && hotKey.startsWith("⌃⌘")) : !event.metaKey)) { 149 return true; 150 } 151 // ⌃⇧[] 152 if (isMatchKey && hotKey.startsWith("⌃⇧") && hotKeys.length === 3 && 153 event.ctrlKey && !event.altKey && event.shiftKey && !event.metaKey) { 154 return true; 155 } 156 // ⌃⌥[] 157 if (isMatchKey && hotKey.startsWith("⌃⌥") && hotKeys.length === 3 && 158 event.ctrlKey && event.altKey && !event.shiftKey && !event.metaKey) { 159 return true; 160 } 161 // ⌃⌥⇧[] / ⌃⌥⌘[] / ⌃⇧⌘[] 162 if (isMatchKey && hotKeys.length === 4 && event.ctrlKey && 163 ( 164 (hotKey.startsWith("⌃⌥⇧") && event.shiftKey && !event.metaKey && event.altKey) || 165 (hotKey.startsWith("⌃⌥⌘") && !event.shiftKey && event.metaKey && event.altKey) || 166 (hotKey.startsWith("⌃⇧⌘") && event.shiftKey && event.metaKey && !event.altKey) 167 ) 168 ) { 169 return true; 170 } 171 172 // ⌃⌥⇧⌘[] 173 if (isMatchKey && hotKeys.length === 5 && event.ctrlKey && event.shiftKey && event.metaKey && event.altKey) { 174 return true; 175 } 176 return false; 177 } 178 179 // 是否匹配 ⇧⌘[] / ⌘[] 180 const hasShift = hotKeys.length > 2 && (hotKeys[0] === "⇧"); 181 if (isOnlyMeta(event) && !event.altKey && ((!hasShift && !event.shiftKey) || (hasShift && event.shiftKey))) { 182 return (hasShift ? hotKeys[2] : hotKeys[1]) === Constants.KEYCODELIST[event.keyCode]; 183 } 184 return false; 185}; 186 187export const isIncludesHotKey = (hotKey: string) => { 188 let isInclude = false; 189 Object.keys(window.siyuan.config.keymap).find(key => { 190 const item = window.siyuan.config.keymap[key as "editor"]; 191 Object.keys(item).find(key2 => { 192 const item2 = item[key2 as "general"]; 193 if (typeof item2.custom === "string") { 194 if (item2.custom === hotKey) { 195 isInclude = true; 196 return true; 197 } 198 } else { 199 Object.keys(item2).forEach(key3 => { 200 const item3: Config.IKey = item2[key3]; 201 if (item3.custom === hotKey) { 202 isInclude = true; 203 return true; 204 } 205 }); 206 if (isInclude) { 207 return true; 208 } 209 } 210 }); 211 212 if (isInclude) { 213 return true; 214 } 215 }); 216 217 return isInclude; 218}; 219 220export const updateControlAlt = () => { 221 if (!window.siyuan.config.keymap.general) { 222 return; 223 } 224 Object.keys(window.siyuan.config.keymap.general).forEach(key => { 225 if (["fileTree", "outline", "bookmark", "tag", "dailyNote", "inbox", "backlinks", 226 "graphView", "globalGraph", "riffCard"].includes(key)) { 227 if (navigator.platform.toUpperCase().indexOf("MAC") > -1) { 228 window.siyuan.config.keymap.general[key].default = window.siyuan.config.keymap.general[key].default.replace("⌥", "⌃"); 229 if (window.siyuan.config.keymap.general[key].default === window.siyuan.config.keymap.general[key].custom) { 230 window.siyuan.config.keymap.general[key].custom = window.siyuan.config.keymap.general[key].default.replace("⌥", "⌃"); 231 } 232 } else { 233 window.siyuan.config.keymap.general[key].default = window.siyuan.config.keymap.general[key].default.replace("⌃", "⌥"); 234 if (window.siyuan.config.keymap.general[key].default === window.siyuan.config.keymap.general[key].custom) { 235 window.siyuan.config.keymap.general[key].custom = window.siyuan.config.keymap.general[key].default.replace("⌃", "⌥"); 236 } 237 } 238 } 239 }); 240};