Merge branch 'dev'
This commit is contained in:
commit
c1c96662fd
6 files changed
+76
-65
No files matched your search
+46
-41
@@ -11,6 +11,7 @@ import { message } from "@/misc/hooks";
|
||||
import i18n from "@/misc/i18n";
|
||||
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
|
||||
import Path from "@/misc/path";
|
||||
import { mergeClassNames } from "@/misc/util";
|
||||
import { ArrowDownOutlined, ArrowUpOutlined, CloseOutlined } from "@ant-design/icons";
|
||||
import G6, { G6GraphEvent, Item, TreeGraph } from "@antv/g6";
|
||||
import { dialog } from "@electron/remote";
|
||||
@@ -18,7 +19,7 @@ import { useSize } from "ahooks";
|
||||
import { Button, Dropdown, Flex, FlexProps, Input, InputRef, MenuProps } from "antd";
|
||||
import { clipboard } from "electron";
|
||||
import * as fs from "fs";
|
||||
import React, { FC, KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import React, { FC, KeyboardEvent, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FiDelete } from "react-icons/fi";
|
||||
import { IoMdReturnLeft } from "react-icons/io";
|
||||
@@ -27,7 +28,6 @@ import { VscCaseSensitive } from "react-icons/vsc";
|
||||
import { mergeRefs } from "react-merge-refs";
|
||||
import { useDebounceCallback } from "usehooks-ts";
|
||||
import "./register-node";
|
||||
import { mergeClassNames } from "@/misc/util";
|
||||
|
||||
export interface EditorProps extends React.HTMLAttributes<HTMLElement> {
|
||||
data: EditorStore;
|
||||
@@ -40,7 +40,7 @@ interface FilterOption {
|
||||
filterStr: string;
|
||||
filterCase: boolean;
|
||||
filterFocus: boolean;
|
||||
filterType: string;
|
||||
filterType: "content" | "id";
|
||||
placeholder: string;
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
workdir: useWorkspace((state) => state.workdir),
|
||||
};
|
||||
|
||||
const searchIptRef = useRef<InputRef>(null);
|
||||
const searchInputRef = useRef<InputRef>(null);
|
||||
const graphRef = useRef(null);
|
||||
const sizeRef = useRef(null);
|
||||
const editorSize = useSize(sizeRef);
|
||||
@@ -147,8 +147,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
filterStr: "",
|
||||
filterCase: false,
|
||||
filterFocus: false,
|
||||
filterType: "",
|
||||
placeholder: ""
|
||||
filterType: "content",
|
||||
placeholder: "",
|
||||
});
|
||||
|
||||
const onSearchChange = (option: FilterOption) => {
|
||||
@@ -236,12 +236,15 @@ 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.filterType === "id") {
|
||||
if (option.filterStr === node.id) {
|
||||
found = true
|
||||
found = true;
|
||||
}
|
||||
} else {
|
||||
if (includeString(node.name, option) || includeString(node.desc || node.def.desc, option)) {
|
||||
if (
|
||||
includeString(node.name, option) ||
|
||||
includeString(node.desc || node.def.desc, option)
|
||||
) {
|
||||
found = true;
|
||||
} else if (node.input) {
|
||||
for (const str of node.input) {
|
||||
@@ -1019,11 +1022,11 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
break;
|
||||
}
|
||||
case "searchNode": {
|
||||
searchByType("");
|
||||
searchByType("content");
|
||||
break;
|
||||
}
|
||||
case "jumpNode": {
|
||||
searchByType("nodeId");
|
||||
searchByType("id");
|
||||
break;
|
||||
}
|
||||
case "editSubtree": {
|
||||
@@ -1090,41 +1093,43 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
}
|
||||
};
|
||||
|
||||
const searchByType = (type: string) => {
|
||||
let placeholder = ""
|
||||
const filterType = type
|
||||
const searchByType = (type: FilterOption["filterType"]) => {
|
||||
let placeholder = "";
|
||||
const filterType = type;
|
||||
// todo multiple parameter format judgment
|
||||
switch (type) {
|
||||
case "nodeId":
|
||||
placeholder = t("jumpNode")
|
||||
break
|
||||
case "id":
|
||||
placeholder = t("jumpNode");
|
||||
break;
|
||||
default:
|
||||
placeholder = t("searchNode")
|
||||
break
|
||||
placeholder = t("searchNode");
|
||||
break;
|
||||
}
|
||||
if (!showingSearch) {
|
||||
setFilterOption({ ...filterOption, placeholder, filterType })
|
||||
setShowingSearch(true)
|
||||
return
|
||||
setFilterOption({ ...filterOption, placeholder, filterType });
|
||||
setShowingSearch(true);
|
||||
return;
|
||||
}
|
||||
if (filterOption.filterType === type) return searchIptRef.current?.focus()
|
||||
setShowingSearch(false)
|
||||
if (filterOption.filterType === type) {
|
||||
return searchInputRef.current?.focus();
|
||||
}
|
||||
setShowingSearch(false);
|
||||
setTimeout(() => {
|
||||
setShowingSearch(true)
|
||||
setFilterOption({ ...filterOption, placeholder, filterType })
|
||||
searchIptRef.current?.focus()
|
||||
}, 50)
|
||||
}
|
||||
setShowingSearch(true);
|
||||
setFilterOption({ ...filterOption, placeholder, filterType });
|
||||
searchInputRef.current?.focus();
|
||||
}, 50);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.code === Hotkey.Enter) {
|
||||
nextResult()
|
||||
nextResult();
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.code === "KeyF") {
|
||||
searchByType("")
|
||||
searchByType("content");
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.code === "KeyG") {
|
||||
searchByType("nodeId")
|
||||
searchByType("id");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -1155,8 +1160,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
ref={searchIptRef}
|
||||
placeholder={ filterOption.placeholder }
|
||||
ref={searchInputRef}
|
||||
placeholder={filterOption.placeholder}
|
||||
autoFocus
|
||||
size="small"
|
||||
style={{
|
||||
@@ -1172,10 +1177,10 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
index: 0,
|
||||
})
|
||||
}
|
||||
onKeyDown={ handleKeyDown }
|
||||
onKeyDown={handleKeyDown}
|
||||
suffix={
|
||||
<Flex gap="2px" style={{ alignItems: "center" }}>
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
{filterOption.filterType !== "id" && (
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
@@ -1215,7 +1220,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
? `${filterOption.index + 1}/${filterOption.results.length}`
|
||||
: ""}
|
||||
</div>
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
{filterOption.filterType !== "id" && (
|
||||
<Button
|
||||
icon={<ArrowDownOutlined />}
|
||||
type="text"
|
||||
@@ -1225,7 +1230,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
onClick={nextResult}
|
||||
/>
|
||||
)}
|
||||
{filterOption.filterType !== "nodeId" && (
|
||||
{filterOption.filterType !== "id" && (
|
||||
<Button
|
||||
icon={<ArrowUpOutlined />}
|
||||
type="text"
|
||||
@@ -1248,8 +1253,8 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
|
||||
filterCase: false,
|
||||
filterFocus: false,
|
||||
filterStr: "",
|
||||
filterType: "",
|
||||
placeholder: ""
|
||||
filterType: "content",
|
||||
placeholder: "",
|
||||
});
|
||||
keysRef.current?.focus();
|
||||
}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EditNode, EditTree, FileTreeType, useWorkspace } from "@/contexts/workspace-context";
|
||||
import { EditNode, EditTree, useWorkspace } from "@/contexts/workspace-context";
|
||||
import { NodeArgType, NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
|
||||
import { Hotkey, isMacos } from "@/misc/keys";
|
||||
import Path from "@/misc/path";
|
||||
|
||||
@@ -7,7 +7,7 @@ import { app } from "@electron/remote";
|
||||
import { Button, Flex, Layout, Space, Tabs, Tag, Tooltip } from "antd";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaExclamationTriangle, FaRegFolderOpen } from "react-icons/fa";
|
||||
import { FaExclamationTriangle } from "react-icons/fa";
|
||||
import { PiTreeStructureFill } from "react-icons/pi";
|
||||
import { VscNewFolder, VscRepo } from "react-icons/vsc";
|
||||
import useForceUpdate from "use-force-update";
|
||||
@@ -44,7 +44,14 @@ 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.JumpNode],
|
||||
[
|
||||
Hotkey.Save,
|
||||
Hotkey.CloseEditor,
|
||||
Hotkey.SearchTree,
|
||||
Hotkey.Build,
|
||||
Hotkey.SearchNode,
|
||||
Hotkey.JumpNode,
|
||||
],
|
||||
(event) => {
|
||||
if (isHotkeyPressed(Hotkey.Save)) {
|
||||
event.preventDefault();
|
||||
@@ -68,8 +75,8 @@ export const Workspace: FC = () => {
|
||||
event.preventDefault();
|
||||
workspace.editing?.dispatch("searchNode");
|
||||
} else if (isHotkeyPressed(Hotkey.JumpNode)) {
|
||||
event.preventDefault()
|
||||
workspace.editing?.dispatch("jumpNode")
|
||||
event.preventDefault();
|
||||
workspace.editing?.dispatch("jumpNode");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { readJson, writeJson } from "@/misc/util";
|
||||
import { app } from "@electron/remote";
|
||||
import { create } from "zustand";
|
||||
import * as fs from "fs";
|
||||
import { create } from "zustand";
|
||||
|
||||
const settingPath = app.getPath("userData") + "/settings.json";
|
||||
|
||||
|
||||
@@ -145,13 +145,13 @@ export type WorkspaceStore = {
|
||||
};
|
||||
|
||||
const loadFileTree = (workdir: string, filename: string) => {
|
||||
const fullpath = fs.realpathSync(`${ workdir }/${ filename }`);
|
||||
const fullpath = fs.realpathSync(`${workdir}/${filename}`);
|
||||
if (!fs.existsSync(fullpath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stat = fs.statSync(fullpath);
|
||||
if (!( stat.isDirectory() || fullpath.endsWith(".json") )) {
|
||||
if (!(stat.isDirectory() || fullpath.endsWith(".json"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -164,13 +164,13 @@ const loadFileTree = (workdir: string, filename: string) => {
|
||||
data.children = [];
|
||||
const files = fs.readdirSync(data.path);
|
||||
files.forEach((v) => {
|
||||
const child = loadFileTree(workdir, `${ filename }/${ v }`);
|
||||
const child = loadFileTree(workdir, `${filename}/${v}`);
|
||||
if (child) {
|
||||
data.children?.push(child);
|
||||
}
|
||||
});
|
||||
data.children.sort((a, b) => {
|
||||
if (( a.children && b.children ) || ( !a.children && !b.children )) {
|
||||
if ((a.children && b.children) || (!a.children && !b.children)) {
|
||||
return a.title.localeCompare(b.title);
|
||||
} else {
|
||||
return a.children ? -1 : 1;
|
||||
@@ -188,7 +188,7 @@ const saveFile = (editor?: EditorStore) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
export const useWorkspace = create<WorkspaceStore>((set, get) => ({
|
||||
allFiles: [],
|
||||
fileTree: undefined,
|
||||
editors: [],
|
||||
@@ -210,15 +210,15 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
if (!fs.existsSync(path)) {
|
||||
useSetting.getState().removeRecent(path);
|
||||
}
|
||||
message.error(`load workspace error: ${ path }`);
|
||||
message.error(`load workspace error: ${path}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createProject: () => {
|
||||
const path = dialog.showSaveDialogSync({
|
||||
properties: [ "showOverwriteConfirmation", "createDirectory" ],
|
||||
filters: [ { name: "Behavior3 Workspace", extensions: [ "b3-workspace" ] } ],
|
||||
properties: ["showOverwriteConfirmation", "createDirectory"],
|
||||
filters: [{ name: "Behavior3 Workspace", extensions: ["b3-workspace"] }],
|
||||
});
|
||||
if (path) {
|
||||
const workspace = get();
|
||||
@@ -234,7 +234,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
const win = BrowserWindow.getFocusedWindow();
|
||||
if (win) {
|
||||
const path = dialog.showOpenDialogSync(win, {
|
||||
filters: [ { name: "workspace", extensions: [ "b3-workspace" ] } ],
|
||||
filters: [{ name: "workspace", extensions: ["b3-workspace"] }],
|
||||
});
|
||||
if (path?.length) {
|
||||
ipcRenderer.invoke("open-win", path[0]);
|
||||
@@ -248,7 +248,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
if (workspace.path)
|
||||
if (!buildDir) {
|
||||
buildDir = dialog.showOpenDialogSync({
|
||||
properties: [ "openDirectory", "createDirectory" ],
|
||||
properties: ["openDirectory", "createDirectory"],
|
||||
})?.[0];
|
||||
}
|
||||
if (buildDir) {
|
||||
@@ -281,9 +281,9 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
batchProject: () => {
|
||||
const workspace = get();
|
||||
const scriptPath = dialog.showOpenDialogSync({
|
||||
properties: [ "openFile" ],
|
||||
properties: ["openFile"],
|
||||
defaultPath: workspace.workdir,
|
||||
filters: [ { name: "Javascript", extensions: [ "js" ] } ],
|
||||
filters: [{ name: "Javascript", extensions: ["js"] }],
|
||||
})?.[0];
|
||||
if (scriptPath) {
|
||||
try {
|
||||
@@ -329,7 +329,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
workspace.edit(editor.path);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
message.error(`invalid file: ${ path }`);
|
||||
message.error(`invalid file: ${path}`);
|
||||
}
|
||||
} else if (workspace.editing !== editor) {
|
||||
workspace.edit(editor.path);
|
||||
@@ -389,8 +389,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
saveFile(workspace.editing);
|
||||
},
|
||||
|
||||
saveAs: () => {
|
||||
},
|
||||
saveAs: () => {},
|
||||
|
||||
saveAll: () => {
|
||||
const workspace = get();
|
||||
@@ -445,7 +444,7 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
|
||||
loadNodeDefs: () => {
|
||||
const workspace = get();
|
||||
const nodeDefData = readJson(`${ workspace.workdir }/node-config.b3-setting`) as NodeDef[];
|
||||
const nodeDefData = readJson(`${workspace.workdir}/node-config.b3-setting`) as NodeDef[];
|
||||
const nodeDefs: Map<string, NodeDef> = new Map();
|
||||
for (const v of nodeDefData) {
|
||||
nodeDefs.set(v.name, v);
|
||||
@@ -479,4 +478,4 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ( {
|
||||
const workspace = get();
|
||||
return workspace.nodeDefs.has(name);
|
||||
},
|
||||
} ));
|
||||
}));
|
||||
+1
-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);
|
||||
|
||||
Reference in new issue
Block a user