show node definitions in explorer

This commit is contained in:
codetypes committed 2024-04-19 09:10:11 +08:00
1 parent ccdaa22c85
commit 5dab8220a5
8 files changed
+182 -83

No files matched your search

+7 -7
View File
@@ -8,7 +8,7 @@ import {
import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type"; 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 { Hotkey, isHotkeyPressed, useHotkeys } from "@/misc/keys"; import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import G6, { G6GraphEvent, Item, TreeGraph } from "@antv/g6"; import G6, { G6GraphEvent, Item, TreeGraph } from "@antv/g6";
import { dialog } from "@electron/remote"; import { dialog } from "@electron/remote";
@@ -840,13 +840,13 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
></Flex> ></Flex>
); );
}; };
const isMac = process.platform === "darwin";
const arr: MenuProps["items"] = [ const arr: MenuProps["items"] = [
{ {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("copy")}</div> <div>{t("copy")}</div>
<div>{isMac ? "⌘ C" : "Ctrl+C"}</div> <div>{isMacos ? "⌘ C" : "Ctrl+C"}</div>
</MenuItem> </MenuItem>
), ),
key: "copy", key: "copy",
@@ -855,7 +855,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("paste")}</div> <div>{t("paste")}</div>
<div>{isMac ? "⌘ V" : "Ctrl+V"}</div> <div>{isMacos ? "⌘ V" : "Ctrl+V"}</div>
</MenuItem> </MenuItem>
), ),
key: "paste", key: "paste",
@@ -864,7 +864,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("replace")}</div> <div>{t("replace")}</div>
<div>{isMac ? "⇧ ⌘ V" : "Ctrl+Shift+V"} </div> <div>{isMacos ? "⇧ ⌘ V" : "Ctrl+Shift+V"} </div>
</MenuItem> </MenuItem>
), ),
key: "replace", key: "replace",
@@ -873,7 +873,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("insertNode")}</div> <div>{t("insertNode")}</div>
<div>{isMac ? <IoMdReturnLeft /> : "Enter"}</div> <div>{isMacos ? <IoMdReturnLeft /> : "Enter"}</div>
</MenuItem> </MenuItem>
), ),
key: "insert", key: "insert",
@@ -882,7 +882,7 @@ export const Editor: FC<EditorProps> = ({ onUpdate: updateState, data: editor, .
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("deleteNode")}</div> <div>{t("deleteNode")}</div>
<div>{isMac ? <FiDelete /> : "Backspace"}</div> <div>{isMacos ? <FiDelete /> : "Backspace"}</div>
</MenuItem> </MenuItem>
), ),
key: "delete", key: "delete",
+90 -24
View File
@@ -1,4 +1,4 @@
import { FileModel, useWorkspace } from "@/contexts/workspace-context"; import { FileTreeType, useWorkspace } from "@/contexts/workspace-context";
import * as b3util from "@/misc/b3util"; import * as b3util from "@/misc/b3util";
import { modal } from "@/misc/hooks"; import { modal } from "@/misc/hooks";
import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys"; import { Hotkey, isHotkeyPressed, isMacos, useHotkeys } from "@/misc/keys";
@@ -10,9 +10,11 @@ import { ipcRenderer, shell } 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, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { BsBoxFill } from "react-icons/bs";
import { FaExclamationTriangle, FaSwatchbook } from "react-icons/fa"; import { FaExclamationTriangle, FaSwatchbook } from "react-icons/fa";
import { FiCommand, FiDelete } from "react-icons/fi"; import { FiCommand, FiDelete } from "react-icons/fi";
import { IoMdReturnLeft } from "react-icons/io"; import { IoMdReturnLeft } from "react-icons/io";
import { PiTreeStructureFill } from "react-icons/pi";
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
@@ -29,7 +31,7 @@ type MenuEvent =
| "move" | "move"
| "duplicate"; | "duplicate";
const findFile = (path: string | undefined, node: FileModel): FileModel | undefined => { const findFile = (path: string | undefined, node: FileTreeType): FileTreeType | undefined => {
if (!path) { if (!path) {
return; return;
} else if (node.path === path) { } else if (node.path === path) {
@@ -45,7 +47,7 @@ const findFile = (path: string | undefined, node: FileModel): FileModel | undefi
} }
}; };
const findParent = (node: FileModel, parent?: FileModel): FileModel | undefined => { const findParent = (node: FileTreeType, parent?: FileTreeType): FileTreeType | undefined => {
if (parent && parent.children) { if (parent && parent.children) {
if (parent.children?.indexOf(node) >= 0) { if (parent.children?.indexOf(node) >= 0) {
return parent; return parent;
@@ -59,7 +61,7 @@ const findParent = (node: FileModel, parent?: FileModel): FileModel | undefined
} }
}; };
const resolveKeys = (path: string, node: FileModel, keys: React.Key[]) => { const resolveKeys = (path: string, node: FileTreeType, keys: React.Key[]) => {
if (node.path === path) { if (node.path === path) {
return true; return true;
} }
@@ -103,13 +105,18 @@ const renameFile = (oldPath: string, newPath: string) => {
return false; return false;
}; };
const getSvgIcon = (path: string) => {};
export const Explorer: FC = () => { export const Explorer: FC = () => {
const workspace = { const workspace = {
close: useWorkspace((state) => state.close), close: useWorkspace((state) => state.close),
editing: useWorkspace((state) => state.editing), editing: useWorkspace((state) => state.editing),
editors: useWorkspace((state) => state.editors), editors: useWorkspace((state) => state.editors),
open: useWorkspace((state) => state.open),
fileTree: useWorkspace((state) => state.fileTree), fileTree: useWorkspace((state) => state.fileTree),
nodeDefs: useWorkspace((state) => state.nodeDefs),
nodeTree: useWorkspace((state) => state.nodeTree),
workdir: useWorkspace((state) => state.workdir),
open: useWorkspace((state) => state.open),
}; };
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedKeys, setSelectedKeys] = useState<string[]>([]); const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
@@ -121,7 +128,54 @@ export const Explorer: FC = () => {
const [contextMenu, setContextMenu] = useState<ItemType[]>([]); const [contextMenu, setContextMenu] = useState<ItemType[]>([]);
if (workspace.fileTree) { if (workspace.fileTree) {
workspace.fileTree.icon = <FaSwatchbook style={{ marginTop: "5px" }} />; workspace.fileTree.icon = (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<FaSwatchbook />
</Flex>
);
}
if (workspace.nodeTree) {
workspace.nodeTree.icon = (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<PiTreeStructureFill size={19} />
</Flex>
);
workspace.nodeTree.children?.forEach((catalog) => {
catalog.icon = (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<img
className="b3-node-icon"
style={{ width: "14px", height: "14px", color: "white" }}
src={`/icons/${catalog.title}.svg`}
/>
</Flex>
);
catalog.children?.forEach((node) => {
if (node.def?.icon) {
node.icon = (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<img
className="b3-node-icon"
key={catalog.title}
style={{ width: "13px", height: "13px", color: "white" }}
src={
process.env.VITE_DEV_SERVER_URL && isMacos
? `${Path.basename(workspace.workdir)}/${node.def?.icon}`
: `${workspace.workdir}/${node.def?.icon}`
}
/>
</Flex>
);
} else {
node.icon = (
<Flex justify="center" align="center" style={{ height: "100%" }}>
<BsBoxFill style={{ width: "12px", height: "12px", color: "white" }} />{" "}
</Flex>
);
}
});
});
} }
useEffect(() => { useEffect(() => {
@@ -182,7 +236,7 @@ export const Explorer: FC = () => {
} }
); );
const submitRename = (node: FileModel) => { const submitRename = (node: FileTreeType) => {
if (!newName) { if (!newName) {
if (fs.existsSync(node.path)) { if (fs.existsSync(node.path)) {
node.editing = false; node.editing = false;
@@ -214,14 +268,14 @@ export const Explorer: FC = () => {
setNewName(null); setNewName(null);
}; };
const dispatch = (event: MenuEvent, node: FileModel, dest?: FileModel) => { const dispatch = (event: MenuEvent, node: FileTreeType, dest?: FileTreeType) => {
switch (event) { switch (event) {
case "open": { case "open": {
workspace.open(node.path); workspace.open(node.path);
break; break;
} }
case "newFolder": { case "newFolder": {
const folderNode: FileModel = { const folderNode: FileTreeType = {
path: node.path + "/:", path: node.path + "/:",
title: "", title: "",
children: [], children: [],
@@ -235,7 +289,7 @@ export const Explorer: FC = () => {
break; break;
} }
case "newFile": { case "newFile": {
const folderNode: FileModel = { const folderNode: FileTreeType = {
path: node.path + "/.json", path: node.path + "/.json",
title: "", title: "",
isLeaf: true, isLeaf: true,
@@ -489,7 +543,7 @@ export const Explorer: FC = () => {
></Flex> ></Flex>
); );
}; };
const isMac = process.platform === "darwin";
const arr: MenuProps["items"] = [ const arr: MenuProps["items"] = [
{ {
label: ( label: (
@@ -503,7 +557,7 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("copy")}</div> <div>{t("copy")}</div>
<div>{isMac ? "⌘ C" : "Ctrl+C"}</div> <div>{isMacos ? "⌘ C" : "Ctrl+C"}</div>
</MenuItem> </MenuItem>
), ),
key: "copy", key: "copy",
@@ -512,7 +566,7 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("duplicate")}</div> <div>{t("duplicate")}</div>
<div>{isMac ? "⌘ D" : "Ctrl+D"}</div> <div>{isMacos ? "⌘ D" : "Ctrl+D"}</div>
</MenuItem> </MenuItem>
), ),
key: "duplicate", key: "duplicate",
@@ -520,7 +574,7 @@ export const Explorer: FC = () => {
{ {
label: ( label: (
<MenuItem> <MenuItem>
<div>{isMac ? t("revealFileOnMac") : t("revealFileOnWindows")}</div> <div>{isMacos ? t("revealFileOnMac") : t("revealFileOnWindows")}</div>
</MenuItem> </MenuItem>
), ),
key: "revealFile", key: "revealFile",
@@ -529,8 +583,8 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("rename")}</div> <div>{t("rename")}</div>
{isMac && <IoMdReturnLeft />} {isMacos && <IoMdReturnLeft />}
{!isMac && <div>F2</div>} {!isMacos && <div>F2</div>}
</MenuItem> </MenuItem>
), ),
key: "rename", key: "rename",
@@ -539,7 +593,7 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("delete")}</div> <div>{t("delete")}</div>
{isMac && ( {isMacos && (
<Space size={6}> <Space size={6}>
<FiCommand /> <FiCommand />
<FiDelete /> <FiDelete />
@@ -563,7 +617,7 @@ export const Explorer: FC = () => {
></Flex> ></Flex>
); );
}; };
const isMac = process.platform === "darwin";
const arr: MenuProps["items"] = [ const arr: MenuProps["items"] = [
{ {
label: ( label: (
@@ -584,7 +638,7 @@ export const Explorer: FC = () => {
{ {
label: ( label: (
<MenuItem> <MenuItem>
<div>{isMac ? t("revealFileOnMac") : t("revealFileOnWindows")}</div> <div>{isMacos ? t("revealFileOnMac") : t("revealFileOnWindows")}</div>
</MenuItem> </MenuItem>
), ),
key: "revealFile", key: "revealFile",
@@ -593,7 +647,7 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div style={{ color: copyFile ? "inherit" : "gray" }}>{t("paste")}</div> <div style={{ color: copyFile ? "inherit" : "gray" }}>{t("paste")}</div>
<div style={{ color: copyFile ? "inherit" : "gray" }}>{isMac ? "⌘ V" : "Ctrl+V"}</div> <div style={{ color: copyFile ? "inherit" : "gray" }}>{isMacos ? "⌘ V" : "Ctrl+V"}</div>
</MenuItem> </MenuItem>
), ),
key: "paste", key: "paste",
@@ -602,8 +656,8 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("rename")}</div> <div>{t("rename")}</div>
{isMac && <IoMdReturnLeft />} {isMacos && <IoMdReturnLeft />}
{!isMac && <div>F2</div>} {!isMacos && <div>F2</div>}
</MenuItem> </MenuItem>
), ),
key: "rename", key: "rename",
@@ -612,7 +666,7 @@ export const Explorer: FC = () => {
label: ( label: (
<MenuItem> <MenuItem>
<div>{t("delete")}</div> <div>{t("delete")}</div>
{isMac && ( {isMacos && (
<Space size={6}> <Space size={6}>
<FiCommand /> <FiCommand />
<FiDelete /> <FiDelete />
@@ -626,6 +680,8 @@ export const Explorer: FC = () => {
return arr; return arr;
}, [t, copyFile]); }, [t, copyFile]);
const nodeConfs = useMemo(() => {}, [workspace.nodeDefs]);
const onClick = (info: MenuInfo) => { const onClick = (info: MenuInfo) => {
const node = findFile(selectedKeys[0], workspace.fileTree!) ?? workspace.fileTree; const node = findFile(selectedKeys[0], workspace.fileTree!) ?? workspace.fileTree;
if (node) { if (node) {
@@ -650,7 +706,11 @@ export const Explorer: FC = () => {
<div style={{ padding: "12px 24px" }}> <div style={{ padding: "12px 24px" }}>
<span style={{ fontSize: "18px", fontWeight: "600" }}>{t("explorer.title")}</span> <span style={{ fontSize: "18px", fontWeight: "600" }}>{t("explorer.title")}</span>
</div> </div>
<Flex vertical style={{ overflow: "auto", height: "100%", paddingBottom: "20px" }}> <Flex
vertical
className={isMacos ? undefined : "b3-overflow"}
style={{ overflow: "auto", height: "100%", paddingBottom: "20px" }}
>
<Dropdown menu={{ items: contextMenu, onClick }} trigger={["contextMenu"]}> <Dropdown menu={{ items: contextMenu, onClick }} trigger={["contextMenu"]}>
<div> <div>
<DirectoryTree <DirectoryTree
@@ -728,6 +788,12 @@ export const Explorer: FC = () => {
/> />
</div> </div>
</Dropdown> </Dropdown>
<DirectoryTree
tabIndex={-1}
fieldNames={{ key: "title" }}
treeData={workspace.nodeTree ? [workspace.nodeTree] : []}
switcherIcon={<DownOutlined />}
/>
</Flex> </Flex>
</Flex> </Flex>
); );
+10 -4
View File
@@ -1,6 +1,6 @@
import { EditNode, EditTree, FileModel, useWorkspace } from "@/contexts/workspace-context"; import { EditNode, EditTree, FileTreeType, useWorkspace } from "@/contexts/workspace-context";
import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type"; import { NodeModel, TreeGraphData, TreeModel } from "@/misc/b3type";
import { Hotkey } from "@/misc/keys"; import { Hotkey, isMacos } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import { AutoComplete, Divider, Flex, Form, Input, InputNumber, Select, Switch } from "antd"; import { AutoComplete, Divider, Flex, Form, Input, InputNumber, Select, Switch } from "antd";
import { DefaultOptionType } from "antd/es/select"; import { DefaultOptionType } from "antd/es/select";
@@ -116,7 +116,10 @@ export const Inspector: FC = () => {
<div style={{ padding: "12px 24px" }}> <div style={{ padding: "12px 24px" }}>
<span style={{ fontSize: "18px", fontWeight: "600" }}>{t("tree.overview")}</span> <span style={{ fontSize: "18px", fontWeight: "600" }}>{t("tree.overview")}</span>
</div> </div>
<div style={{ overflow: "auto", height: "100%", padding: "24px" }}> <div
className={isMacos ? undefined : "b3-overflow"}
style={{ overflow: "auto", height: "100%", padding: "24px" }}
>
<Form form={form} labelCol={{ span: 8 }} onFinish={finish}> <Form form={form} labelCol={{ span: 8 }} onFinish={finish}>
<Form.Item name="name" label={t("tree.name")}> <Form.Item name="name" label={t("tree.name")}>
<Input disabled={true} /> <Input disabled={true} />
@@ -197,7 +200,10 @@ export const Inspector: FC = () => {
<div style={{ padding: "12px 24px" }}> <div style={{ padding: "12px 24px" }}>
<span style={{ fontSize: "18px", fontWeight: "600" }}>{def.desc}</span> <span style={{ fontSize: "18px", fontWeight: "600" }}>{def.desc}</span>
</div> </div>
<div style={{ overflow: "auto", height: "100%", padding: "24px" }}> <div
className={isMacos ? undefined : "b3-overflow"}
style={{ overflow: "auto", height: "100%", padding: "24px" }}
>
<Form <Form
form={form} form={form}
wrapperCol={{ span: "auto" }} wrapperCol={{ span: "auto" }}
+8 -25
View File
@@ -2,7 +2,7 @@ import { useSetting } from "@/contexts/setting-context";
import { useWorkspace } from "@/contexts/workspace-context"; import { useWorkspace } from "@/contexts/workspace-context";
import * as b3util from "@/misc/b3util"; import * as b3util from "@/misc/b3util";
import i18n from "@/misc/i18n"; import i18n from "@/misc/i18n";
import { Hotkey, sendInputEvent } from "@/misc/keys"; import { Hotkey, isMacos, sendInputEvent } from "@/misc/keys";
import { CheckOutlined } from "@ant-design/icons"; import { CheckOutlined } from "@ant-design/icons";
import { Menu as AppMenu, BrowserWindow, app, dialog } from "@electron/remote"; import { Menu as AppMenu, BrowserWindow, app, dialog } from "@electron/remote";
import { Button, DropDownProps, Dropdown, Flex, FlexProps, LayoutProps, Space } from "antd"; import { Button, DropDownProps, Dropdown, Flex, FlexProps, LayoutProps, Space } from "antd";
@@ -61,7 +61,6 @@ export const Menu: FC<LayoutProps> = () => {
recent: useSetting((state) => state.recent), recent: useSetting((state) => state.recent),
}; };
const isMac = process.platform === "darwin";
const menuTemplate: MenuItemConstructorOptions[] = useMemo(() => { const menuTemplate: MenuItemConstructorOptions[] = useMemo(() => {
const recentWorkspaces: MenuItemConstructorOptions[] = settings.recent.map((path, i) => ({ const recentWorkspaces: MenuItemConstructorOptions[] = settings.recent.map((path, i) => ({
id: "menu.file.recent" + i, id: "menu.file.recent" + i,
@@ -70,7 +69,7 @@ export const Menu: FC<LayoutProps> = () => {
})); }));
return [ return [
// { role: 'appMenu' } // { role: 'appMenu' }
...(isMac ...(isMacos
? [ ? [
{ {
id: "menu.app", id: "menu.app",
@@ -341,31 +340,15 @@ export const Menu: FC<LayoutProps> = () => {
}, },
], ],
}, },
// {
// id: "menu.window",
// label: t("menu.window"),
// submenu: [
// { id: "menu.window.minimize", role: "minimize" },
// { id: "menu.window.zoom", role: "zoom" },
// ...(isMac
// ? [
// { type: "separator" },
// { id: "menu.window.front", role: "front" },
// { type: "separator" },
// { id: "menu.window.window", role: "window" },
// ]
// : [{ id: "menu.window.close", role: "close" }]),
// ],
// },
] as MenuItemConstructorOptions[]; ] as MenuItemConstructorOptions[];
}, [t, workspace.workdir, settings.recent, workspace.editing]); }, [t, workspace.workdir, settings.recent, workspace.editing]);
if (isMac) { if (isMacos) {
const menu = AppMenu.buildFromTemplate(menuTemplate); const menu = AppMenu.buildFromTemplate(menuTemplate);
AppMenu.setApplicationMenu(menu); AppMenu.setApplicationMenu(menu);
} }
if (!process.env.VITE_DEV_SERVER_URL && isMac) { if (!process.env.VITE_DEV_SERVER_URL && isMacos) {
return <div />; return <div />;
} }
@@ -387,15 +370,15 @@ export const Menu: FC<LayoutProps> = () => {
const keys = (option.accelerator?.split("+") ?? []).map((key) => { const keys = (option.accelerator?.split("+") ?? []).map((key) => {
const lowerKey = key.toLowerCase(); const lowerKey = key.toLowerCase();
if (lowerKey.indexOf("alt") !== -1) { if (lowerKey.indexOf("alt") !== -1) {
return isMac ? "⌥" : "Alt"; return isMacos ? "⌥" : "Alt";
} else if ( } else if (
lowerKey.indexOf("cmdorctrl") !== -1 || lowerKey.indexOf("cmdorctrl") !== -1 ||
lowerKey.indexOf("ctrl") !== -1 || lowerKey.indexOf("ctrl") !== -1 ||
lowerKey.indexOf("meta") !== -1 lowerKey.indexOf("meta") !== -1
) { ) {
return isMac ? "⌘" : "Ctrl"; return isMacos ? "⌘" : "Ctrl";
} else if (lowerKey.indexOf("shift") !== -1) { } else if (lowerKey.indexOf("shift") !== -1) {
return isMac ? "⇧" : "Shift"; return isMacos ? "⇧" : "Shift";
} else { } else {
return key.toUpperCase().replace("=", "+"); return key.toUpperCase().replace("=", "+");
} }
@@ -423,7 +406,7 @@ export const Menu: FC<LayoutProps> = () => {
)} )}
{option.label} {option.label}
</div> </div>
<div>{keys.join(isMac ? " " : "+")}</div> <div>{keys.join(isMacos ? " " : "+")}</div>
</MenuItemLabel> </MenuItemLabel>
), ),
key: option.id ?? "", key: option.id ?? "",
+3 -4
View File
@@ -1,7 +1,7 @@
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, setInputFocus, useHotkeys } from "@/misc/keys"; import { Hotkey, isHotkeyPressed, isMacos, setInputFocus, useHotkeys } from "@/misc/keys";
import Path from "@/misc/path"; import Path from "@/misc/path";
import { app } from "@electron/remote"; import { app } from "@electron/remote";
import { Button, Flex, Layout, Space, Tabs, Tag, Tooltip } from "antd"; import { Button, Flex, Layout, Space, Tabs, Tag, Tooltip } from "antd";
@@ -41,7 +41,6 @@ export const Workspace: FC = () => {
const [isShowingSave, setShowingSave] = useState(false); const [isShowingSave, setShowingSave] = useState(false);
const { t } = useTranslation(); const { t } = useTranslation();
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
const isMac = process.platform === "darwin";
const { width = 0, height = 0 } = useWindowSize(); const { width = 0, height = 0 } = useWindowSize();
const keysRef = useHotkeys<HTMLDivElement>( const keysRef = useHotkeys<HTMLDivElement>(
@@ -333,8 +332,8 @@ export const Workspace: FC = () => {
}} }}
> >
{[ {[
{ label: t("searchFile"), hotkeys: isMac ? "⌘ P" : "Ctrl + P" }, { label: t("searchFile"), hotkeys: isMacos ? "⌘ P" : "Ctrl + P" },
{ label: t("build"), hotkeys: isMac ? "⌘ B" : "Ctrl + B" }, { label: t("build"), hotkeys: isMacos ? "⌘ B" : "Ctrl + B" },
{ label: t("insertNode"), hotkeys: "Enter" }, { label: t("insertNode"), hotkeys: "Enter" },
{ label: t("deleteNode"), hotkeys: "Backspace" }, { label: t("deleteNode"), hotkeys: "Backspace" },
].map((v) => ( ].map((v) => (
+49 -8
View File
@@ -68,14 +68,24 @@ export class EditorStore {
} }
} }
export type FileModel = { export type FileTreeType = {
path: string; path: string;
title: string; title: string;
icon?: React.ReactNode; icon?: React.ReactNode;
desc?: string; desc?: string;
isLeaf?: boolean; isLeaf?: boolean;
children?: FileModel[]; children?: FileTreeType[];
editing?: boolean; editing?: boolean;
style?: React.CSSProperties;
};
export type NodeTreeType = {
title: string;
def?: NodeDef;
icon?: React.ReactNode;
isLeaf?: boolean;
children?: NodeTreeType[];
style?: React.CSSProperties;
}; };
export type EditNode = { export type EditNode = {
@@ -98,7 +108,8 @@ export type WorkspaceStore = {
path: string; path: string;
allFiles: string[]; allFiles: string[];
fileTree?: FileModel; nodeTree?: NodeTreeType;
fileTree?: FileTreeType;
editors: EditorStore[]; editors: EditorStore[];
editing?: EditorStore; editing?: EditorStore;
@@ -143,7 +154,7 @@ const loadFileTree = (workdir: string, filename: string) => {
return; return;
} }
const data: FileModel = { const data: FileTreeType = {
path: fullpath.replaceAll(Path.sep, "/"), path: fullpath.replaceAll(Path.sep, "/"),
title: Path.basename(filename), title: Path.basename(filename),
}; };
@@ -412,11 +423,15 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
loadTrees: () => { loadTrees: () => {
const workspace = get(); const workspace = get();
const data = loadFileTree(workspace.workdir, ".")!; const data = loadFileTree(workspace.workdir, ".")!;
data.title = Path.basename(workspace.workdir); data.title = Path.basename(workspace.workdir).toUpperCase();
data.style = {
fontWeight: "bold",
fontSize: "13px",
};
set({ fileTree: data }); set({ fileTree: data });
const allFiles: string[] = []; const allFiles: string[] = [];
const collect = (fileNode?: FileModel) => { const collect = (fileNode?: FileTreeType) => {
if (fileNode?.isLeaf) { if (fileNode?.isLeaf) {
allFiles.push(fileNode.path); allFiles.push(fileNode.path);
} }
@@ -429,10 +444,36 @@ export const useWorkspace = create<WorkspaceStore>((set, get) => ({
loadNodeDefs: () => { loadNodeDefs: () => {
const workspace = get(); 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 nodeTree: NodeTreeType = {
title: "NODES",
children: [],
style: {
fontWeight: "bold",
fontSize: "13px",
},
};
const nodeDefs: Map<string, NodeDef> = new Map();
for (const v of nodeDefData) { for (const v of nodeDefData) {
workspace.nodeDefs.set(v.name, v); nodeDefs.set(v.name, v);
let catalog: NodeTreeType | undefined = nodeTree.children?.find((nt) => nt.title === v.type);
if (!catalog) {
catalog = {
title: v.type,
children: [],
};
nodeTree.children?.push(catalog);
} }
set({ nodeDefs: workspace.nodeDefs }); catalog.children?.push({
title: `${v.name}(${v.desc})`,
isLeaf: true,
def: v,
});
}
nodeTree.children?.sort((a, b) => a.title.localeCompare(b.title));
nodeTree.children?.forEach((child) =>
child.children?.sort((a, b) => a.title.localeCompare(b.title))
);
set({ nodeDefs, nodeTree });
workspace.editing?.dispatch?.("reload"); workspace.editing?.dispatch?.("reload");
}, },
+14 -10
View File
@@ -16,20 +16,24 @@
--b3-color-border: #30363d; --b3-color-border: #30363d;
} }
::-webkit-scrollbar {
width: 9px;
}
::-webkit-scrollbar-thumb {
background: #30363d;
border-radius: 9px;
-webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
}
body { body {
margin: 0; margin: 0;
} }
.b3-node-icon {
filter: invert(100%) sepia(5%) saturate(1%) hue-rotate(320deg) brightness(104%) contrast(100%);
}
.b3-overflow::-webkit-scrollbar {
width: 8px;
}
.b3-overflow::-webkit-scrollbar-thumb {
background: #30363d;
border-radius: 4px;
-webkit-box-shadow: inset006pxrgba(0, 0, 0, 0.5);
}
.b3-drag-region { .b3-drag-region {
-webkit-app-region: drag; -webkit-app-region: drag;
} }
+1 -1
View File
@@ -14,7 +14,7 @@ export interface NodeArg {
} }
export interface NodeDef { export interface NodeDef {
name: string; name: string;
type?: string; type: string;
desc?: string; desc?: string;
args?: NodeArg[]; args?: NodeArg[];
input?: string[]; input?: string[];