add nanoid for node

This commit is contained in:
codetypes committed 2025-09-29 14:44:03 +08:00
1 parent bbdf7a95d6
commit 05cce8f91f
9 files changed
+114 -54

No files matched your search

+23 -14
View File
@@ -19,7 +19,7 @@ import * as b3util from "../misc/b3util";
import { message } from "../misc/hooks";
import i18n from "../misc/i18n";
import Path from "../misc/path";
import { readTree, writeTree } from "../misc/util";
import { nanoid, readTree, writeTree } from "../misc/util";
import { TreeNodeState, TreeNodeStyle } from "./register-node";
type G6NodeState = Exclude<G6GraphOptions["node"], undefined>["state"];
@@ -89,8 +89,8 @@ export class Graph {
const dataB = nodeB.data as unknown as NodeData;
return Number(dataA.id) - Number(dataB.id);
},
getHeight: ({ data }: { data: NodeData }) => data.size![1],
getWidth: ({ data }: { data: NodeData }) => data.size![0],
getHeight: ({ data }: { data: NodeData }) => data.$size![1],
getWidth: ({ data }: { data: NodeData }) => data.$size![0],
getVGap: () => 10,
getHGap: () => 30,
},
@@ -147,7 +147,7 @@ export class Graph {
private async _update(data: TreeData, refreshId: boolean = true, refreshVars: boolean = false) {
this.editor.data = data;
if (refreshId) {
b3util.refreshNodeData(this.data.root, 1);
b3util.refreshNodeData(this.data, this.data.root, 1);
}
if (refreshVars) {
@@ -471,18 +471,24 @@ export class Graph {
async updateNode(editNode: EditNode) {
const node = this._graph.getNodeData(editNode.data.id);
const data = node.data as unknown as NodeData;
let data = node.data as unknown as NodeData;
if (b3util.isNodeEqual(data, editNode.data)) {
return;
}
const subtree = data.path;
// update node
node.data = { ...editNode.data, size: b3util.calcSize(editNode.data) };
data = { ...editNode.data, $size: b3util.calcSize(editNode.data) };
if (editNode.data.name !== data.name) {
data.$id = nanoid();
}
node.data = data as unknown as Record<string, unknown>;
this._graph.updateNodeData([node]);
await this._graph.draw();
// update subtree
if (data.path !== editNode.data.path) {
if (subtree !== editNode.data.path) {
this.editor.data.root = this._nodeToData("1");
await this.refresh();
}
@@ -640,7 +646,7 @@ export class Graph {
const id = this._dropId;
const pos = this._graph.getElementPosition(id);
const data = this._graph.getNodeData(id).data as unknown as NodeData;
const [w, h] = data.size!;
const [w, h] = data.$size!;
const x = e.canvas.x - pos[0];
const y = e.canvas.y - pos[1];
const states = this._getState(id);
@@ -803,17 +809,20 @@ export class Graph {
}
console.debug("parse node:", str);
const node = JSON.parse(str) as NodeData;
b3util.dfs(node, (v) => (v.$id = nanoid()));
const root = this._nodeToData("1");
let dstData: NodeData | undefined;
b3util.dfs(root, (node) => {
if (node.id === this._selectedId) {
dstData = node;
b3util.dfs(root, (v) => {
if (v.id === this._selectedId) {
dstData = v;
}
});
assert(dstData, this._selectedId);
dstData.children ||= [];
dstData.children.push(JSON.parse(str) as NodeData);
dstData.children.push(node);
this.selectNode(null);
await this._update({ ...this.data, root });
this._storeHistory();
@@ -881,7 +890,7 @@ export class Graph {
assert(dstData, this._selectedId);
dstData.children ||= [];
dstData.children.push({ id: "", name: "unknow" });
dstData.children.push({ id: "", name: "unknow", $id: nanoid() });
await this._update({ ...this.data, root });
this._storeHistory();
}
@@ -920,7 +929,7 @@ export class Graph {
hasSubtreeUpdated() {
let updated = false;
b3util.dfs(this.data.root, (node) => {
if (node.path && b3util.files[node.path] !== node.mtime) {
if (node.path && b3util.files[node.path] !== node.$mtime) {
updated = true;
}
});
+1
View File
@@ -822,6 +822,7 @@ const NodeInspector: FC = () => {
if (editingNode.data.name !== newname) {
workspace.onEditingNode({
data: {
$id: editingNode.data.$id,
id: editingNode.data.id,
name: workspace.nodeDefs.get(newname)?.name ?? newname,
desc: editingNode.data.desc,
+3 -3
View File
@@ -388,7 +388,7 @@ class TreeNode extends Rect {
}
private drawStatusIcon(attributes: Required<RectStyleProps>, container: Group) {
const status = ((this._data.status ?? 0) & 0b111).toString(2).padStart(3, "0");
const status = ((this._data.$status ?? 0) & 0b111).toString(2).padStart(3, "0");
this.upsert(
"status",
GImage,
@@ -758,8 +758,8 @@ class TreeNode extends Rect {
color = NODE_COLORS[classify];
}
assert(data.size);
const [width, height] = data.size;
assert(data.$size);
const [width, height] = data.$size;
this._prefix = (node.prefix as string) ?? "";
this._width = width;
+10 -3
View File
@@ -27,10 +27,13 @@ export interface NodeData {
disabled?: boolean;
path?: string;
// nanoid, for override
$id: string;
// for runtime
mtime?: number;
size?: number[];
status?: number;
$mtime?: number;
$size?: number[];
$status?: number;
}
export type NodeLayout = "compact" | "normal";
@@ -71,6 +74,10 @@ export interface TreeData {
import: string[];
vars: VarDecl[];
root: NodeData;
$override: {
[key: string]: Pick<NodeData, "desc" | "input" | "output" | "args" | "debug" | "disabled">;
};
}
export const getNodeType = (def: NodeDef): NodeType => {
+23 -19
View File
@@ -20,7 +20,7 @@ import {
VERSION,
} from "./b3type";
import Path from "./path";
import { readJson, readTree, readWorkspace } from "./util";
import { nanoid, readJson, readTree, readWorkspace } from "./util";
export class NodeDefs extends Map<string, NodeDef> {
get(key: string): NodeDef {
@@ -520,6 +520,7 @@ const parsingStack: string[] = [];
export const createNode = (data: NodeData, includeChildren: boolean = true) => {
const node: NodeData = {
$id: data.$id,
id: data.id,
name: data.name,
desc: data.desc,
@@ -598,7 +599,7 @@ const appendStatusFlag = (status: number, childStatus: number) => {
};
const buildStatusFlag = (data: NodeData, childStatus: number) => {
let status = data.status!;
let status = data.$status!;
const def = nodeDefs.get(data.name);
if (def.status?.length) {
const childSuccess = (childStatus >> StatusFlag.SUCCESS) & 1;
@@ -639,9 +640,9 @@ const buildStatusFlag = (data: NodeData, childStatus: number) => {
break;
}
});
data.status = status;
data.$status = status;
} else {
data.status = status | childStatus;
data.$status = status | childStatus;
}
};
@@ -694,9 +695,9 @@ export const checkTreeData = (data: NodeData) => {
return true;
};
export const refreshNodeData = (node: NodeData, id: number) => {
export const refreshNodeData = (tree: TreeData, node: NodeData, id: number) => {
node.id = (id++).toString();
node.size = calcSize(node);
node.$size = calcSize(node);
const def = nodeDefs.get(node.name);
@@ -718,16 +719,16 @@ export const refreshNodeData = (node: NodeData, id: number) => {
parsingStack.push(node.path);
try {
const subtreePath = workdir + "/" + node.path;
const subtree = readTree(subtreePath).root;
id = refreshNodeData(subtree, --id);
const subtree = readTree(subtreePath);
id = refreshNodeData(subtree, subtree.root, --id);
node.name = subtree.name;
node.desc = subtree.desc;
node.args = subtree.args;
node.input = subtree.input;
node.output = subtree.output;
node.children = subtree.children;
node.mtime = fs.statSync(subtreePath).mtimeMs;
node.size = calcSize(node);
node.args = subtree.root.args;
node.input = subtree.root.input;
node.output = subtree.root.output;
node.children = subtree.root.children;
node.$mtime = fs.statSync(subtreePath).mtimeMs;
node.$size = calcSize(node);
} catch (e) {
alertError(`解析子树失败:${node.path}`);
console.log("parse subtree:", e);
@@ -735,16 +736,16 @@ export const refreshNodeData = (node: NodeData, id: number) => {
parsingStack.pop();
} else if (node.children?.length) {
for (let i = 0; i < node.children.length; i++) {
id = refreshNodeData(node.children[i], id);
id = refreshNodeData(tree, node.children[i], id);
}
}
node.status = toStatusFlag(node);
node.$status = toStatusFlag(node);
if (node.children) {
let childStatus = 0;
node.children.forEach((child) => {
if (child.status && !child.disabled) {
childStatus = appendStatusFlag(childStatus, child.status);
if (child.$status && !child.disabled) {
childStatus = appendStatusFlag(childStatus, child.$status);
}
});
buildStatusFlag(node, childStatus);
@@ -756,7 +757,7 @@ export const refreshNodeData = (node: NodeData, id: number) => {
export const createBuildData = (path: string) => {
try {
const treeModel: TreeData = readTree(path);
refreshNodeData(treeModel.root, 1);
refreshNodeData(treeModel, treeModel.root, 1);
dfs(treeModel.root, (node) => (node.id = treeModel.prefix + node.id));
treeModel.name = Path.basenameWithoutExt(path);
treeModel.root = createFileData(treeModel.root, true);
@@ -885,6 +886,7 @@ export const loadModule = async (path: string) => {
export const createFileData = (data: NodeData, includeSubtree?: boolean) => {
const nodeData: NodeData = {
$id: data.$id,
id: data.id,
name: data.name,
desc: data.desc || undefined,
@@ -926,7 +928,9 @@ export const createNewTree = (path: string) => {
root: {
id: "1",
name: "Sequence",
$id: nanoid(),
},
$override: {},
};
return tree;
};
+16 -4
View File
@@ -1,9 +1,15 @@
import * as fs from "fs";
import { customAlphabet } from "nanoid";
import { type WorkspaceModel } from "../contexts/workspace-context";
import { VarDecl, VERSION, type TreeData } from "./b3type";
import { VERSION, type TreeData } from "./b3type";
import { dfs } from "./b3util";
import Path from "./path";
export const nanoid = customAlphabet(
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
10
);
export const readJson = <T>(path: string): T => {
const str = fs.readFileSync(path, "utf-8");
return JSON.parse(str);
@@ -21,16 +27,21 @@ export const readWorkspace = (path: string) => {
};
export const readTree = (path: string) => {
const data = readJson(path) as TreeData & { declvar?: VarDecl[] };
const data = readJson(path) as TreeData;
data.version = data.version ?? VERSION;
data.prefix = data.prefix ?? "";
data.group = data.group || [];
data.import = data.import || [];
data.vars = data.vars || data.declvar || [];
data.vars = data.vars || [];
data.root = data.root || {};
// compatible with old version
dfs(data.root, (node) => (node.id = node.id.toString()));
dfs(data.root, (node) => {
node.id = node.id.toString();
if (!node.$id) {
node.$id = nanoid();
}
});
return data;
};
@@ -46,6 +57,7 @@ export const writeTree = (path: string, data: TreeData) => {
import: data.import,
vars: data.vars,
root: data.root,
$override: data.$override,
});
};