Browse Source

默认尺寸修改

feature/071
yun 1 week ago
parent
commit
bfb4ac2a64
  1. 14
      src/components/__tests__/GenerationComposer.test.tsx
  2. 44
      src/constants/nodeDimensions.ts
  3. 8
      src/store/__tests__/generationPreferenceStore.test.ts
  4. 26
      src/store/__tests__/workflowStore.integration.test.ts
  5. 4
      src/utils/__tests__/nodeSizing.test.ts
  6. 26
      src/utils/nodeDimensions.ts

14
src/components/__tests__/GenerationComposer.test.tsx

@ -1500,9 +1500,7 @@ describe("GenerationComposer", () => {
nodes: [
{
...imageNode("img-1", true, { aspectRatio: "16:9", parameters: {} }),
width: 360,
height: 203,
measured: { width: 360, height: 203 },
style: { width: 615, height: 346 },
} as WorkflowNode,
],
});
@ -1516,8 +1514,7 @@ describe("GenerationComposer", () => {
const data = node.data as NanoBananaNodeData;
expect(data.aspectRatio).toBe("9:16");
expect(data.parameters).toEqual({ ratio: "9:16" });
expect(node.width).toBe(203);
expect(node.height).toBe(360);
expect(node.style).toMatchObject({ width: 346, height: 615 });
});
});
@ -1546,9 +1543,7 @@ describe("GenerationComposer", () => {
nodes: [
{
...imageNode("img-1", true, { aspectRatio: "16:9", parameters: {} }),
width: 360,
height: 203,
measured: { width: 360, height: 203 },
style: { width: 615, height: 346 },
} as WorkflowNode,
],
});
@ -1560,8 +1555,7 @@ describe("GenerationComposer", () => {
const data = node.data as NanoBananaNodeData;
expect(data.parameters).toEqual({ ratio: "9:16" });
expect(data.aspectRatio).toBe("9:16");
expect(node.width).toBe(203);
expect(node.height).toBe(360);
expect(node.style).toMatchObject({ width: 346, height: 615 });
});
});

44
src/constants/nodeDimensions.ts

@ -3,34 +3,34 @@ import type { NodeType } from "@/types";
export type NodeDimensions = { width: number; height: number };
export const defaultNodeDimensions: Record<NodeType, NodeDimensions> = {
group: { width: 400, height: 300 },
group: { width: 420, height: 300 },
imageInput: { width: 300, height: 280 },
smartImage: { width: 300, height: 280 },
audioInput: { width: 300, height: 280 },
smartAudio: { width: 300, height: 280 },
audioInput: { width: 320, height: 180 },
smartAudio: { width: 360, height: 180 },
videoInput: { width: 300, height: 280 },
annotation: { width: 300, height: 280 },
annotation: { width: 520, height: 360 },
smartVideo: { width: 300, height: 280 },
prompt: { width: 300, height: 200 },
smartText: { width: 300, height: 200 },
array: { width: 300, height: 280 },
promptConstructor: { width: 300, height: 280 },
prompt: { width: 320, height: 180 },
smartText: { width: 360, height: 220 },
array: { width: 320, height: 220 },
promptConstructor: { width: 420, height: 280 },
nanoBanana: { width: 300, height: 280 },
generateVideo: { width: 300, height: 280 },
generate3d: { width: 300, height: 300 },
generateAudio: { width: 300, height: 280 },
llmGenerate: { width: 300, height: 200 },
output: { width: 300, height: 280 },
outputGallery: { width: 300, height: 280 },
imageCompare: { width: 400, height: 360 },
videoStitch: { width: 400, height: 280 },
easeCurve: { width: 340, height: 280 },
videoTrim: { width: 360, height: 360 },
videoFrameGrab: { width: 320, height: 320 },
router: { width: 200, height: 80 },
switch: { width: 220, height: 120 },
conditionalSwitch: { width: 260, height: 180 },
glbViewer: { width: 360, height: 380 },
generate3d: { width: 360, height: 300 },
generateAudio: { width: 360, height: 180 },
llmGenerate: { width: 360, height: 240 },
output: { width: 360, height: 260 },
outputGallery: { width: 420, height: 320 },
imageCompare: { width: 520, height: 360 },
videoStitch: { width: 420, height: 280 },
easeCurve: { width: 340, height: 260 },
videoTrim: { width: 420, height: 280 },
videoFrameGrab: { width: 360, height: 240 },
router: { width: 280, height: 180 },
switch: { width: 280, height: 180 },
conditionalSwitch: { width: 340, height: 240 },
glbViewer: { width: 420, height: 360 },
};
export const DEFAULT_NODE_DIMENSIONS: NodeDimensions = { width: 300, height: 280 };

