7.2 KiB
TASK-000J Working Notes
Quick Reference
Key Files
Comment System:
├── models/commentsmodel.ts # Data model
├── views/CommentLayer/CommentLayerView.tsx # React rendering
├── views/CommentLayer/CommentForeground.tsx # Interactive layer
├── views/CommentLayer/CommentBackground.tsx # Background rendering
└── views/commentlayer.ts # Layer coordinator
Node Graph:
├── views/nodegrapheditor.ts # Main canvas controller
├── views/nodegrapheditor/NodeGraphEditorNode.ts # Node rendering
└── views/nodegrapheditor/NodeGraphEditorConnection.ts # Connection rendering
Editor:
├── views/documents/EditorDocument/EditorDocument.tsx # Main editor
└── utils/editorsettings.ts # Persistent settings
Useful Patterns in Codebase
Subscribing to model changes:
CommentsModel.on('commentsChanged', () => {
this._renderReact();
}, this);
Node graph coordinate transforms:
// Screen to canvas
const canvasPos = this.relativeCoordsToNodeGraphCords(screenPos);
// Canvas to screen
const screenPos = this.nodeGraphCordsToRelativeCoords(canvasPos);
Existing hit-testing:
// Check if point hits a node
forEachNode((node) => {
if (node.isHit(pos)) { ... }
});
// Check if point hits a connection
// See NodeGraphEditorConnection.isHit()
Implementation Notes
Phase 1: Smart Frames
Session 1.1 Notes
Add notes here during implementation
Things discovered:
Questions to resolve:
Code snippets to remember:
Session 1.2 Notes
Add notes here
Session 1.3 Notes
Add notes here
Session 1.4 Notes
Add notes here
Session 1.5 Notes
Add notes here
Session 1.6 Notes
Add notes here
Session 1.7 Notes
Add notes here
Session 1.8 Notes
Add notes here
Phase 2: Canvas Navigation
Session 2.1 Notes
Add notes here
Session 2.2 Notes
Add notes here
Session 2.3 Notes
Add notes here
Session 2.4 Notes
Add notes here
Session 2.5 Notes
Add notes here
Phase 3: Vertical Snap + Push
Session 3.1 Notes
Add notes here
Session 3.2 Notes
Add notes here
Session 3.3 Notes
Add notes here
Session 3.4 Notes
Add notes here
Session 3.5 Notes
Add notes here
Session 3.6 Notes
Add notes here
Session 3.7 Notes
Add notes here
Phase 4: Connection Labels
Session 4.1 Notes
Add notes here
Bezier math resources:
- https://pomax.github.io/bezierinfo/
- De Casteljau's algorithm for point on curve
- Newton-Raphson for nearest point
Session 4.2 Notes
Add notes here
Session 4.3 Notes
Add notes here
Session 4.4 Notes
Add notes here
Session 4.5 Notes
Add notes here
Session 4.6 Notes
Add notes here
Debugging Tips
Smart Frame Issues
Frame not detecting node:
- Check
isPointInFrame()bounds calculation - Log frame bounds vs node position
- Verify padding is accounted for
Nodes not moving with frame:
- Verify
containedNodeIdsis populated - Check if node IDs match
- Log delta calculation
Auto-resize not working:
- Check subscription to node changes
- Verify
calculateFrameBounds()returns correct values - Check minimum size constraints
Navigation Issues
Minimap not showing frames:
- Verify CommentsModel subscription
- Check filter for Smart Frames (containedNodeIds.length > 0)
- Log frame positions being rendered
Click navigation incorrect:
- Log coordinate transformation
- Verify minimap scale factor
- Check canvas bounds calculation
Attachment Issues
Attachment not creating:
- Log edge proximity values
- Verify threshold constant
- Check for existing attachments blocking
Push not working:
- Log size change subscription
- Verify attachment chain lookup
- Check for circular dependencies
Connection Label Issues
Label not rendering:
- Verify
labelfield on connection - Check bezier position calculation
- Log paint() being called
Label position wrong:
- Verify control points passed to bezier function
- Log t-value and resulting point
- Check canvas transform
Performance Considerations
Smart Frames
- Don't recalculate bounds on every frame during drag
- Throttle auto-resize updates
- Consider virtualizing nodes in very large frames
Minimap
- Don't re-render on every pan/zoom
- Use requestAnimationFrame for smooth updates
- Consider canvas rendering vs DOM for many frames
Attachments
- Cache attachment chains
- Invalidate cache only on attachment changes
- Avoid recalculating during animations
Labels
- Cache bezier calculations
- Don't hit-test labels that are off-screen
- Consider label culling at low zoom levels
Test Scenarios
Edge Cases to Test
- Nested geometry - Frame inside frame (even if not supported, shouldn't crash)
- Circular attachments - A→B→C→A (should be prevented)
- Deleted references - Node deleted while in frame/attachment
- Empty states - Canvas with no nodes, frame with no nodes
- Extreme zoom - Labels at 0.1x and 1x zoom
- Large data - 100+ nodes, 20+ frames
- Undo stack - Complex sequence of operations then undo all
- Copy/paste - Frame with nodes, attached chain, labeled connections
- Project reload - All state persists correctly
User Workflows to Test
- Gradual adoption - Load old project, start using Smart Frames
- Organize existing - Take messy canvas, organize with frames
- Navigate complex - Jump between distant frames
- Document flow - Add labels to explain data path
- Refactor - Move nodes between frames
- Expand/collapse - Work with collapsed frames
Helpful Snippets
Get all nodes in a bounding box
const nodesInBounds = [];
this.forEachNode((node) => {
const nodeBounds = {
x: node.global.x,
y: node.global.y,
width: node.nodeSize.width,
height: node.nodeSize.height
};
if (boundsOverlap(nodeBounds, targetBounds)) {
nodesInBounds.push(node);
}
});
Calculate point on cubic bezier
function getPointOnCubicBezier(t, p0, p1, p2, p3) {
const mt = 1 - t;
const mt2 = mt * mt;
const mt3 = mt2 * mt;
const t2 = t * t;
const t3 = t2 * t;
return {
x: mt3 * p0.x + 3 * mt2 * t * p1.x + 3 * mt * t2 * p2.x + t3 * p3.x,
y: mt3 * p0.y + 3 * mt2 * t * p1.y + 3 * mt * t2 * p2.y + t3 * p3.y
};
}
Render guide line
ctx.save();
ctx.strokeStyle = '#3b82f6';
ctx.lineWidth = 1;
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.moveTo(0, guideY);
ctx.lineTo(canvasWidth, guideY);
ctx.stroke();
ctx.restore();
Questions for Review
Add questions to ask during code review
Future Improvements
Ideas for follow-up work (out of scope for this task)
- Frame templates (pre-populated with common node patterns)
- Smart routing for connections (avoid crossing frames)
- Frame-level undo (undo all changes within a frame)
- Export frame as component (auto-componentize)
- Frame documentation export (generate docs from labels)
- Collaborative frame locking (multi-user editing)