Files
2026-01-01 21:15:51 +01:00

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:

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 containedNodeIds is 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 label field 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

  1. Nested geometry - Frame inside frame (even if not supported, shouldn't crash)
  2. Circular attachments - A→B→C→A (should be prevented)
  3. Deleted references - Node deleted while in frame/attachment
  4. Empty states - Canvas with no nodes, frame with no nodes
  5. Extreme zoom - Labels at 0.1x and 1x zoom
  6. Large data - 100+ nodes, 20+ frames
  7. Undo stack - Complex sequence of operations then undo all
  8. Copy/paste - Frame with nodes, attached chain, labeled connections
  9. Project reload - All state persists correctly

User Workflows to Test

  1. Gradual adoption - Load old project, start using Smart Frames
  2. Organize existing - Take messy canvas, organize with frames
  3. Navigate complex - Jump between distant frames
  4. Document flow - Add labels to explain data path
  5. Refactor - Move nodes between frames
  6. 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)