Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions apps/roam/src/components/Export.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,7 @@ const ExportDialog: ExportDialogComponent = ({

// UTILS
const discourseNodeUtils = [DiscourseNodeUtil];
const discourseRelationUtils =
createAllRelationShapeUtils(allRelationIds);
const discourseRelationUtils = createAllRelationShapeUtils();
const referencedNodeUtils = createAllReferencedNodeUtils(
allAddReferencedNodeByAction,
);
Expand All @@ -415,7 +414,7 @@ const ExportDialog: ExportDialogComponent = ({
...referencedNodeUtils,
];
// BINDINGS
const relationBindings = createAllRelationBindings(allRelationIds);
const relationBindings = createAllRelationBindings();
const referencedNodeBindings = createAllReferencedNodeBindings(
allAddReferencedNodeByAction,
);
Expand Down
89 changes: 64 additions & 25 deletions apps/roam/src/components/canvas/DiscourseNodeUtil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ import getDiscourseContextResults from "~/utils/getDiscourseContextResults";
import calcCanvasNodeSizeAndImg from "~/utils/calcCanvasNodeSizeAndImg";
import { createTextJsxFromSpans } from "./DiscourseRelationShape/helpers";
import { loadImage } from "~/utils/loadImage";
import { getRelationColor } from "./DiscourseRelationShape/DiscourseRelationUtil";
import {
DISCOURSE_RELATION_SHAPE_TYPE,
getDiscourseRelationTypeId,
getRelationColor,
isDiscourseRelationShape,
} from "./DiscourseRelationShape/DiscourseRelationUtil";
import { getPersonalSetting } from "~/components/settings/utils/accessors";
import { PERSONAL_KEYS } from "~/components/settings/utils/settingKeys";
import DiscourseContextOverlay from "~/components/DiscourseContextOverlay";
Expand Down Expand Up @@ -217,7 +222,11 @@ export class DiscourseNodeUtil extends BaseBoxShapeUtil<DiscourseNodeShape> {
relationIds?: Set<string>;
}) {
const editor = this.editor;
const bindingsToThisShape = Array.from(relationIds).flatMap((r) =>
const relationBindingTypes = new Set([
DISCOURSE_RELATION_SHAPE_TYPE,
...relationIds,
]);
const bindingsToThisShape = Array.from(relationBindingTypes).flatMap((r) =>
editor.getBindingsToShape(shape.id, r),
);
const relationIdsAndType = bindingsToThisShape.map((b) => {
Expand Down Expand Up @@ -269,24 +278,40 @@ export class DiscourseNodeUtil extends BaseBoxShapeUtil<DiscourseNodeShape> {
)
.filter((id) => id !== undefined),
);
const currentShapeRelations = Array.from(
discourseContextRelationIds,
).flatMap((relationId) => {
const bindingsToThisShape = editor.getBindingsToShape(
shape.id,
relationId,
);
return bindingsToThisShape.map((b) => {
const arrowId = b.fromId;
const bindingsFromArrow = editor.getBindingsFromShape(
arrowId,
relationId,
const relationBindingTypes = new Set([
DISCOURSE_RELATION_SHAPE_TYPE,
...discourseContextRelationIds,
]);
const currentShapeRelations = Array.from(relationBindingTypes).flatMap(
Comment thread
mdroidian marked this conversation as resolved.
(bindingType) => {
const bindingsToThisShape = editor.getBindingsToShape(
shape.id,
bindingType,
);
const endBinding = bindingsFromArrow.find((b) => b.toId !== shape.id);
if (!endBinding) return null;
return { startId: shape.id, endId: endBinding.toId };
});
});
return bindingsToThisShape.flatMap((bindingToThisShape) => {
const arrowId = bindingToThisShape.fromId;
const arrow = editor.getShape(arrowId);
if (!arrow || !isDiscourseRelationShape(arrow)) return [];

const bindingsFromArrow = editor.getBindingsFromShape(
arrowId,
bindingType,
);
const endBinding = bindingsFromArrow.find(
(bindingFromArrow) => bindingFromArrow.toId !== shape.id,
);
if (!endBinding) return [];

return [
{
startId: shape.id,
endId: endBinding.toId,
relationTypeId: getDiscourseRelationTypeId({ shape: arrow }),
},
];
});
},
);

const toCreate = discourseContextResults
.flatMap((r) =>
Expand All @@ -301,13 +326,15 @@ export class DiscourseNodeUtil extends BaseBoxShapeUtil<DiscourseNodeShape> {
};
}),
)
.filter(({ complement, nodeId }) => {
.filter(({ relationId, complement, nodeId }) => {
const startId = complement ? nodesInCanvas[nodeId].id : shape.id;
const endId = complement ? shape.id : nodesInCanvas[nodeId].id;
const relationAlreadyExists = currentShapeRelations.some((r) => {
if (r.relationTypeId !== relationId) return false;

return complement
? r?.startId === endId && r?.endId === startId
: r?.startId === startId && r?.endId === endId;
? r.startId === endId && r.endId === startId
: r.startId === startId && r.endId === endId;
});
return !relationAlreadyExists;
})
Expand All @@ -319,13 +346,25 @@ export class DiscourseNodeUtil extends BaseBoxShapeUtil<DiscourseNodeShape> {
const shapesToCreate = toCreate.map(
({ relationId, arrowId, label }, index) => {
const color = getRelationColor(label, index);
return { id: arrowId, type: relationId, props: { color } };
return {
id: arrowId,
type: DISCOURSE_RELATION_SHAPE_TYPE,
props: {
color,
labelColor: color,
text: label,
relationTypeId: relationId,
},
};
},
);

const bindingsToCreate = toCreate.flatMap(
({ relationId, complement, nodeId, arrowId }) => {
const staticRelationProps = { type: relationId, fromId: arrowId };
({ complement, nodeId, arrowId }) => {
const staticRelationProps = {
type: DISCOURSE_RELATION_SHAPE_TYPE,
fromId: arrowId,
};
return [
{
...staticRelationProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,12 @@ export const createAllReferencedNodeBindings = (
};
});
};
export const createAllRelationBindings = (relationIds: string[]) => {
const relationBindings = relationIds.map((id) => {
return class RelationBindingUtil extends BaseRelationBindingUtil {
static override type = id;
};
});

class DiscourseRelationFallbackBindingUtil extends BaseRelationBindingUtil {
static override type = DISCOURSE_RELATION_SHAPE_TYPE;
}

return [...relationBindings, DiscourseRelationFallbackBindingUtil];
export const createAllRelationBindings = () => {
return [
class RelationBindingUtil extends BaseRelationBindingUtil {
static override type = DISCOURSE_RELATION_SHAPE_TYPE;
},
];
};

export type RelationBindings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
TLStateNodeConstructor,
} from "tldraw";
import {
DISCOURSE_RELATION_SHAPE_TYPE,
DiscourseRelationShape,
getRelationColor,
} from "./DiscourseRelationUtil";
Expand Down Expand Up @@ -483,11 +484,14 @@ export const createAllRelationShapeTools = (

this.editor.createShape<DiscourseRelationShape>({
id,
type: this.shapeType,
type: DISCOURSE_RELATION_SHAPE_TYPE,
x: originPagePoint.x,
y: originPagePoint.y,
props: {
color,
labelColor: color,
text: name,
relationTypeId: this.shapeType,
scale: this.editor.user.getIsDynamicResizeMode()
? 1 / this.editor.getZoomLevel()
: 1,
Expand All @@ -501,7 +505,7 @@ export const createAllRelationShapeTools = (
if (!handles) throw Error(`expected handles for arrow`);

const util = this.editor.getShapeUtil<DiscourseRelationShape>(
this.shapeType,
DISCOURSE_RELATION_SHAPE_TYPE,
);
const initial = this.shape;
const startHandle = handles.find((h) => h.id === "start")!;
Expand Down Expand Up @@ -536,7 +540,7 @@ export const createAllRelationShapeTools = (

{
const util = this.editor.getShapeUtil<DiscourseRelationShape>(
this.shapeType,
DISCOURSE_RELATION_SHAPE_TYPE,
);
const initial = this.shape;
const startHandle = handles.find((h) => h.id === "start")!;
Expand All @@ -554,7 +558,7 @@ export const createAllRelationShapeTools = (
// end update
{
const util = this.editor.getShapeUtil<DiscourseRelationShape>(
this.shapeType,
DISCOURSE_RELATION_SHAPE_TYPE,
);
const initial = this.shape;
const point = this.editor.getPointInShapeSpace(
Expand Down
Loading