use ahook keypress

This commit is contained in:
codetypes committed 2024-09-26 11:34:26 +08:00
1 parent d462958c1b
commit 3be15ee116
6 files changed
+132 -174

No files matched your search

-16
View File
@@ -23,7 +23,6 @@
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.2", "i18next-http-backend": "^2.5.2",
"json-stable-stringify": "^1.1.1", "json-stable-stringify": "^1.1.1",
"react-hotkeys-hook": "^4.5.0",
"react-i18next": "^14.1.3", "react-i18next": "^14.1.3",
"react-icons": "^5.2.1", "react-icons": "^5.2.1",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
@@ -8188,15 +8187,6 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
}, },
"node_modules/react-hotkeys-hook": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.5.0.tgz",
"integrity": "sha512-Samb85GSgAWFQNvVt3PS90LPPGSf9mkH/r4au81ZP1yOIFayLC3QAvqTgGtJ8YEDMXtPmaVBs6NgipHO6h4Mug==",
"peerDependencies": {
"react": ">=16.8.1",
"react-dom": ">=16.8.1"
}
},
"node_modules/react-i18next": { "node_modules/react-i18next": {
"version": "14.1.3", "version": "14.1.3",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz",
@@ -15706,12 +15696,6 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
}, },
"react-hotkeys-hook": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.5.0.tgz",
"integrity": "sha512-Samb85GSgAWFQNvVt3PS90LPPGSf9mkH/r4au81ZP1yOIFayLC3QAvqTgGtJ8YEDMXtPmaVBs6NgipHO6h4Mug==",
"requires": {}
},
"react-i18next": { "react-i18next": {
"version": "14.1.3", "version": "14.1.3",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz",
-1
View File
@@ -60,7 +60,6 @@
"i18next-browser-languagedetector": "^7.2.1", "i18next-browser-languagedetector": "^7.2.1",
"i18next-http-backend": "^2.5.2", "i18next-http-backend": "^2.5.2",
"json-stable-stringify": "^1.1.1", "json-stable-stringify": "^1.1.1",
"react-hotkeys-hook": "^4.5.0",
"react-i18next": "^14.1.3", "react-i18next": "^14.1.3",
"react-icons": "^5.2.1", "react-icons": "^5.2.1",
"react-markdown": "^9.0.1", "react-markdown": "^9.0.1",
+10 -33
View File
@@ -9,7 +9,7 @@ import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
import * as b3util from "@/misc/b3util"; import * as b3util from "@/misc/b3util";
import { message } from "@/misc/hooks"; import { message } from "@/misc/hooks";
import i18n from "@/misc/i18n"; import i18n from "@/misc/i18n";
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys"; import { Hotkey, isMacos, useKeyUp } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import { mergeClassNames } from "@/misc/util"; import { mergeClassNames } from "@/misc/util";
import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons"; import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons";
@@ -956,38 +956,15 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
} }
}; };
const keysRef = useHotkeys<HTMLDivElement>( const keysRef = useRef<HTMLDivElement>(null);
[
Hotkey.Copy, useKeyUp(Hotkey.Copy, keysRef, () => copyNode());
Hotkey.Paste, useKeyUp(Hotkey.Replace, keysRef, () => replaceNode());
Hotkey.Save, useKeyUp(Hotkey.Paste, keysRef, () => pasteNode());
Hotkey.Replace, useKeyUp(Hotkey.Undo, keysRef, () => undo());
Hotkey.Undo, useKeyUp(Hotkey.Redo, keysRef, () => redo());
Hotkey.Redo, useKeyUp([Hotkey.Insert, Hotkey.Enter], keysRef, () => createNode());
Hotkey.Insert, useKeyUp([Hotkey.Delete, Hotkey.Backspace], keysRef, () => deleteNode());
Hotkey.Delete,
Hotkey.Enter,
Hotkey.Backspace,
],
(event) => {
event.preventDefault();
if (isHotkeyPressed(Hotkey.Copy)) {
copyNode();
} else if (isHotkeyPressed(Hotkey.Replace)) {
replaceNode();
} else if (isHotkeyPressed(Hotkey.Paste)) {
pasteNode();
} else if (isHotkeyPressed(Hotkey.Redo)) {
redo();
} else if (isHotkeyPressed(Hotkey.Undo)) {
undo();
} else if (isHotkeyPressed(Hotkey.Insert) || isHotkeyPressed(Hotkey.Enter)) {
createNode();
} else if (isHotkeyPressed(Hotkey.Delete) || isHotkeyPressed(Hotkey.Backspace)) {
deleteNode();
}
}
);
editor.dispatch = (event: EditEvent, data: unknown) => { editor.dispatch = (event: EditEvent, data: unknown) => {
switch (event) { switch (event) {
+51 -43
View File
@@ -3,14 +3,14 @@ import { NodeDef, getNodeType } from "@/misc/b3type";
import * as b3util from "@/misc/b3util"; import * as b3util from "@/misc/b3util";
import { modal } from "@/misc/hooks"; import { modal } from "@/misc/hooks";
import i18n from "@/misc/i18n"; import i18n from "@/misc/i18n";
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys"; import { Hotkey, isMacos, useKeyUp } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import { DownOutlined } from "@ant-design/icons"; import { DownOutlined } from "@ant-design/icons";
import { Button, Dropdown, Flex, FlexProps, Input, MenuProps, Space, Tree } from "antd"; import { Button, Dropdown, Flex, FlexProps, Input, MenuProps, Space, Tree } from "antd";
import { ItemType } from "antd/es/menu/interface"; import { ItemType } from "antd/es/menu/interface";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import * as fs from "fs"; import * as fs from "fs";
import React, { FC, useEffect, useMemo, useState } from "react"; import React, { FC, useEffect, useMemo, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { BsBoxFill } from "react-icons/bs"; import { BsBoxFill } from "react-icons/bs";
import { FaExclamationTriangle, FaSwatchbook } from "react-icons/fa"; import { FaExclamationTriangle, FaSwatchbook } from "react-icons/fa";
@@ -397,48 +397,56 @@ export const Explorer: FC = () => {
} }
}, [t, workspace.editingNodeDef]); }, [t, workspace.editingNodeDef]);
const keysRef = useHotkeys<HTMLDivElement>( const keysRef = useRef<HTMLDivElement>(null);
[
Hotkey.F2, useKeyUp([Hotkey.F2, isMacos ? Hotkey.Enter : ""], keysRef, (event) => {
Hotkey.Enter, event.preventDefault();
Hotkey.Copy, const node = findFile(selectedKeys[0], workspace.fileTree!);
Hotkey.Paste, if (node && node !== workspace.fileTree) {
Hotkey.Delete, dispatch("rename", node);
Hotkey.MacDelete,
Hotkey.Escape,
Hotkey.Duplicate,
],
(event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (isHotkeyPressed(Hotkey.F2) || (isMacos && isHotkeyPressed(Hotkey.Enter))) {
if (node && node !== workspace.fileTree) {
dispatch("rename", node);
}
} else if (isHotkeyPressed(Hotkey.Delete) || isHotkeyPressed(Hotkey.MacDelete)) {
if (node && node !== workspace.fileTree) {
dispatch("delete", node);
}
} else if (isHotkeyPressed(Hotkey.Escape)) {
if (node) {
node.editing = false;
setNewName(null);
}
} else if (isHotkeyPressed(Hotkey.Duplicate)) {
if (node && node.isLeaf) {
dispatch("duplicate", node);
}
} else if (isHotkeyPressed(Hotkey.Copy)) {
if (node && node.isLeaf) {
dispatch("copy", node);
}
} else if (isHotkeyPressed(Hotkey.Paste)) {
if (node) {
dispatch("paste", node);
}
}
} }
); });
useKeyUp([Hotkey.Delete, isMacos ? Hotkey.MacDelete : ""], keysRef, (event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (node && node !== workspace.fileTree) {
dispatch("delete", node);
}
});
useKeyUp(Hotkey.Escape, keysRef, (event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (node) {
node.editing = false;
setNewName(null);
}
});
useKeyUp(Hotkey.Duplicate, keysRef, (event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (node && node.isLeaf) {
dispatch("duplicate", node);
}
});
useKeyUp(Hotkey.Copy, keysRef, (event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (node && node.isLeaf) {
dispatch("copy", node);
}
});
useKeyUp(Hotkey.Paste, keysRef, (event) => {
event.preventDefault();
const node = findFile(selectedKeys[0], workspace.fileTree!);
if (node) {
dispatch("paste", node);
}
});
const submitRename = (node: FileTreeType) => { const submitRename = (node: FileTreeType) => {
if (!newName) { if (!newName) {
+43 -38
View File
@@ -1,11 +1,12 @@
import { useSetting } from "@/contexts/setting-context"; import { useSetting } from "@/contexts/setting-context";
import { EditorStore, useWorkspace } from "@/contexts/workspace-context"; import { EditorStore, useWorkspace } from "@/contexts/workspace-context";
import { modal } from "@/misc/hooks"; import { modal } from "@/misc/hooks";
import { Hotkey, isHotkeyPressed, isMacos, setInputFocus, useHotkeys } from "@/misc/keys"; import { Hotkey, isMacos, setInputFocus, useKeyUp } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import { app } from "@electron/remote"; import { app } from "@electron/remote";
import { useKeyPress } from "ahooks";
import { Button, Flex, Layout, Space, Tabs, Tag, Tooltip } from "antd"; import { Button, Flex, Layout, Space, Tabs, Tag, Tooltip } from "antd";
import { FC, useEffect, useState } from "react"; import { FC, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FaExclamationTriangle } from "react-icons/fa"; import { FaExclamationTriangle } from "react-icons/fa";
import { PiTreeStructureFill } from "react-icons/pi"; import { PiTreeStructureFill } from "react-icons/pi";
@@ -43,44 +44,48 @@ export const Workspace: FC = () => {
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
const { width = 0, height = 0 } = useWindowSize(); const { width = 0, height = 0 } = useWindowSize();
const keysRef = useHotkeys<HTMLDivElement>( const keysRef = useRef<HTMLDivElement>(null);
[
Hotkey.Save, useKeyUp(Hotkey.Build, keysRef, (event) => {
Hotkey.CloseEditor, event.preventDefault();
Hotkey.SearchTree, workspace.buildProject();
Hotkey.Build, });
Hotkey.SearchNode,
Hotkey.JumpNode, useKeyUp(Hotkey.Save, keysRef, (event) => {
], event.preventDefault();
(event) => { workspace.save();
if (isHotkeyPressed(Hotkey.Save)) { });
event.preventDefault();
workspace.save(); useKeyPress(Hotkey.CloseEditor, (event) => {
} else if (isHotkeyPressed(Hotkey.CloseEditor)) { event.preventDefault();
if (workspace.editing) { });
event.preventDefault();
if (workspace.editing.unsave) { useKeyUp(Hotkey.CloseEditor, null, (event) => {
showSaveDialog(workspace.editing); if (workspace.editing) {
} else { event.preventDefault();
workspace.close(workspace.editing.path); if (workspace.editing.unsave) {
} showSaveDialog(workspace.editing);
} } else {
keysRef.current?.focus(); workspace.close(workspace.editing.path);
} else if (isHotkeyPressed(Hotkey.SearchTree)) {
event.preventDefault();
workspace.onShowingSearch(true);
} else if (isHotkeyPressed(Hotkey.Build)) {
event.preventDefault();
workspace.buildProject();
} else if (isHotkeyPressed(Hotkey.SearchNode)) {
event.preventDefault();
workspace.editing?.dispatch("searchNode");
} else if (isHotkeyPressed(Hotkey.JumpNode)) {
event.preventDefault();
workspace.editing?.dispatch("jumpNode");
} }
} }
); keysRef.current?.focus();
});
useKeyUp(Hotkey.SearchTree, keysRef, (event) => {
event.preventDefault();
workspace.onShowingSearch(true);
});
useKeyUp(Hotkey.SearchNode, keysRef, (event) => {
event.preventDefault();
workspace.editing?.dispatch("searchNode");
});
useKeyUp(Hotkey.JumpNode, keysRef, (event) => {
event.preventDefault();
workspace.editing?.dispatch("jumpNode");
});
useEffect(() => { useEffect(() => {
if (!workspace.isShowingSearch && !isShowingSave) { if (!workspace.isShowingSearch && !isShowingSave) {
+28 -43
View File
@@ -1,12 +1,5 @@
import { BrowserWindow } from "@electron/remote"; import { BrowserWindow } from "@electron/remote";
import { MutableRefObject } from "react"; import useKeyPress, { KeyFilter, KeyType, Options, Target } from "ahooks/lib/useKeyPress";
import {
HotkeyCallback,
Keys,
isHotkeyPressed as _isHotkeyPressed,
useHotkeys as _useHotkeys,
} from "react-hotkeys-hook";
import { OptionsOrDependencyArray, RefType } from "react-hotkeys-hook/dist/types";
import { Key } from "ts-key-enum"; import { Key } from "ts-key-enum";
export const isMacos = process.platform === "darwin"; export const isMacos = process.platform === "darwin";
@@ -20,49 +13,41 @@ const hotkey = (key: string) => {
return key.toLowerCase(); return key.toLowerCase();
}; };
export const isHotkeyPressed = (key: string) => { export const useKeyUp = (
if (!key) { keyFilter: KeyFilter,
return false; target: Target,
} else if (key.indexOf("ctrl") >= 0 && isMacos) { eventHandler: (event: KeyboardEvent, key: KeyType) => void,
key = key.replace("ctrl", Key.Meta); option?: Options
} ) => {
return _isHotkeyPressed(key.toLowerCase(), "+"); option = option || {};
option.events = ["keyup"];
option.target = target;
option.exactMatch = true;
return useKeyPress(keyFilter, eventHandler, option);
}; };
export function useHotkeys<T extends HTMLElement>(
keys: Keys,
callback: HotkeyCallback,
options?: OptionsOrDependencyArray,
dependencies?: OptionsOrDependencyArray
): MutableRefObject<RefType<T>> {
if (keys instanceof Array) {
keys = keys.filter((v) => !!v);
}
return _useHotkeys(keys, callback, options, dependencies);
}
export const Hotkey = { export const Hotkey = {
Backspace: Key.Backspace, Backspace: Key.Backspace,
Build: hotkey("ctrl+b"), Build: hotkey("ctrl.b"),
CloseEditor: hotkey("ctrl+w"), CloseEditor: hotkey("ctrl.w"),
Copy: hotkey("ctrl+c"), Copy: hotkey("ctrl.c"),
Cut: hotkey('ctrl+x'), Cut: hotkey("ctrl.x"),
Delete: Key.Delete, Delete: Key.Delete,
Duplicate: hotkey("ctrl+d"), Duplicate: hotkey("ctrl.d"),
Enter: Key.Enter, Enter: Key.Enter,
Escape: Key.Escape, Escape: Key.Escape,
F2: Key.F2, F2: Key.F2,
Insert: Key.Insert, Insert: Key.Insert,
JumpNode: hotkey("ctrl+g"), JumpNode: hotkey("ctrl.g"),
MacDelete: isMacos ? hotkey("ctrl+backspace") : "", MacDelete: isMacos ? hotkey("ctrl.backspace") : "",
Paste: hotkey("ctrl+v"), Paste: hotkey("ctrl.v"),
Redo: isMacos ? hotkey("shift+ctrl+z") : hotkey("ctrl+y"), Redo: isMacos ? hotkey("shift.ctrl.z") : hotkey("ctrl.y"),
Replace: hotkey("shift+ctrl+v"), Replace: hotkey("shift.ctrl.v"),
Save: hotkey("ctrl+s"), Save: hotkey("ctrl.s"),
SearchTree: hotkey("ctrl+p"), SearchTree: hotkey("ctrl.p"),
SearchNode: hotkey("ctrl+f"), SearchNode: hotkey("ctrl.f"),
SelectAll: hotkey('ctrl+a'), SelectAll: hotkey("ctrl.a"),
Undo: hotkey("ctrl+z"), Undo: hotkey("ctrl.z"),
}; };
export const setInputFocus = (target: HTMLElement) => { export const setInputFocus = (target: HTMLElement) => {
@@ -74,7 +59,7 @@ export const sendInputEvent = (key: string) => {
if (webContents) { if (webContents) {
let keyCode: string | undefined; let keyCode: string | undefined;
const modifiers: Electron.InputEvent["modifiers"] = []; const modifiers: Electron.InputEvent["modifiers"] = [];
key.split("+").forEach((v) => { key.split(".").forEach((v) => {
if (v.indexOf("ctrl") >= 0) { if (v.indexOf("ctrl") >= 0) {
modifiers.push("ctrl"); modifiers.push("ctrl");
} else if (v.indexOf("shift") >= 0) { } else if (v.indexOf("shift") >= 0) {