Merge pull request #22 from GeorgeShiZZZ/master
add ctrl/command + g to jump node by id
This commit is contained in:
6 files changed
+78
-7
No files matched your search
@@ -19,6 +19,7 @@
|
||||
"hide": "Hide Behavior3",
|
||||
"hideOthers": "Hide Others",
|
||||
"insertNode": "Insert Node",
|
||||
"jumpNode": "Jump Node",
|
||||
"language": "Language",
|
||||
"moveToTrash": "Move to Trash",
|
||||
"newFile": "New File...",
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"hide": "隐藏 Behavior3",
|
||||
"hideOthers": "隐藏其它",
|
||||
"insertNode": "插入节点",
|
||||
"jumpNode": "跳转节点",
|
||||
"language": "语言",
|
||||
"moveToTrash": "移至回收站",
|
||||
"newFile": "新建行为树...",
|
||||
|
||||
@@ -15,10 +15,10 @@ import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/i
|
||||
import G6, { G6GraphEvent, Item, TreeGraph } from "@antv/g6";
|
||||
import { dialog } from "@electron/remote";
|
||||
import { useSize } from "ahooks";
|
||||
import { Button, Dropdown, Flex, FlexProps, Input, MenuProps } from "antd";
|
||||
import { Button, Dropdown, Flex, FlexProps, Input, InputRef, MenuProps } from "antd";
|
||||
import { clipboard } from "electron";
|
||||
import * as fs from "fs";
|
||||
import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import React, { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FiDelete } from "react-icons/fi";
|
||||
import { IoMdReturnLeft } from "react-icons/io";
|
||||
@@ -40,6 +40,8 @@ interface FilterOption {
|
||||
filterStr: string;
|
||||
filterCase: boolean;
|
||||
filterFocus: boolean;
|
||||
filterType: string;
|
||||
placeholder: string;
|
||||
}
|
||||
|
||||
const createMenu = () => {
|
||||
@@ -131,6 +133,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
workdir: useWorkspace((state) => state.workdir),
|
||||
};
|
||||
|
||||
const searchIptRef = useRef<InputRef>(null);
|
||||
const graphRef = useRef(null);
|
||||
const sizeRef = useRef(null);
|
||||
const editorSize = useSize(sizeRef);
|
||||
@@ -144,6 +147,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
filterStr: "",
|
||||
filterCase: false,
|
||||
filterFocus: false,
|
||||
filterType: "",
|
||||
placeholder: ""
|
||||
});
|
||||
|
||||
const onSearchChange = (option: FilterOption) => {
|
||||
@@ -231,6 +236,11 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
node.highlightGray = option.filterFocus;
|
||||
if (option.filterStr) {
|
||||
let found = false;
|
||||
if (option.filterType === "nodeId") {
|
||||
if (option.filterStr === node.id) {
|
||||
found = true
|
||||
}
|
||||
} else {
|
||||
if (includeString(node.name, option) || includeString(node.desc || node.def.desc, option)) {
|
||||
found = true;
|
||||
} else if (node.input) {
|
||||
@@ -259,6 +269,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
option.results.push(node.id);
|
||||
node.highlightGray = false;
|
||||
@@ -1008,7 +1019,11 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
break;
|
||||
}
|
||||
case "searchNode": {
|
||||
setShowingSearch(true);
|
||||
searchByType("");
|
||||
break;
|
||||
}
|
||||
case "jumpNode": {
|
||||
searchByType("nodeId");
|
||||
break;
|
||||
}
|
||||
case "editSubtree": {
|
||||
@@ -1075,6 +1090,42 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
}
|
||||
};
|
||||
|
||||
const searchByType = (type: string) => {
|
||||
let placeholder = ""
|
||||
const filterType = type
|
||||
// todo multiple parameter format judgment
|
||||
switch (type) {
|
||||
case "nodeId":
|
||||
placeholder = t("jumpNode")
|
||||
break
|
||||
default:
|
||||
placeholder = t("searchNode")
|
||||
break
|
||||
}
|
||||
if (!showingSearch) {
|
||||
setFilterOption({ ...filterOption, placeholder, filterType })
|
||||
setShowingSearch(true)
|
||||
return
|
||||
}
|
||||
if (filterOption.filterType === type) return searchIptRef.current?.focus()
|
||||
setShowingSearch(false)
|
||||
setTimeout(() => {
|
||||
setShowingSearch(true)
|
||||
setFilterOption({ ...filterOption, placeholder, filterType })
|
||||
searchIptRef.current?.focus()
|
||||
}, 50)
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.code === Hotkey.Enter) {
|
||||
nextResult()
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.code === "KeyF") {
|
||||
searchByType("")
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.code === "KeyG") {
|
||||
searchByType("nodeId")
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
@@ -1104,6 +1155,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
ref={searchIptRef}
|
||||
placeholder={ filterOption.placeholder }
|
||||
autoFocus
|
||||
size="small"
|
||||
style={{
|
||||
@@ -1119,9 +1172,10 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
index: 0,
|
||||
})
|
||||
}
|
||||
onKeyDown={(e) => e.code === Hotkey.Enter && nextResult()}
|
||||
onKeyDown={ handleKeyDown }
|
||||
suffix={
|
||||
<Flex gap="2px" style={{ alignItems: "center" }}>
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
@@ -1137,6 +1191,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
})
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
@@ -1160,6 +1215,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
? `${filterOption.index + 1}/${filterOption.results.length}`
|
||||
: ""}
|
||||
</div>
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
<Button
|
||||
icon={<ArrowDownOutlined />}
|
||||
type="text"
|
||||
@@ -1168,6 +1224,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
disabled={filterOption.results.length == 0}
|
||||
onClick={nextResult}
|
||||
/>
|
||||
)}
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
<Button
|
||||
icon={<ArrowUpOutlined />}
|
||||
type="text"
|
||||
@@ -1176,6 +1234,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
disabled={filterOption.results.length == 0}
|
||||
onClick={prevResult}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
icon={<CloseOutlined />}
|
||||
type="text"
|
||||
@@ -1189,6 +1248,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
filterCase: false,
|
||||
filterFocus: false,
|
||||
filterStr: "",
|
||||
filterType: "",
|
||||
placeholder: ""
|
||||
});
|
||||
keysRef.current?.focus();
|
||||
}}
|
||||
|
||||
@@ -44,7 +44,7 @@ export const Workspace: FC = () => {
|
||||
const { width = 0, height = 0 } = useWindowSize();
|
||||
|
||||
const keysRef = useHotkeys<HTMLDivElement>(
|
||||
[Hotkey.Save, Hotkey.CloseEditor, Hotkey.SearchTree, Hotkey.Build, Hotkey.SearchNode],
|
||||
[Hotkey.Save, Hotkey.CloseEditor, Hotkey.SearchTree, Hotkey.Build, Hotkey.SearchNode, Hotkey.JumpNode],
|
||||
(event) => {
|
||||
if (isHotkeyPressed(Hotkey.Save)) {
|
||||
event.preventDefault();
|
||||
@@ -67,6 +67,9 @@ export const Workspace: FC = () => {
|
||||
} else if (isHotkeyPressed(Hotkey.SearchNode)) {
|
||||
event.preventDefault();
|
||||
workspace.editing?.dispatch("searchNode");
|
||||
} else if (isHotkeyPressed(Hotkey.JumpNode)) {
|
||||
event.preventDefault()
|
||||
workspace.editing?.dispatch("jumpNode")
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -338,6 +341,7 @@ export const Workspace: FC = () => {
|
||||
{ label: t("searchFile"), hotkeys: isMacos ? "⌘ P" : "Ctrl + P" },
|
||||
{ label: t("build"), hotkeys: isMacos ? "⌘ B" : "Ctrl + B" },
|
||||
{ label: t("searchNode"), hotkeys: isMacos ? "⌘ F" : "Ctrl + F" },
|
||||
{ label: t("jumpNode"), hotkeys: isMacos ? "⌘ G" : "Ctrl + G" },
|
||||
{ label: t("insertNode"), hotkeys: "Enter" },
|
||||
{ label: t("deleteNode"), hotkeys: "Backspace" },
|
||||
].map((v) => (
|
||||
|
||||
@@ -16,6 +16,7 @@ let buildDir: string | undefined;
|
||||
|
||||
interface BatchScript {
|
||||
processTree?(tree: TreeModel): TreeModel;
|
||||
|
||||
processNode?(node: NodeModel, tree: TreeModel): NodeModel;
|
||||
}
|
||||
|
||||
@@ -26,6 +27,7 @@ export type EditEvent =
|
||||
| "replace"
|
||||
| "delete"
|
||||
| "insert"
|
||||
| "jumpNode"
|
||||
| "undo"
|
||||
| "redo"
|
||||
| "reload"
|
||||
@@ -387,7 +389,8 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
|
||||
saveFile(workspace.editing);
|
||||
},
|
||||
|
||||
saveAs: () => {},
|
||||
saveAs: () => {
|
||||
},
|
||||
|
||||
saveAll: () => {
|
||||
const workspace = get();
|
||||
|
||||
+2
-1
@@ -33,7 +33,7 @@ export function useHotkeys<T extends HTMLElement>(
|
||||
keys: Keys,
|
||||
callback: HotkeyCallback,
|
||||
options?: OptionsOrDependencyArray,
|
||||
dependencies?: OptionsOrDependencyArray
|
||||
dependencies?: OptionsOrDependencyArray,
|
||||
): MutableRefObject<RefType<T>> {
|
||||
if (keys instanceof Array) {
|
||||
keys = keys.filter((v) => !!v);
|
||||
@@ -52,6 +52,7 @@ export const Hotkey = {
|
||||
Escape: Key.Escape,
|
||||
F2: Key.F2,
|
||||
Insert: Key.Insert,
|
||||
JumpNode: hotkey("ctrl+g"),
|
||||
MacDelete: isMacos ? hotkey("ctrl+backspace") : "",
|
||||
Paste: hotkey("ctrl+v"),
|
||||
Redo: isMacos ? hotkey("shift+ctrl+z") : hotkey("ctrl+y"),
|
||||
|
||||
Reference in new issue
Block a user