Browse Source
Phase 10: Node Autosizing - 1 plan created - 2 tasks defined - Ready for executionhandoff-20260429-1057
1 changed files with 127 additions and 0 deletions
@ -0,0 +1,127 @@ |
|||||
|
--- |
||||
|
phase: 10-node-autosizing |
||||
|
plan: 01 |
||||
|
type: execute |
||||
|
--- |
||||
|
|
||||
|
<objective> |
||||
|
Auto-size generate nodes to match output image/video aspect ratio after generation completes. |
||||
|
|
||||
|
Purpose: Nodes should visually reflect their output dimensions, making the canvas layout more intuitive and allowing users to see aspect ratios at a glance. |
||||
|
Output: GenerateImageNode and GenerateVideoNode automatically resize to match output aspect ratio. |
||||
|
</objective> |
||||
|
|
||||
|
<execution_context> |
||||
|
~/.claude/get-shit-done/workflows/execute-phase.md |
||||
|
~/.claude/get-shit-done/templates/summary.md |
||||
|
</execution_context> |
||||
|
|
||||
|
<context> |
||||
|
@.planning/PROJECT.md |
||||
|
@.planning/ROADMAP.md |
||||
|
@.planning/STATE.md |
||||
|
|
||||
|
# Prior phase context |
||||
|
@.planning/phases/09-video-history/09-01-SUMMARY.md |
||||
|
|
||||
|
# Key source files |
||||
|
@src/store/workflowStore.ts |
||||
|
@src/components/nodes/BaseNode.tsx |
||||
|
@src/components/nodes/GenerateImageNode.tsx |
||||
|
@src/components/nodes/GenerateVideoNode.tsx |
||||
|
|
||||
|
**Relevant codebase patterns:** |
||||
|
- Node dimensions set via `node.style.width/height` in workflowStore.ts:469-494 |
||||
|
- `defaultDimensions` defines initial sizes per node type |
||||
|
- `useReactFlow().setNodes()` updates node styles from within components |
||||
|
- Generate nodes already use `setNodes` for parameter panel expansion (GenerateImageNode.tsx:244) |
||||
|
- Output images stored in `outputImage` (NanoBananaNodeData) and `outputVideo` (GenerateVideoNodeData) |
||||
|
|
||||
|
**Constraints from prior phases:** |
||||
|
- Phase 9 noted: "Carousel UI may need adjustment when node autosizing is implemented" |
||||
|
</context> |
||||
|
|
||||
|
<tasks> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 1: Create node dimension calculation utility</name> |
||||
|
<files>src/utils/nodeDimensions.ts</files> |
||||
|
<action> |
||||
|
Create a utility module with functions to: |
||||
|
|
||||
|
1. `getImageDimensions(base64DataUrl: string): Promise<{width: number, height: number}>` - Extract dimensions from base64 image by loading into Image element |
||||
|
2. `calculateNodeSize(aspectRatio: number, baseWidth: number = 300): {width: number, height: number}` - Calculate node dimensions that maintain aspect ratio with constraints: |
||||
|
- Minimum width: 200px |
||||
|
- Maximum width: 500px |
||||
|
- Minimum height: 200px |
||||
|
- Maximum height: 600px |
||||
|
- Base width defaults to 300px |
||||
|
|
||||
|
The utility should handle edge cases: |
||||
|
- Return null/default for invalid input |
||||
|
- Handle both portrait and landscape orientations |
||||
|
- Account for node chrome (header ~40px, controls ~60px) when calculating content area |
||||
|
|
||||
|
Export both functions for use in generate nodes. |
||||
|
</action> |
||||
|
<verify>File exists at src/utils/nodeDimensions.ts with both exported functions. TypeScript compiles without errors: `npm run build`</verify> |
||||
|
<done>Utility module exists with getImageDimensions and calculateNodeSize functions, build passes</done> |
||||
|
</task> |
||||
|
|
||||
|
<task type="auto"> |
||||
|
<name>Task 2: Auto-resize generate nodes on output</name> |
||||
|
<files>src/components/nodes/GenerateImageNode.tsx, src/components/nodes/GenerateVideoNode.tsx</files> |
||||
|
<action> |
||||
|
Update both generate node components to resize when output is set: |
||||
|
|
||||
|
**GenerateImageNode.tsx:** |
||||
|
1. Import the utility functions from nodeDimensions.ts |
||||
|
2. Add useEffect that triggers when `nodeData.outputImage` changes: |
||||
|
- If outputImage exists, call getImageDimensions() |
||||
|
- Calculate appropriate node size with calculateNodeSize() |
||||
|
- Use setNodes() to update the node's style.width and style.height |
||||
|
- Only resize if dimensions actually changed (avoid infinite loops) |
||||
|
|
||||
|
**GenerateVideoNode.tsx:** |
||||
|
1. Same pattern as GenerateImageNode |
||||
|
2. For videos, use a hidden video element to get dimensions: |
||||
|
- Create video element, set src to outputVideo |
||||
|
- On loadedmetadata event, read videoWidth and videoHeight |
||||
|
- Calculate and apply node size |
||||
|
|
||||
|
**Important considerations:** |
||||
|
- Don't resize while loading (only on complete output) |
||||
|
- Preserve user's manual resize if they've adjusted the node (track with a `userResized` flag in node data, or skip resize if current size differs significantly from default) |
||||
|
- Use requestAnimationFrame or setTimeout(0) to avoid React Flow update conflicts |
||||
|
</action> |
||||
|
<verify> |
||||
|
1. `npm run build` passes |
||||
|
2. Manual test: Generate an image with different aspect ratios (1:1, 16:9, 9:16) and verify node resizes appropriately |
||||
|
</verify> |
||||
|
<done> |
||||
|
- GenerateImageNode resizes to match output image aspect ratio |
||||
|
- GenerateVideoNode resizes to match output video aspect ratio |
||||
|
- Build passes without errors |
||||
|
</done> |
||||
|
</task> |
||||
|
|
||||
|
</tasks> |
||||
|
|
||||
|
<verification> |
||||
|
Before declaring plan complete: |
||||
|
- [ ] `npm run build` succeeds without errors |
||||
|
- [ ] No TypeScript errors in new/modified files |
||||
|
- [ ] Generate nodes resize when output is set |
||||
|
- [ ] Aspect ratio is maintained in node dimensions |
||||
|
</verification> |
||||
|
|
||||
|
<success_criteria> |
||||
|
- All tasks completed |
||||
|
- All verification checks pass |
||||
|
- No errors or warnings introduced |
||||
|
- Generate nodes auto-size to output aspect ratio |
||||
|
</success_criteria> |
||||
|
|
||||
|
<output> |
||||
|
After completion, create `.planning/phases/10-node-autosizing/10-01-SUMMARY.md` |
||||
|
</output> |
||||
Loading…
Reference in new issue