Skip to content

Commit 73f4dd7

Browse files
trangdoan982claude
andauthored
[ENG-1547] Relation creation via drag handle (Obsidian) (#909)
* drag handle works * fix: reset isDragging on early returns and use e.currentTarget for hover Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * format and lint * format * address PR comment + fix z-position * some updates naming etc * address PR comments * dry as much as possible * further DRY and styling fixes * prettier * clean dead code --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2267d73 commit 73f4dd7

8 files changed

Lines changed: 852 additions & 149 deletions

File tree

apps/obsidian/src/components/canvas/DiscourseRelationTool.ts

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import { StateNode, TLEventHandlers, TLStateNodeConstructor } from "tldraw";
22
import { createShapeId } from "tldraw";
33
import type { TFile } from "obsidian";
44
import DiscourseGraphPlugin from "~/index";
5-
import { getRelationTypeById, isAcceptedSchema } from "~/utils/typeUtils";
5+
import { getNodeTypeById, getRelationTypeById } from "~/utils/typeUtils";
6+
import {
7+
getCompatibleTargetNodeTypeIds,
8+
getDiscourseNodeTypeId,
9+
} from "~/components/canvas/utils/relationTypeUtils";
610
import { DiscourseRelationShape } from "./shapes/DiscourseRelationShape";
7-
import { getNodeTypeById } from "~/utils/typeUtils";
811
import { showToast } from "./utils/toastUtils";
912
import { toTldrawColor } from "~/utils/tldrawColors";
1013

@@ -88,40 +91,6 @@ class Pointing extends StateNode {
8891
this.cancel();
8992
};
9093

91-
private getCompatibleNodeTypes = (
92-
plugin: DiscourseGraphPlugin,
93-
relationTypeId: string,
94-
sourceNodeTypeId: string,
95-
): string[] => {
96-
const compatibleTypes: string[] = [];
97-
98-
// Find all accepted discourse relations that match the relation type and source
99-
const relations = plugin.settings.discourseRelations.filter(
100-
(relation) =>
101-
isAcceptedSchema(relation) &&
102-
relation.relationshipTypeId === relationTypeId &&
103-
relation.sourceId === sourceNodeTypeId,
104-
);
105-
106-
relations.forEach((relation) => {
107-
compatibleTypes.push(relation.destinationId);
108-
});
109-
110-
// Also check reverse relations (where current node is destination)
111-
const reverseRelations = plugin.settings.discourseRelations.filter(
112-
(relation) =>
113-
isAcceptedSchema(relation) &&
114-
relation.relationshipTypeId === relationTypeId &&
115-
relation.destinationId === sourceNodeTypeId,
116-
);
117-
118-
reverseRelations.forEach((relation) => {
119-
compatibleTypes.push(relation.sourceId);
120-
});
121-
122-
return [...new Set(compatibleTypes)]; // Remove duplicates
123-
};
124-
12594
override onEnter = () => {
12695
this.didTimeout = false;
12796

@@ -143,20 +112,19 @@ class Pointing extends StateNode {
143112
return;
144113
}
145114

146-
const sourceNodeTypeId = (target as { props?: { nodeTypeId?: string } })
147-
.props?.nodeTypeId;
115+
const sourceNodeTypeId = getDiscourseNodeTypeId(target);
148116
if (!sourceNodeTypeId) {
149117
this.showWarning("Source node must have a valid node type");
150118
return;
151119
}
152120

153121
// Check if this source node type can create relations of this type
154122
if (sourceNodeTypeId) {
155-
const compatibleTargetTypes = this.getCompatibleNodeTypes(
156-
plugin,
123+
const compatibleTargetTypes = getCompatibleTargetNodeTypeIds({
124+
discourseRelations: plugin.settings.discourseRelations,
157125
relationTypeId,
158126
sourceNodeTypeId,
159-
);
127+
});
160128

161129
if (compatibleTargetTypes.length === 0) {
162130
const sourceNodeType = getNodeTypeById(plugin, sourceNodeTypeId);
@@ -168,11 +136,7 @@ class Pointing extends StateNode {
168136
}
169137
}
170138

171-
if (!target) {
172-
this.createArrowShape();
173-
} else {
174-
this.editor.setHintingShapes([target.id]);
175-
}
139+
this.editor.setHintingShapes([target.id]);
176140

177141
this.startPreciseTimeout();
178142
};

apps/obsidian/src/components/canvas/TldrawViewComponent.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
} from "~/components/canvas/shapes/DiscourseRelationBinding";
4747
import ToastListener from "./ToastListener";
4848
import { RelationsOverlay } from "./overlays/RelationOverlay";
49+
import { DragHandleOverlay } from "./overlays/DragHandleOverlay";
4950
import { WHITE_LOGO_SVG } from "~/icons";
5051
import { CustomContextMenu } from "./CustomContextMenu";
5152
import {
@@ -474,7 +475,10 @@ export const TldrawPreviewComponent = ({
474475
);
475476
},
476477
InFrontOfTheCanvas: () => (
477-
<RelationsOverlay plugin={plugin} file={file} />
478+
<>
479+
<RelationsOverlay plugin={plugin} file={file} />
480+
<DragHandleOverlay plugin={plugin} file={file} />
481+
</>
478482
),
479483
}}
480484
/>

0 commit comments

Comments
 (0)