8
src/store/__tests__/generationPreferenceStore.test.ts

@ -128,7 +128,7 @@ describe("generationPreferenceStore", () => {
await expect(buildDefaultGenerationNodeCreation("nanoBanana")).resolves.toEqual({
data: expect.any(Object),
size: { width: 360, height: 203 },
size: { width: 615, height: 346 },
});
});
@ -147,7 +147,7 @@ describe("generationPreferenceStore", () => {
await expect(buildDefaultGenerationNodeCreation("generateVideo")).resolves.toEqual({
data: expect.any(Object),
size: { width: 360, height: 203 },
size: { width: 615, height: 346 },
});
});
@ -166,7 +166,7 @@ describe("generationPreferenceStore", () => {
aspectRatio: "4:5",
parameters: { ratio: "4:5" },
}),
size: { width: 256, height: 320 },
size: { width: 346, height: 432 },
});
});
@ -245,7 +245,7 @@ describe("generationPreferenceStore", () => {
parameters: { ratio: "9:16" },
selectedModel: expect.objectContaining({ modelId: "44", billingMethod: 2 }),
}),
size: { width: 203, height: 360 },
size: { width: 346, height: 615 },
});
});

26
src/store/__tests__/workflowStore.integration.test.ts

@ -634,7 +634,7 @@ describe("workflowStore integration tests", () => {
});
const node = useWorkflowStore.getState().nodes[0];
expect(node).toMatchObject({ style: { width: 203, height: 360 } });
expect(node).toMatchObject({ style: { width: 346, height: 615 } });
expect(useWorkflowStore.getState().hasUnsavedChanges).toBe(true);
});
@ -685,7 +685,7 @@ describe("workflowStore integration tests", () => {
);
const node = useWorkflowStore.getState().nodes.find((candidate) => candidate.id === nodeId);
expect(node?.style).toMatchObject({ width: 203, height: 360 });
expect(node?.style).toMatchObject({ width: 346, height: 615 });
});
it("infers generation node dimensions from model parameter ratio", () => {
@ -696,7 +696,7 @@ describe("workflowStore integration tests", () => {
);
const node = useWorkflowStore.getState().nodes.find((candidate) => candidate.id === nodeId);
expect(node?.style).toMatchObject({ width: 360, height: 203 });
expect(node?.style).toMatchObject({ width: 615, height: 346 });
});
it("infers media node dimensions from initial media dimensions", () => {
@ -2130,7 +2130,7 @@ describe("workflowStore integration tests", () => {
});
describe("createGroup bounding box calculation", () => {
it("should correctly calculate bounding box for easeCurve nodes (340x280)", () => {
it("should correctly calculate bounding box for easeCurve nodes (340x260)", () => {
useWorkflowStore.setState({
nodes: [
createTestNode("ease-1", "easeCurve", {
@ -2173,13 +2173,13 @@ describe("workflowStore integration tests", () => {
expect(groupId).toBeTruthy();
const group = useWorkflowStore.getState().groups[groupId];
// easeCurve is 340x280, so maxX = 500 + 340 = 840, maxY = 100 + 280 = 380
// easeCurve is 340x260, so maxX = 500 + 340 = 840, maxY = 100 + 260 = 360
// With padding=20: position.x = 100-20=80, width = 840-100+40=780
expect(group.size.width).toBeGreaterThanOrEqual(740); // Must account for 340px wide nodes
expect(group.size.height).toBeGreaterThanOrEqual(280); // Must account for 280px tall nodes
expect(group.size.height).toBeGreaterThanOrEqual(260); // Must account for 260px tall nodes
});
it("should correctly calculate bounding box for videoStitch nodes (400x280)", () => {
it("should correctly calculate bounding box for videoStitch nodes (420x280)", () => {
useWorkflowStore.setState({
nodes: [
createTestNode("vs-1", "videoStitch", {
@ -2208,8 +2208,8 @@ describe("workflowStore integration tests", () => {
const groupId = store.createGroup(["vs-1"]);
const group = useWorkflowStore.getState().groups[groupId];
// videoStitch is 400x280, with padding=20: width = 400+40=440
expect(group.size.width).toBeGreaterThanOrEqual(400); // Must account for 400px wide node
// videoStitch is 420x280, with padding=20: width = 420+40=460
expect(group.size.width).toBeGreaterThanOrEqual(420); // Must account for 420px wide node
expect(group.size.height).toBeGreaterThanOrEqual(280); // Must account for 280px tall node
});
@ -2241,7 +2241,7 @@ describe("workflowStore integration tests", () => {
expect(imageNode?.position).toEqual({ x: 0, y: 0 });
});
it("should correctly calculate bounding box for audioInput nodes (300x200)", () => {
it("should correctly calculate bounding box for audioInput nodes (320x180)", () => {
useWorkflowStore.setState({
nodes: [
createTestNode("audio-1", "audioInput", {
@ -2259,9 +2259,9 @@ describe("workflowStore integration tests", () => {
const groupId = store.createGroup(["audio-1"]);
const group = useWorkflowStore.getState().groups[groupId];
// audioInput is 300x200, with padding=20: width = 300+40=340
expect(group.size.width).toBeGreaterThanOrEqual(300);
expect(group.size.height).toBeGreaterThanOrEqual(200);
// audioInput is 320x180, with padding=20: width = 320+40=360
expect(group.size.width).toBeGreaterThanOrEqual(320);
expect(group.size.height).toBeGreaterThanOrEqual(180);
});
it("should replace selected existing groups when creating a new group", () => {

4
src/utils/__tests__/nodeSizing.test.ts

@ -30,7 +30,7 @@ describe("resolveNodeAutoSize", () => {
aspectRatio: "9:16",
dimensions: null,
})
).toEqual({ width: 203, height: 360 });
).toEqual({ width: 346, height: 615 });
});
it("reads model ratio from parameters when no media url exists", () => {
@ -39,7 +39,7 @@ describe("resolveNodeAutoSize", () => {
outputVideo: null,
parameters: { ratio: "16:9" },
})
).toEqual({ width: 360, height: 203 });
).toEqual({ width: 615, height: 346 });
});
});

26
src/utils/nodeDimensions.ts

@ -193,28 +193,20 @@ export function calculateMediaNodeSizeByShortSide(
};
}
const GENERATION_NODE_SIZE_BY_ASPECT_RATIO: Record<string, { width: number; height: number }> = {
"1:1": { width: 300, height: 300 },
"16:9": { width: 360, height: 203 },
"9:16": { width: 203, height: 360 },
"21:9": { width: 420, height: 180 },
"2:3": { width: 227, height: 340 },
"3:2": { width: 340, height: 227 },
"3:4": { width: 255, height: 340 },
"4:3": { width: 340, height: 255 },
"4:5": { width: 256, height: 320 },
"5:4": { width: 320, height: 256 },
"1:4": { width: 140, height: 420 },
"4:1": { width: 420, height: 140 },
"1:8": { width: 100, height: 420 },
"8:1": { width: 420, height: 100 },
};
function parseAspectRatioValue(value: string): number | null {
const [widthText, heightText] = value.trim().split(":");
const width = Number(widthText);
const height = Number(heightText);
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null;
return width / height;
}
export function getGenerationNodeSizeForAspectRatio(
value: unknown
): { width: number; height: number } | null {
if (typeof value !== "string") return null;
return GENERATION_NODE_SIZE_BY_ASPECT_RATIO[value.trim()] ?? null;
const aspectRatio = parseAspectRatioValue(value);
return aspectRatio ? calculateMediaNodeSizeByShortSide(aspectRatio) : null;
}
// Node sizing constraints

Loading…
Cancel
Save