Skip to content

Conversation

@trangdoan982
Copy link
Collaborator

@trangdoan982 trangdoan982 commented Sep 2, 2025

Summary by CodeRabbit

  • New Features
    • Added relation arrows on Canvas to connect nodes, supporting straight and curved paths with adjustable bend and handles.
    • Arrow bindings automatically follow, update, and clean up when connected shapes move or are deleted.
    • Improved arrow labeling with smart placement, font sizing, and styling.
    • Multiple arrowhead styles available (e.g., dot, cross, triangle, diamond).
    • Enhanced export quality with embedded fonts and pattern fills for SVG/canvas exports.
    • Relation arrows are now available in the drawing UI alongside existing shapes.

@linear
Copy link

linear bot commented Sep 2, 2025

@supabase
Copy link

supabase bot commented Sep 2, 2025

This pull request has been ignored for the connected project zytfjzqyijgagqxrzbmz because there are no changes detected in packages/database/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

Copy link
Collaborator Author

trangdoan982 commented Sep 2, 2025

@trangdoan982 trangdoan982 marked this pull request as ready for review September 2, 2025 16:13
@trangdoan982
Copy link
Collaborator Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 2, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 2, 2025

Caution

Review failed

An error occurred during the review process. Please try again later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (20)
apps/obsidian/src/components/canvas/shapes/DiscourseRelationShape.tsx (4)

133-159: Handle missing arrow info defensively.

Non-null assertion on getArrowInfo can crash; provide a fallback to raw start/end handles.

Apply this diff:

