diff --git a/app/src/boot/globalEvent/keydown.ts b/app/src/boot/globalEvent/keydown.ts index 42c3e318a..53b3a9c7d 100644 --- a/app/src/boot/globalEvent/keydown.ts +++ b/app/src/boot/globalEvent/keydown.ts @@ -1,4 +1,4 @@ -import {isCtrl, isMac, updateHotkeyTip, writeText} from "../../protyle/util/compatibility"; +import {isMac, isNotCtrl, isOnlyMeta, updateHotkeyTip, writeText} from "../../protyle/util/compatibility"; import {matchHotKey} from "../../protyle/util/hotKey"; import {openSearch} from "../../search/spread"; import { @@ -439,7 +439,7 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => { const liElements = Array.from(files.element.querySelectorAll(".b3-list-item--focus")); if (liElements.length === 0) { - if (event.key.startsWith("Arrow") && !isCtrl(event)) { + if (event.key.startsWith("Arrow") && isNotCtrl(event)) { const liElement = files.element.querySelector(".b3-list-item"); if (liElement) { liElement.classList.add("b3-list-item--focus"); @@ -572,7 +572,7 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => { } if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && (event.code.startsWith("Arrow") || event.code === "Enter") && - !event.altKey && !event.shiftKey && !isCtrl(event)) { + !event.altKey && !event.shiftKey && isNotCtrl(event)) { event.preventDefault(); return true; } @@ -629,7 +629,7 @@ const fileTreeKeydown = (app: App, event: KeyboardEvent) => { } } return; - } else if (!isCtrl(event)) { + } else if (isNotCtrl(event)) { files.element.querySelector('[select-end="true"]')?.removeAttribute("select-end"); files.element.querySelector('[select-start="true"]')?.removeAttribute("select-start"); if ((event.key === "ArrowRight" && !liElements[0].querySelector(".b3-list-item__arrow--open") && !liElements[0].querySelector(".b3-list-item__toggle").classList.contains("fn__hidden")) || @@ -957,7 +957,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { return; } const target = event.target as HTMLElement; - if (!event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey && + if (isNotCtrl(event) && !event.shiftKey && !event.altKey && !["INPUT", "TEXTAREA"].includes(target.tagName) && ["0", "1", "2", "3", "4", "j", "k", "l", ";", "s", " ", "p"].includes(event.key.toLowerCase())) { let cardElement: Element; @@ -978,15 +978,15 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { } // 仅处理以下快捷键操作 - if (!event.ctrlKey && !isCtrl(event) && event.key !== "Escape" && !event.shiftKey && !event.altKey && + if (isNotCtrl(event) && event.key !== "Escape" && !event.shiftKey && !event.altKey && Constants.KEYCODELIST[event.keyCode] !== "PageUp" && Constants.KEYCODELIST[event.keyCode] !== "PageDown" && !/^F\d{1,2}$/.test(event.key) && event.key.indexOf("Arrow") === -1 && event.key !== "Enter" && event.key !== "Backspace" && event.key !== "Delete") { return; } - if (!event.altKey && !event.shiftKey && isCtrl(event)) { - if (event.key === "Meta" || event.key === "Control" || event.ctrlKey || event.metaKey) { + if (!event.altKey && !event.shiftKey && isOnlyMeta(event)) { + if ((isMac() ? event.key === "Meta" : event.key === "Control") || isOnlyMeta(event)) { window.siyuan.ctrlIsPressed = true; if ((event.key === "Meta" || event.key === "Control") && window.siyuan.config.editor.floatWindowMode === 1 && !event.repeat) { @@ -997,7 +997,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { } } - if (!event.altKey && event.shiftKey && !isCtrl(event)) { + if (!event.altKey && event.shiftKey && isNotCtrl(event)) { if (event.key === "Shift") { window.siyuan.shiftIsPressed = true; if (!event.repeat) { @@ -1008,7 +1008,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { } } - if (event.altKey && !event.shiftKey && !isCtrl(event)) { + if (event.altKey && !event.shiftKey && isNotCtrl(event)) { if (event.key === "Alt") { window.siyuan.altIsPressed = true; } else { @@ -1016,6 +1016,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { } } + // mac 中只能使用 ⌃ if (switchDialog && event.ctrlKey && !event.metaKey && event.key.startsWith("Arrow")) { dialogArrow(app, switchDialog.element, event); return; @@ -1100,7 +1101,7 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => { return; } - if (!event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey && + if (isNotCtrl(event) && !event.shiftKey && !event.altKey && (event.key.startsWith("Arrow") || event.key === "Enter")) { const openRecentDocsDialog = window.siyuan.dialogs.find(item => { if (item.element.getAttribute("data-key") === window.siyuan.config.keymap.general.recentDocs.custom) { diff --git a/app/src/config/keymap.ts b/app/src/config/keymap.ts index 65ea63be4..c9aae57af 100644 --- a/app/src/config/keymap.ts +++ b/app/src/config/keymap.ts @@ -1,4 +1,4 @@ -import {isCtrl, isMac, updateHotkeyTip} from "../protyle/util/compatibility"; +import {isMac, updateHotkeyTip} from "../protyle/util/compatibility"; import {Constants} from "../constants"; import {hideMessage, showMessage} from "../dialog/message"; import {fetchPost} from "../util/fetch"; @@ -429,7 +429,7 @@ export const keymap = { }, _getKeymapString(event: KeyboardEvent) { let keymapStr = ""; - if (event.ctrlKey && !event.metaKey && isMac()) { + if (event.ctrlKey && isMac()) { keymapStr += "⌃"; } if (event.altKey) { @@ -438,7 +438,7 @@ export const keymap = { if (event.shiftKey) { keymapStr += "⇧"; } - if (isCtrl(event)) { + if (event.metaKey || (!isMac() && event.ctrlKey)) { keymapStr += "⌘"; } if (event.key !== "Shift" && event.key !== "Alt" && event.key !== "Meta" && event.key !== "Control" && event.key !== "Unidentified") { diff --git a/app/src/constants.ts b/app/src/constants.ts index afa5b8525..2ab743502 100644 --- a/app/src/constants.ts +++ b/app/src/constants.ts @@ -120,7 +120,7 @@ export abstract class Constants { 9: "⇥", 13: "↩", 16: "⇧", - 17: "⌘", + 17: "⌃", 18: "⌥", 19: "Pause", 20: "CapsLock", diff --git a/app/src/dialog/index.ts b/app/src/dialog/index.ts index fe6ad68e9..6da12b141 100644 --- a/app/src/dialog/index.ts +++ b/app/src/dialog/index.ts @@ -3,7 +3,7 @@ import {genUUID} from "../util/genID"; import {moveResize} from "./moveResize"; /// #endif import {isMobile} from "../util/functions"; -import {isCtrl} from "../protyle/util/compatibility"; +import {isNotCtrl} from "../protyle/util/compatibility"; import {Protyle} from "../protyle"; export class Dialog { @@ -104,7 +104,7 @@ export class Dialog { event.stopPropagation(); return; } - if (!event.shiftKey && !isCtrl(event) && event.key === "Enter" && enterEvent) { + if (!event.shiftKey && isNotCtrl(event) && event.key === "Enter" && enterEvent) { if (confirmElement) { confirmElement.dispatchEvent(new CustomEvent("click")); } else { diff --git a/app/src/layout/dock/Files.ts b/app/src/layout/dock/Files.ts index b41fb3011..afb8d80bd 100644 --- a/app/src/layout/dock/Files.ts +++ b/app/src/layout/dock/Files.ts @@ -14,7 +14,7 @@ import {fetchPost, fetchSyncPost} from "../../util/fetch"; import {openEmojiPanel, unicode2Emoji} from "../../emoji"; import {mountHelp, newNotebook} from "../../util/mount"; import {confirmDialog} from "../../dialog/confirmDialog"; -import {updateHotkeyTip} from "../../protyle/util/compatibility"; +import {isNotCtrl, isOnlyMeta, updateHotkeyTip} from "../../protyle/util/compatibility"; import {openFileById} from "../../editor/util"; import {hasClosestByAttribute, hasClosestByTag, hasTopClosestByTag} from "../../protyle/util/hasClosest"; import {isTouchDevice} from "../../util/functions"; @@ -243,7 +243,7 @@ export class Files extends Model { if (ulElement) { const notebookId = ulElement.getAttribute("data-url"); while (target && !target.isEqualNode(this.element)) { - if (!event.metaKey && !event.ctrlKey && target.classList.contains("b3-list-item__icon") && window.siyuan.config.system.container !== "ios") { + if (isNotCtrl(event) && target.classList.contains("b3-list-item__icon") && window.siyuan.config.system.container !== "ios") { event.preventDefault(); event.stopPropagation(); const rect = target.getBoundingClientRect(); @@ -263,14 +263,14 @@ export class Files extends Model { }); } break; - } else if (!event.metaKey && !event.ctrlKey && target.classList.contains("b3-list-item__toggle")) { + } else if (isNotCtrl(event) && target.classList.contains("b3-list-item__toggle")) { this.getLeaf(target.parentElement, notebookId); this.setCurrent(target.parentElement); event.preventDefault(); event.stopPropagation(); window.siyuan.menus.menu.remove(); break; - } else if (!event.metaKey && !event.ctrlKey && target.classList.contains("b3-list-item__action")) { + } else if (isNotCtrl(event) && target.classList.contains("b3-list-item__action")) { const type = target.getAttribute("data-type"); const pathString = target.parentElement.getAttribute("data-path"); if (!window.siyuan.config.readonly) { @@ -298,7 +298,7 @@ export class Files extends Model { event.stopPropagation(); break; } else if (target.tagName === "LI") { - if ((event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey) { + if (isOnlyMeta(event) && !event.altKey && !event.shiftKey) { target.classList.toggle("b3-list-item--focus"); } else { this.setCurrent(target, false); @@ -308,7 +308,7 @@ export class Files extends Model { return; } target.setAttribute("data-opening", "true"); - if (event.altKey && !event.metaKey && !event.ctrlKey && !event.shiftKey) { + if (event.altKey && isNotCtrl(event) && !event.shiftKey) { openFileById({ app: options.app, id: target.getAttribute("data-node-id"), @@ -318,7 +318,7 @@ export class Files extends Model { target.removeAttribute("data-opening"); } }); - } else if (!event.altKey && !event.metaKey && !event.ctrlKey && event.shiftKey) { + } else if (!event.altKey && isNotCtrl(event) && event.shiftKey) { openFileById({ app: options.app, id: target.getAttribute("data-node-id"), @@ -329,7 +329,7 @@ export class Files extends Model { } }); } else if (window.siyuan.config.fileTree.openFilesUseCurrentTab && - event.altKey && (event.metaKey || event.ctrlKey) && !event.shiftKey) { + event.altKey && isOnlyMeta(event) && !event.shiftKey) { openFileById({ app: options.app, removeCurrentTab: false, diff --git a/app/src/menus/Menu.ts b/app/src/menus/Menu.ts index a99250a0f..cb2080a9d 100644 --- a/app/src/menus/Menu.ts +++ b/app/src/menus/Menu.ts @@ -248,7 +248,7 @@ const getActionMenu = (element: Element, next: boolean) => { export const bindMenuKeydown = (event: KeyboardEvent) => { if (window.siyuan.menus.menu.element.classList.contains("fn__none") - || event.altKey || event.shiftKey || isCtrl(event)) { + || event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) { return false; } const target = event.target as HTMLElement; diff --git a/app/src/protyle/gutter/index.ts b/app/src/protyle/gutter/index.ts index d4997e96d..3914ef383 100644 --- a/app/src/protyle/gutter/index.ts +++ b/app/src/protyle/gutter/index.ts @@ -3,7 +3,7 @@ import {getIconByType} from "../../editor/getIcon"; import {enterBack, iframeMenu, setFold, tableMenu, videoMenu, zoomOut} from "../../menus/protyle"; import {MenuItem} from "../../menus/Menu"; import {copySubMenu, openAttr, openWechatNotify} from "../../menus/commonMenuItem"; -import {copyPlainText, isMac, updateHotkeyTip, writeText} from "../util/compatibility"; +import {copyPlainText, isMac, isOnlyMeta, updateHotkeyTip, writeText} from "../util/compatibility"; import { transaction, turnsIntoOneTransaction, @@ -170,7 +170,7 @@ export class Gutter { window.siyuan.menus.menu.remove(); return; } - if (event.ctrlKey || event.metaKey) { + if (isOnlyMeta(event)) { zoomOut({protyle, id}); } else if (event.altKey) { let foldElement: Element; diff --git a/app/src/protyle/hint/index.ts b/app/src/protyle/hint/index.ts index d66d4b8aa..9181488b7 100644 --- a/app/src/protyle/hint/index.ts +++ b/app/src/protyle/hint/index.ts @@ -30,7 +30,7 @@ import {openMobileFileById} from "../../mobile/editor"; import {processRender} from "../util/processCode"; import {AIChat} from "../../ai/chat"; import {isMobile} from "../../util/functions"; -import {isCtrl, isIPhone} from "../util/compatibility"; +import {isIPhone, isNotCtrl, isOnlyMeta} from "../util/compatibility"; import {avRender} from "../render/av/render"; import {genIconHTML} from "../render/util"; @@ -59,10 +59,10 @@ export class Hint { const btnElement = hasClosestByMatchTag(eventTarget, "BUTTON"); if (btnElement && !btnElement.classList.contains("emojis__item") && !btnElement.classList.contains("emojis__type")) { if (this.source !== "search") { - this.fill(decodeURIComponent(btnElement.getAttribute("data-value")), protyle, true, isCtrl(event)); + this.fill(decodeURIComponent(btnElement.getAttribute("data-value")), protyle, true, isOnlyMeta(event)); } else { setTimeout(() => { - this.fill(decodeURIComponent(btnElement.getAttribute("data-value")), protyle, true, !isCtrl(event)); + this.fill(decodeURIComponent(btnElement.getAttribute("data-value")), protyle, true, isNotCtrl(event)); }, 148); // 划选引用点击,需先重置 range } focusByRange(protyle.toolbar.range); @@ -302,7 +302,7 @@ ${unicode2Emoji(emoji.unicode)}`; upDownHint(this.element.lastElementChild, event); if (event.key === "Enter") { setTimeout(() => { - this.fill(decodeURIComponent(this.element.querySelector(".b3-list-item--focus").getAttribute("data-value")), protyle, true, !isCtrl(event)); + this.fill(decodeURIComponent(this.element.querySelector(".b3-list-item--focus").getAttribute("data-value")), protyle, true, isNotCtrl(event)); }, 148); // 划选引用点击,需先重置 range focusByRange(protyle.toolbar.range); event.preventDefault(); @@ -826,7 +826,7 @@ ${genHintItemHTML(item)} if (mark === Constants.ZWSP + 3) { (this.element.querySelector(".b3-list-item--focus input") as HTMLElement).click(); } else { - this.fill(mark, protyle, true, isCtrl(event)); + this.fill(mark, protyle, true, isOnlyMeta(event)); } } event.preventDefault(); diff --git a/app/src/protyle/preview/index.ts b/app/src/protyle/preview/index.ts index 7fda735f6..db3f72142 100644 --- a/app/src/protyle/preview/index.ts +++ b/app/src/protyle/preview/index.ts @@ -1,4 +1,4 @@ -import {openByMobile, writeText} from "../util/compatibility"; +import {isOnlyMeta, openByMobile, writeText} from "../util/compatibility"; import {focusByRange} from "../util/selection"; import {showMessage} from "../../dialog/message"; import {isLocalPath, pathPosix} from "../../util/pathName"; @@ -98,7 +98,7 @@ export class Preview { event.preventDefault(); if (isLocalPath(linkAddress)) { /// #if !MOBILE - if (event.metaKey || event.ctrlKey) { + if (isOnlyMeta(event)) { openBy(linkAddress, "folder"); } else if (event.shiftKey) { openBy(linkAddress, "app"); diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 14fac4a92..ef7903188 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -3,7 +3,7 @@ import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest"; import {openMenuPanel} from "./openMenuPanel"; import {Menu} from "../../../plugin/Menu"; import {updateAttrViewCellAnimation} from "./action"; -import {isCtrl} from "../../util/compatibility"; +import {isNotCtrl} from "../../util/compatibility"; import {objEquals} from "../../../util/functions"; import {fetchPost} from "../../../util/fetch"; import {focusBlock} from "../../util/selection"; @@ -444,7 +444,7 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type return; } if (event.key === "Escape" || - (event.key === "Enter" && !event.shiftKey && !isCtrl(event))) { + (event.key === "Enter" && !event.shiftKey && isNotCtrl(event))) { updateCellValue(protyle, type, cellElements); event.preventDefault(); event.stopPropagation(); diff --git a/app/src/protyle/util/compatibility.ts b/app/src/protyle/util/compatibility.ts index 4b9e33cbd..2fa71009c 100644 --- a/app/src/protyle/util/compatibility.ts +++ b/app/src/protyle/util/compatibility.ts @@ -73,8 +73,7 @@ export const getEventName = () => { } }; -// 区别 mac 上的 ctrl 和 meta -export const isCtrl = (event: KeyboardEvent | MouseEvent) => { +export const isOnlyMeta = (event: KeyboardEvent | MouseEvent) => { if (isMac()) { // mac if (event.metaKey && !event.ctrlKey) { @@ -89,6 +88,13 @@ export const isCtrl = (event: KeyboardEvent | MouseEvent) => { } }; +export const isNotCtrl = (event: KeyboardEvent | MouseEvent) => { + if (!event.metaKey && !event.ctrlKey) { + return true; + } + return false +} + export const isHuawei = () => { return window.siyuan.config.system.osPlatform.toLowerCase().indexOf("huawei") > -1; }; diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts index 523cd2289..32b3ca267 100644 --- a/app/src/protyle/util/editorCommonEvent.ts +++ b/app/src/protyle/util/editorCommonEvent.ts @@ -914,6 +914,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => { if (targetElement.parentElement.getAttribute("data-type") === "NodeSuperBlock" && targetElement.parentElement.getAttribute("data-sb-layout") === "col") { if (targetClass.includes("dragover__left") || targetClass.includes("dragover__right")) { + // Mac 上 ⌘ 无法进行拖拽 dragSame(protyle, sourceElements, targetElement, targetClass.includes("dragover__right"), event.ctrlKey); } else { dragSb(protyle, sourceElements, targetElement, targetClass.includes("dragover__bottom"), "row", event.ctrlKey); diff --git a/app/src/protyle/util/hotKey.ts b/app/src/protyle/util/hotKey.ts index 10d40c653..f4fea7195 100644 --- a/app/src/protyle/util/hotKey.ts +++ b/app/src/protyle/util/hotKey.ts @@ -1,4 +1,4 @@ -import {isCtrl} from "./compatibility"; +import {isNotCtrl, isOnlyMeta} from "./compatibility"; import {Constants} from "../../constants"; // 是否匹配 ⇧⌘[] / ⌘[] / ⌥[] / ⌥⌘[] / ⌥⇧[] / ⌥⇧⌘[] / ⇧[] / [] @@ -9,7 +9,7 @@ export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { // [] if (hotKey.indexOf("⇧") === -1 && hotKey.indexOf("⌘") === -1 && hotKey.indexOf("⌥") === -1 && hotKey.indexOf("⌃") === -1) { - if (!event.ctrlKey && !isCtrl(event) && !event.altKey && !event.shiftKey && hotKey === Constants.KEYCODELIST[event.keyCode]) { + if (isNotCtrl(event) && !event.altKey && !event.shiftKey && hotKey === Constants.KEYCODELIST[event.keyCode]) { return true; } return false; @@ -30,7 +30,7 @@ export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { // 是否匹配 ⇧[] if (hotKey.startsWith("⇧") && hotKeys.length === 2) { - if (!event.ctrlKey && !isCtrl(event) && !event.altKey && event.shiftKey && hotKeys[1] === Constants.KEYCODELIST[event.keyCode]) { + if (isNotCtrl(event) && !event.altKey && event.shiftKey && hotKeys[1] === Constants.KEYCODELIST[event.keyCode]) { return true; } return false; @@ -45,33 +45,35 @@ export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { const isMatchKey = keyCode === Constants.KEYCODELIST[event.keyCode]; // 是否匹配 ⌥[] / ⌥⌘[] if (isMatchKey && event.altKey && !event.shiftKey && - (hotKeys.length === 3 ? (isCtrl(event) && hotKey.startsWith("⌥⌘")) : !isCtrl(event))) { + (hotKeys.length === 3 ? (isOnlyMeta(event) && hotKey.startsWith("⌥⌘")) : isNotCtrl(event))) { return true; } // ⌥⇧⌘[] if (isMatchKey && hotKey.startsWith("⌥⇧⌘") && hotKeys.length === 4 && - event.altKey && event.shiftKey && isCtrl(event)) { + event.altKey && event.shiftKey && isOnlyMeta(event)) { return true; } // ⌥⇧[] if (isMatchKey && hotKey.startsWith("⌥⇧") && hotKeys.length === 3 && - event.altKey && event.shiftKey && !isCtrl(event)) { + event.altKey && event.shiftKey && isNotCtrl(event)) { return true; } return false; } - // 是否匹配 ⌃[] / ⌃⌥[] / ⌃⇧[]/ ⌃⌥⇧[] + // 是否匹配 ⌃[] / ⌃⌘[] / ⌃⌥[] / ⌃⇧[]/ ⌃⌥⇧[] if (hotKey.startsWith("⌃")) { let keyCode = hotKeys.length === 3 ? hotKeys[2] : hotKeys[1]; if (hotKeys.length === 4) { keyCode = hotKeys[3]; + } else if (hotKeys.length === 5) { + keyCode = hotKeys[4]; } const isMatchKey = keyCode === Constants.KEYCODELIST[event.keyCode]; - // 是否匹配 ⌃[] - if (isMatchKey && hotKeys.length === 2 && - event.ctrlKey && !event.altKey && !event.shiftKey && !event.metaKey) { + // 是否匹配 ⌃[] / ⌃⌘[] + if (isMatchKey && event.ctrlKey && !event.altKey && !event.shiftKey && hotKeys.length < 4 && + (hotKeys.length === 3 ? (event.metaKey && hotKey.startsWith("⌃⌘")) : !event.metaKey)) { return true; } // ⌃⇧[] @@ -84,9 +86,19 @@ export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { event.ctrlKey && event.altKey && !event.shiftKey && !event.metaKey) { return true; } - // ⌃⌥⇧[] - if (isMatchKey && hotKey.startsWith("⌃⌥⇧") && hotKeys.length === 4 && - event.ctrlKey && event.altKey && event.shiftKey && !event.metaKey) { + // ⌃⌥⇧[] / ⌃⌥⌘[] / ⌃⇧⌘[] + if (isMatchKey && hotKeys.length === 4 && event.ctrlKey && + ( + (hotKey.startsWith("⌃⌥⇧") && event.shiftKey && !event.metaKey && event.altKey) || + (hotKey.startsWith("⌃⌥⌘") && !event.shiftKey && event.metaKey && event.altKey) || + (hotKey.startsWith("⌃⇧⌘") && event.shiftKey && event.metaKey && !event.altKey) + ) + ) { + return true; + } + + // ⌃⌥⇧⌘[] + if (isMatchKey && hotKeys.length === 5 && event.ctrlKey && event.shiftKey && event.metaKey && event.altKey) { return true; } return false; @@ -94,7 +106,7 @@ export const matchHotKey = (hotKey: string, event: KeyboardEvent) => { // 是否匹配 ⇧⌘[] / ⌘[] const hasShift = hotKeys.length > 2 && (hotKeys[0] === "⇧"); - if (isCtrl(event) && !event.altKey && ((!hasShift && !event.shiftKey) || (hasShift && event.shiftKey))) { + if (isOnlyMeta(event) && !event.altKey && ((!hasShift && !event.shiftKey) || (hasShift && event.shiftKey))) { return (hasShift ? hotKeys[2] : hotKeys[1]) === Constants.KEYCODELIST[event.keyCode]; } return false; diff --git a/app/src/protyle/util/table.ts b/app/src/protyle/util/table.ts index 2a121f16b..592f3c4d7 100644 --- a/app/src/protyle/util/table.ts +++ b/app/src/protyle/util/table.ts @@ -2,7 +2,7 @@ import {updateTransaction} from "../wysiwyg/transaction"; import {getSelectionOffset, focusByWbr, focusByRange, focusBlock} from "./selection"; import {hasClosestBlock, hasClosestByMatchTag} from "./hasClosest"; import {matchHotKey} from "./hotKey"; -import {isCtrl} from "./compatibility"; +import {isNotCtrl} from "./compatibility"; import {scrollCenter} from "../../util/highlightById"; import {insertEmptyBlock} from "../../block/util"; @@ -369,7 +369,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) } // shift+enter 软换行 - if (event.key === "Enter" && event.shiftKey && !isCtrl(event) && !event.altKey) { + if (event.key === "Enter" && event.shiftKey && isNotCtrl(event) && !event.altKey) { const wbrElement = document.createElement("wbr"); range.insertNode(wbrElement); const oldHTML = nodeElement.outerHTML; @@ -394,7 +394,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) return true; } // enter 光标跳转到下一行同列 - if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Enter") { + if (isNotCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Enter") { event.preventDefault(); const trElement = cellElement.parentElement as HTMLTableRowElement; if ((!trElement.nextElementSibling && trElement.parentElement.tagName === "TBODY") || @@ -423,7 +423,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) return true; } // tab:光标移向下一个 cell - if (event.key === "Tab" && !event.ctrlKey) { + if (event.key === "Tab" && isNotCtrl(event)) { if (event.shiftKey) { // shift + tab 光标移动到前一个 cell goPreviousCell(cellElement, range); @@ -453,7 +453,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) return true; } - if (event.key === "ArrowUp" && !isCtrl(event) && !event.shiftKey && !event.altKey) { + if (event.key === "ArrowUp" && isNotCtrl(event) && !event.shiftKey && !event.altKey) { const startContainer = range.startContainer as HTMLElement; let previousBrElement; if (startContainer.nodeType !== 3 && (startContainer.tagName === "TH" || startContainer.tagName === "TD")) { @@ -484,7 +484,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) return true; } - if (event.key === "ArrowDown" && !isCtrl(event) && !event.shiftKey && !event.altKey) { + if (event.key === "ArrowDown" && isNotCtrl(event) && !event.shiftKey && !event.altKey) { const endContainer = range.endContainer as HTMLElement; let nextBrElement; if (endContainer.nodeType !== 3 && (endContainer.tagName === "TH" || endContainer.tagName === "TD")) { @@ -520,7 +520,7 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) } // Backspace:光标移动到前一个 cell - if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" + if (isNotCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" && getSelectionOffset(cellElement, protyle.wysiwyg.element, range).start === 0 && range.toString() === "" && // 空换行无法删除 https://github.com/siyuan-note/siyuan/issues/2732 (range.startOffset === 0 || (range.startOffset === 1 && cellElement.querySelectorAll("br").length === 1))) { diff --git a/app/src/protyle/wysiwyg/commonClick.ts b/app/src/protyle/wysiwyg/commonClick.ts index bfea670c1..a34fd4d69 100644 --- a/app/src/protyle/wysiwyg/commonClick.ts +++ b/app/src/protyle/wysiwyg/commonClick.ts @@ -4,6 +4,7 @@ import {openAttr, openFileAttr} from "../../menus/commonMenuItem"; import {openGlobalSearch} from "../../search/util"; /// #endif import {isMobile} from "../../util/functions"; +import {isOnlyMeta} from "../util/compatibility"; export const commonClick = (event: MouseEvent & { target: HTMLElement @@ -11,7 +12,7 @@ export const commonClick = (event: MouseEvent & { const isM = isMobile(); const attrBookmarkElement = hasClosestByClassName(event.target, "protyle-attr--bookmark"); if (attrBookmarkElement) { - if (!isM && (event.ctrlKey || event.metaKey)) { + if (!isM && isOnlyMeta(event)) { /// #if !MOBILE openGlobalSearch(protyle.app, attrBookmarkElement.textContent.trim(), true); /// #endif @@ -28,7 +29,7 @@ export const commonClick = (event: MouseEvent & { const attrNameElement = hasClosestByClassName(event.target, "protyle-attr--name"); if (attrNameElement) { - if (!isM && (event.ctrlKey || event.metaKey)) { + if (!isM && isOnlyMeta(event)) { /// #if !MOBILE openGlobalSearch(protyle.app, attrNameElement.textContent.trim(), true); /// #endif @@ -56,7 +57,7 @@ export const commonClick = (event: MouseEvent & { const attrAliasElement = hasClosestByClassName(event.target, "protyle-attr--alias"); if (attrAliasElement) { - if (!isM && (event.ctrlKey || event.metaKey)) { + if (!isM && isOnlyMeta(event)) { /// #if !MOBILE openGlobalSearch(protyle.app, attrAliasElement.textContent.trim(), true); /// #endif @@ -73,7 +74,7 @@ export const commonClick = (event: MouseEvent & { const attrMemoElement = hasClosestByClassName(event.target, "protyle-attr--memo"); if (attrMemoElement) { - if (!isM && (event.ctrlKey || event.metaKey)) { + if (!isM && isOnlyMeta(event)) { /// #if !MOBILE openGlobalSearch(protyle.app, attrMemoElement.getAttribute("aria-label").trim(), true); /// #endif diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index bb1f823a4..8c5c41386 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -64,7 +64,7 @@ import {openGlobalSearch} from "../../search/util"; import {popSearch} from "../../mobile/menu/search"; /// #endif import {BlockPanel} from "../../block/Panel"; -import {isCtrl, isInIOS, openByMobile} from "../util/compatibility"; +import {isInIOS, isOnlyMeta, openByMobile} from "../util/compatibility"; import {MenuItem} from "../../menus/Menu"; import {fetchPost} from "../../util/fetch"; import {onGet} from "../util/onGet"; @@ -1582,7 +1582,7 @@ export class WYSIWYG { return; } - if ((event.shiftKey || isCtrl(event)) && !event.isComposing && range.toString() !== "") { + if ((event.shiftKey || isOnlyMeta(event)) && !event.isComposing && range.toString() !== "") { // 工具栏 protyle.toolbar.render(protyle, range, event); countSelectWord(range); @@ -1634,7 +1634,7 @@ export class WYSIWYG { }); }); hideElements(["hint", "util"], protyle); - const ctrlIsPressed = event.metaKey || event.ctrlKey; + const ctrlIsPressed = isOnlyMeta(event); /// #if !MOBILE const backlinkBreadcrumbItemElement = hasClosestByClassName(event.target, "protyle-breadcrumb__item"); if (backlinkBreadcrumbItemElement) { diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index 09bac08b8..e71b1cbc9 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -1,5 +1,5 @@ import {hideElements} from "../ui/hideElements"; -import {copyPlainText, isCtrl, isMac, writeText} from "../util/compatibility"; +import {copyPlainText, isMac, isNotCtrl, isOnlyMeta, writeText} from "../util/compatibility"; import { focusBlock, focusByRange, @@ -121,7 +121,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } - if (nodeElement.classList.contains("protyle-wysiwyg--select") && !isCtrl(event) && !event.shiftKey && !event.altKey) { + if (nodeElement.classList.contains("protyle-wysiwyg--select") && isNotCtrl(event) && !event.shiftKey && !event.altKey) { if (event.key.toLowerCase() === "a") { event.stopPropagation(); event.preventDefault(); @@ -146,7 +146,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } // https://github.com/siyuan-note/siyuan/issues/2261 - if (!isCtrl(event) && !event.shiftKey && !event.altKey) { + if (isNotCtrl(event) && !event.shiftKey && !event.altKey) { if (event.code === "Slash") { protyle.hint.enableSlash = true; } else if (event.code === "Backslash") { @@ -171,7 +171,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { if (!window.siyuan.menus.menu.element.classList.contains("fn__none") && (event.code.startsWith("Arrow") || event.code === "Enter") && - !event.altKey && !event.shiftKey && !isCtrl(event)) { + !event.altKey && !event.shiftKey && isNotCtrl(event)) { event.preventDefault(); return; } else if (event.key !== "Escape") { @@ -182,7 +182,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { protyle.breadcrumb.hide(); } - if (!event.altKey && !event.shiftKey && !isCtrl(event) && (event.key === "ArrowDown" || event.key === "ArrowUp")) { + if (!event.altKey && !event.shiftKey && isNotCtrl(event) && (event.key === "ArrowDown" || event.key === "ArrowUp")) { const selectElements = protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select"); if (selectElements.length > 0) { event.preventDefault(); @@ -268,7 +268,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { // 仅处理以下快捷键操作 if (event.key !== "PageUp" && event.key !== "PageDown" && event.key !== "Home" && event.key !== "End" && event.key.indexOf("Arrow") === -1 && - !isCtrl(event) && event.key !== "Escape" && !event.shiftKey && !event.altKey && !/^F\d{1,2}$/.test(event.key) && + isNotCtrl(event) && event.key !== "Escape" && !event.shiftKey && !event.altKey && !/^F\d{1,2}$/.test(event.key) && event.key !== "Enter" && event.key !== "Tab" && event.key !== "Backspace" && event.key !== "Delete" && event.key !== "ContextMenu") { event.stopPropagation(); hideElements(["select"], protyle); @@ -470,8 +470,8 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } - if ((event.shiftKey && !event.altKey && !isCtrl(event) && (event.key === "Home" || event.key === "End") && isMac()) || - (event.shiftKey && !event.altKey && isCtrl(event) && (event.key === "Home" || event.key === "End") && !isMac())) { + if ((event.shiftKey && !event.altKey && isNotCtrl(event) && (event.key === "Home" || event.key === "End") && isMac()) || + (event.shiftKey && !event.altKey && isOnlyMeta(event) && (event.key === "Home" || event.key === "End") && !isMac())) { const topElement = hasTopClosestByAttribute(nodeElement, "data-node-id", null); if (topElement) { // 超级块内已选中某个块 @@ -495,7 +495,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } // ctrl+home 光标移动到顶 - if (!event.altKey && !event.shiftKey && isCtrl(event) && event.key === "Home") { + if (!event.altKey && !event.shiftKey && isOnlyMeta(event) && event.key === "Home") { goHome(protyle); hideElements(["select"], protyle); event.stopPropagation(); @@ -503,7 +503,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } // ctrl+end 光标移动到尾 - if (!event.altKey && !event.shiftKey && isCtrl(event) && event.key === "End") { + if (!event.altKey && !event.shiftKey && isOnlyMeta(event) && event.key === "End") { goEnd(protyle); hideElements(["select"], protyle); event.stopPropagation(); @@ -511,7 +511,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } // 向上/下滚动一屏 - if (!event.altKey && !event.shiftKey && !isCtrl(event) && (event.key === "PageUp" || event.key === "PageDown")) { + if (!event.altKey && !event.shiftKey && isNotCtrl(event) && (event.key === "PageUp" || event.key === "PageDown")) { if (event.key === "PageUp") { protyle.contentElement.scrollTop = protyle.contentElement.scrollTop - protyle.contentElement.clientHeight; protyle.scroll.lastScrollTop = protyle.contentElement.scrollTop + 1; @@ -534,7 +534,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } // hint: 上下、回车选择 if (!event.altKey && !event.shiftKey && - ((event.key.indexOf("Arrow") > -1 && !isCtrl(event)) || event.key === "Enter") && + ((event.key.indexOf("Arrow") > -1 && isNotCtrl(event)) || event.key === "Enter") && !protyle.hint.element.classList.contains("fn__none") && protyle.hint.select(event, protyle)) { event.stopPropagation(); event.preventDefault(); @@ -607,7 +607,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } const selectText = range.toString(); // 上下左右光标移动 - if (!event.altKey && !event.shiftKey && !isCtrl(event) && !event.isComposing && (event.key.indexOf("Arrow") > -1)) { + if (!event.altKey && !event.shiftKey && isNotCtrl(event) && !event.isComposing && (event.key.indexOf("Arrow") > -1)) { // 需使用 editabled,否则代码块会把语言字数算入 const nodeEditableElement = getContenteditableElement(nodeElement) || nodeElement; const position = getSelectionOffset(nodeEditableElement, protyle.wysiwyg.element, range); @@ -716,7 +716,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } - // 删除,不可使用 !isCtrl(event),否则软删除回导致 https://github.com/siyuan-note/siyuan/issues/5607 + // 删除,不可使用 isNotCtrl(event),否则软删除回导致 https://github.com/siyuan-note/siyuan/issues/5607 // 不可使用 !event.shiftKey,否则 https://ld246.com/article/1666434796806 if (!event.altKey && (event.key === "Backspace" || event.key === "Delete")) { if (protyle.wysiwyg.element.querySelector(".protyle-wysiwyg--select")) { @@ -853,7 +853,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } // 代码块中空行 ⌘+Del 异常 https://ld246.com/article/1663166544901 - if (nodeElement.classList.contains("code-block") && isCtrl(event) && + if (nodeElement.classList.contains("code-block") && isOnlyMeta(event) && range.startContainer.nodeType === 3 && range.startContainer.textContent.substring(range.startOffset - 1, range.startOffset) === "\n") { event.stopPropagation(); event.preventDefault(); @@ -939,7 +939,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } // 回车 - if (!event.altKey && !event.shiftKey && !isCtrl(event) && event.key === "Enter") { + if (!event.altKey && !event.shiftKey && isNotCtrl(event) && event.key === "Enter") { event.stopPropagation(); event.preventDefault(); enter(nodeElement, range, protyle); @@ -1535,7 +1535,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { } // tab 需等待 list 和 table 处理完成 - if (event.key === "Tab" && !event.ctrlKey && !isCtrl(event) && !event.altKey) { + if (event.key === "Tab" && isNotCtrl(event) && !event.altKey) { event.preventDefault(); const tabSpace = window.siyuan.config.editor.codeTabSpaces === 0 ? "\t" : "".padStart(window.siyuan.config.editor.codeTabSpaces, " "); if (nodeElement.getAttribute("data-type") === "NodeCodeBlock" && selectText !== "") { @@ -1698,7 +1698,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { /// #endif // 置于最后,太多快捷键会使用到选中元素 - if (!isCtrl(event) && event.key !== "Backspace" && event.key !== "Escape" && event.key !== "Delete" && !event.shiftKey && !event.altKey && event.key !== "Enter") { + if (isNotCtrl(event) && event.key !== "Backspace" && event.key !== "Escape" && event.key !== "Delete" && !event.shiftKey && !event.altKey && event.key !== "Enter") { hideElements(["select"], protyle); } }); diff --git a/app/src/search/util.ts b/app/src/search/util.ts index 6814360bf..e1cc46a75 100644 --- a/app/src/search/util.ts +++ b/app/src/search/util.ts @@ -23,7 +23,7 @@ import {addLoading} from "../protyle/ui/initUI"; import {getIconByType} from "../editor/getIcon"; import {unicode2Emoji} from "../emoji"; import {hasClosestByClassName} from "../protyle/util/hasClosest"; -import {setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility"; +import {isNotCtrl, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility"; import {newFileByName} from "../util/newFile"; import {filterMenu, getKeyByLiElement, initCriteriaMenu, moreMenu, queryMenu, saveCriterion} from "./menu"; import {App} from "../index"; @@ -810,7 +810,7 @@ export const genSearch = (app: App, config: ISearchOption, element: Element, clo } } }, Constants.TIMEOUT_DBLCLICK); - } else if (isDblClick && !event.ctrlKey) { + } else if (isDblClick && isNotCtrl(event)) { clearTimeout(clickTimeout); if (isAsset) { /// #if !BROWSER diff --git a/app/src/util/pathName.ts b/app/src/util/pathName.ts index ea871ecac..1a7534897 100644 --- a/app/src/util/pathName.ts +++ b/app/src/util/pathName.ts @@ -10,6 +10,7 @@ import {Constants} from "../constants"; import {ipcRenderer} from "electron"; /// #endif import {showMessage} from "../dialog/message"; +import {isOnlyMeta} from "../protyle/util/compatibility"; export const showFileInFolder = (filePath: string) => { /// #if !BROWSER @@ -448,7 +449,7 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void, if (currentItemElements.length === 0) { return; } - if (title === window.siyuan.languages.specifyPath && (event.ctrlKey || event.metaKey)) { + if (title === window.siyuan.languages.specifyPath && isOnlyMeta(event)) { if (currentItemElements.length === 1 && currentItemElements[0].isSameNode(target)) { // 至少需选中一个 } else {