-  const info = getArrowInfo(this.editor, shape)!;
-
-  return [
+  const info = getArrowInfo(this.editor, shape);
+  if (!info) {
+    const { start, end } = shape.props;
+    return [
+      { id: ARROW_HANDLES.START, type: "vertex", index: "a0", x: start.x, y: start.y },
+      { id: ARROW_HANDLES.MIDDLE, type: "virtual", index: "a2", x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 },
+      { id: ARROW_HANDLES.END, type: "vertex", index: "a3", x: end.x, y: end.y },
+    ] as TLHandle[];
+  }
+  return [
     {
       id: ARROW_HANDLES.START,
       type: "vertex",
       index: "a0",
       x: info.start.handle.x,
       y: info.start.handle.y,
     },

289-328: Prefer instance method over prototype call for defaults.

Use this.getDefaultProps() to respect overrides and avoid unusual prototype access.

Apply this diff:

-      props: {
-        ...DiscourseRelationUtil.prototype.getDefaultProps(),
+      props: {
+        ...this.getDefaultProps(),
         relationTypeId,
         text: relationLabel,
         start: startPoint,
         end: endPoint,
       },

184-202: Curve control point could bend in the wrong axis.

Using midPoint.x + bend shifts only horizontally. For more natural bending, project along the normal of the start→end segment.

I can provide a small helper to compute a perpendicular control point if you want to refine the arc later.


242-254: Indicator should mirror curved geometry for accurate hit testing.

Straight-line indicator on a bent arrow underestimates the selectable area.

Consider using the same path “d” with stroke="transparent" and thicker strokeWidth.

apps/obsidian/src/components/canvas/shapes/DiscourseRelationBinding.tsx (2)

121-123: Remove stray console log.

Leftover debug logging in a hot path; please drop it.

-    console.log("deleted arrow");
-    // this.editor.deleteShape(arrow.id); // we don't want to keep the arrow
+    // this.editor.deleteShape(arrow.id); // we don't want to keep the arrow

131-138: Confirm deletion semantics on bound-shape removal.

Currently deletes the arrow when its bound shape is deleted. Is the desired UX “auto-unbind” instead? If deletion is correct, consider gating behind a user setting.

-  if (arrow) this.editor.deleteShape(arrow.id);
+  if (!arrow) return;
+  // Option A: unbind to keep the arrow
+  // removeArrowBinding(this.editor, arrow, binding.props.terminal);
+  // Option B: keep current behavior (delete)
+  this.editor.deleteShape(arrow.id);
apps/obsidian/src/components/canvas/utils/relationUtils.tsx (14)

851-859: Remove duplicate guard.

The second identical guard is dead code; drop it.

-  if (!intersectionPoints || intersectionPoints.length !== 2) {
-    return { start: 0.5, end: 0.5 };
-  }
-
-  // there should be two intersection points - one near the start, and one near the end
-  // after the existing guard:
-  if (!intersectionPoints || intersectionPoints.length !== 2)
-    return { start: 0.5, end: 0.5 };
+  if (!intersectionPoints || intersectionPoints.length !== 2) {
+    return { start: 0.5, end: 0.5 };
+  }

1125-1141: Export key namespace: use a distinct key for fill defs.

getFillDefForExport uses DefaultFontStyle.id in the key. Use a fill-specific prefix to avoid collisions with font defs.

-    key: `${DefaultFontStyle.id}:${fill}`,
+    key: `tldraw:fill:${fill}`,

2056-2087: Consolidate identical fill cases.

"solid", "semi", and "fill" all render the same. Consider collapsing to reduce branches.

-    case "solid": {
-      return <path fill={color} d={d} />;
-    }
-    case "semi": {
-      return <path fill={color} d={d} />;
-    }
-    case "fill": {
-      return <path fill={color} d={d} />;
-    }
+    case "solid":
+    case "semi":
+    case "fill":
+      return <path fill={color} d={d} />;

1700-1713: Consider relocating shared types to break mutual imports.

Both files import each other. Moving RelationBinding(s)/RelationInfo to a separate types module would eliminate the cycle and allow deduping utilities like updateArrowTerminal.


1955-2005: Mask id stability on Safari workaround: verify for collisions.

maskId uses shape.id + changeIndex; ensure it stays unique across pages and sessions. Consider prefixing with a namespace.

-  const maskId = (shape.id + "_clip_" + changeIndex).replace(":", "_");
+  const maskId = (`dg_rel_clip_${shape.id}_${changeIndex}`).replace(":", "_");

1602-1608: Dead code: isLegacyAlign unused.

Remove if unused to keep the module lean.

-function isLegacyAlign(align: TLDefaultHorizontalAlignStyle | string): boolean {
-  return (
-    align === "start-legacy" ||
-    align === "middle-legacy" ||
-    align === "end-legacy"
-  );
-}
+// (remove if not needed)

1422-1436: Revoke data URLs for default pixels on teardown.

getDefaultPixels creates long-lived data URLs. If re-initialized often (e.g., HMR/tests), consider a teardown path to avoid leaks.


1570-1593: Marker ids should be namespaced.

Plain ids like arrowhead-dot/arrowhead-cross can collide if multiple canvases exist. Namespace with a stable prefix.

-      id="arrowhead-dot"
+      id="dg-arrowhead-dot"
...
-      id="arrowhead-cross"
+      id="dg-arrowhead-cross"

1641-1650: Binding cleanup robustness.

When deleting existing bindings, ensure you don't pass an empty array or already-deleted ids; defensive guard avoids multi-player races.

-  editor.deleteBindings(existing);
+  if (existing.length) editor.deleteBindings(existing);

1673-1699: Idempotent create-or-update binding.

Between read/update, the binding may change in multiplayer. Wrap in a small retry or re-read before updateBinding.


1256-1267: Line-break detection in SVG spans may break with fractional y.

Comparing box.y > currentLineTop without epsilon can mis-detect lines at high zoom. Consider epsilon threshold.

-    const didBreakLine = currentLineTop !== null && box.y > currentLineTop;
+    const didBreakLine =
+      currentLineTop !== null && box.y - currentLineTop > 0.5;

1841-1864: approximately duplicates tldraw util name.

This local export shadows the approximately you import/use elsewhere. Consider renaming to avoid confusion.


1501-1537: Pattern image object URLs: ensure cleanup on each render cycle.

Cleanup already revokes on unmount; also revoke and replace when DPR/zoom changes to prevent leaks during long sessions.


1715-1724: mapObjectMapValues: potential perf nit.

Micro: can use for..in to avoid interim arrays from Object.entries for large objects. Not critical.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e587380 and 3b90e93.

⛔ Files ignored due to path filters (1)
  • apps/obsidian/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • apps/obsidian/src/components/canvas/TldrawViewComponent.tsx (2 hunks)
  • apps/obsidian/src/components/canvas/shapes/DiscourseRelationBinding.tsx (1 hunks)
  • apps/obsidian/src/components/canvas/shapes/DiscourseRelationShape.tsx (1 hunks)
  • apps/obsidian/src/components/canvas/utils/relationUtils.tsx (1 hunks)
  • apps/obsidian/src/components/canvas/utils/tldraw.ts (2 hunks)
  • apps/obsidian/src/utils/generateUid.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI
apps/obsidian/src/utils/generateUid.ts

[error] 1-1: TypeScript error TS2595: 'nanoid' can only be imported by using a default import. (Command: tsc --noEmit --skipLibCheck)

🪛 Biome (2.1.2)
apps/obsidian/src/components/canvas/utils/relationUtils.tsx

[error] 1785-1785: This code will never be reached ...

... because this statement will throw an exception beforehand

(lint/correctness/noUnreachable)


[error] 555-555: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🔇 Additional comments (3)
apps/obsidian/src/components/canvas/utils/tldraw.ts (1)

23-23: Registering DiscourseRelationUtil during store init looks correct.

Order (Node before Relation) is sensible for binding dependencies. No issues.

Also applies to: 50-51

apps/obsidian/src/components/canvas/TldrawViewComponent.tsx (1)

35-35: Good: DiscourseRelationUtil configured in the editor’s shape utils.

Mirrors processInitialData registration; consistent integration.

Also applies to: 63-67

apps/obsidian/src/components/canvas/utils/relationUtils.tsx (1)

588-590: Log-scale pattern LOD: confirm perceptual step.

Math.ceil(log2(max(1, zoom))) can jump aggressively at low zooms; verify intended for Obsidian canvases.

@trangdoan982 trangdoan982 force-pushed the 09-02-eng-600_discourse_relation_shape_definition branch from 3b90e93 to 65b4a9c Compare September 4, 2025 04:39
@trangdoan982 trangdoan982 force-pushed the 09-02-eng-600_discourse_relation_shape_definition branch 3 times, most recently from f8fec7f to 2117973 Compare September 6, 2025 02:56
Copy link
Contributor

@mdroidian mdroidian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For code that we copy/pasted from tldraw, we should make a note of that and link to it. Looks like I missed this for roam (I'll go back and add it).

Biggest blockers are the migrations and the package-lock.json doesn't seem right.

@@ -0,0 +1,2654 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.tsx if you are returning react jsx. Just .ts for helper utils.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lots of functions in this utils return react jsx components (eg: ArrowheadCrossDef), so i needed to switch it to tsx

@@ -0,0 +1,2654 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unused-vars */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to assume all of this is copy/pasted from tldraw arrows (with minor edits for our relation arrows)? If not, let me know. If so, let's make a note of that and link directly to it where possible.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it was all copied and slightly modified to fit our shape. I will make a comment

@trangdoan982 trangdoan982 force-pushed the 09-02-eng-600_discourse_relation_shape_definition branch from 2117973 to 382d101 Compare September 8, 2025 14:43
Copy link
Contributor

@mdroidian mdroidian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

@trangdoan982 trangdoan982 merged commit a7eba8e into tldraw-obsidian Sep 17, 2025
5 checks passed
@github-project-automation github-project-automation bot moved this to Done in General Sep 17, 2025
@trangdoan982 trangdoan982 deleted the 09-02-eng-600_discourse_relation_shape_definition branch September 17, 2025 14:27
trangdoan982 added a commit that referenced this pull request Oct 16, 2025
* [ENG-495] Tldraw obsidian setup (#285)

* cleaned

* sm

* address PR comments

* [ENG-598] Data persistence for tldraw (#303)

* data persistence to the file

* error handling

* address PR comments

* address some PR comments

* address other PR comments

* address PR comments

* [ENG-624] TLDraw Obsidian asset store (#326)

* current state

* works now

* clean up

* address PR comments

* address PR reviews

* cleanup

* fix styling issues

* address PR comments

* correct styles

* [ENG-599] Discourse node shape (#341)

* current state

* works now

* clean up

* address PR comments

* address PR reviews

* fix styling issues

* latest progress

* update new shape

* shape defined

* address PR comments

* sm address PR review

* current progress

* reorg

* address other PR comments

* clean

* simplify flow

* address PR comments

* [ENG-604] Create node flow (#387)

* eng-604: create node flow

* pwd

* [ENG-658] Add existing node flow (#389)

* eng-658-add-existing-nodes-flow

* address PR comments

* small changes

* [ENG-601] Create settings for canvas and attachment default folder (#338)

* add new settings

* small add

* ENG-600: Discourse Relation shape definition (#408)

* ENG-605: Add new relation flow (#411)

* [ENG-603] Add existing relations (#412)

https://www.loom.com/share/3641f2a642714b0d849262344e8c6ee5?sid=0614c657-e541-4bfd-92df-9b1aa60945b6

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- New Features
  - Added a Relations overlay on the canvas that shows a “Relations” button when a discourse node is selected.
  - Introduced a Relations panel to view and manage relations for the selected node, including adding or removing links, with clear loading/error states.
  - Overlay appears above the canvas without disrupting existing tools.

- Chores
  - Consolidated relation-type lookup into shared utilities and updated imports. No user-facing changes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

* [ENG-844] Add color setting for relation types (#429)

* add color setting

* address PR reviews

* address PR commens

* fix icons

* ENG-812 Update of database cli tools (#401)

* eng-812 : Update database cli tools: supabase, vercel, cucumber.

* newer cucumber constrains node

* [ENG-495] Tldraw obsidian setup (#285)

* cleaned

* sm

* address PR comments

* [ENG-598] Data persistence for tldraw (#303)

* data persistence to the file

* error handling

* address PR comments

* address some PR comments

* address other PR comments

* address PR comments

* switch to pnpm

* delete wrong rebase file

* fix pnpm lock

* fix type checks

* address all the PR comments

* delete redundant files

* fix types

* shift click to open file on the right split (#485)

* address PR comments

* final lint cleanup

---------

Co-authored-by: Marc-Antoine Parent <maparent@acm.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants