From 98af9b197712d9a4c85e2a283a0d96cf7431b1c5 Mon Sep 17 00:00:00 2001 From: Trang Doan Date: Mon, 11 May 2026 08:58:51 -0700 Subject: [PATCH 1/4] ENG-1693 Add insert backlink checkbox to ModifyNodeModal with smart defaults - Add "Insert backlink" checkbox to ModifyNodeModal (create mode only) - Default true when pre-filled text exists (user had text selected) or existing node is chosen; false otherwise - Gate backlink insertion in canvas flow and editor command flow on checkbox value Co-Authored-By: Claude Sonnet 4.6 --- .../src/components/ModifyNodeModal.tsx | 28 +++++++++++++++++-- .../canvas/utils/nodeCreationFlow.ts | 13 +++++---- apps/obsidian/src/utils/createNode.ts | 2 +- apps/obsidian/src/utils/registerCommands.ts | 8 ++++-- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/apps/obsidian/src/components/ModifyNodeModal.tsx b/apps/obsidian/src/components/ModifyNodeModal.tsx index 6c4107cb9..f14a42f8e 100644 --- a/apps/obsidian/src/components/ModifyNodeModal.tsx +++ b/apps/obsidian/src/components/ModifyNodeModal.tsx @@ -1,4 +1,4 @@ -import { App, Modal, Notice, TFile } from "obsidian"; +import { App, MarkdownView, Modal, Notice, TFile } from "obsidian"; import { createRoot, Root } from "react-dom/client"; import { StrictMode, @@ -49,6 +49,7 @@ type ModifyNodeFormProps = { /** DiscourseRelation.id; when set, relation is created with currentFile as the other end. */ relationshipId?: string; relationshipTargetFile?: TFile; + insertBacklink: boolean; }) => Promise; onCancel: () => void; initialTitle?: string; @@ -83,6 +84,9 @@ export const ModifyNodeForm = ({ const [selectedRelationshipKey, setSelectedRelationshipKey] = useState< string | undefined >(undefined); + const hasEditorContext = + plugin.app.workspace.activeLeaf?.view instanceof MarkdownView; + const [insertBacklink, setInsertBacklink] = useState(!!initialTitle); const queryEngine = useRef(new QueryEngine(plugin.app)); const titleInputRef = useRef(null); const popoverRef = useRef(null); @@ -278,6 +282,7 @@ export const ModifyNodeForm = ({ setSelectedExistingNode(file); setQuery(file.basename); setTitle(file.basename); + setInsertBacklink(true); // Auto-detect node type from the selected file's frontmatter const nodeTypeId = await getNodeTypeIdForFile(plugin, file); if (nodeTypeId && selectedFileRef.current === file) { @@ -291,12 +296,13 @@ export const ModifyNodeForm = ({ const handleClearSelection = useCallback(() => { selectedFileRef.current = null; setSelectedExistingNode(null); + setInsertBacklink(!!initialTitle); setQuery(""); setTitle(""); setTimeout(() => { titleInputRef.current?.focus(); }, 50); - }, []); + }, [initialTitle]); const handleKeyDown = (e: React.KeyboardEvent) => { if (selectedExistingNode) { @@ -391,6 +397,7 @@ export const ModifyNodeForm = ({ selectedExistingNode: selectedExistingNode || undefined, relationshipId: selectedRel?.uniqueKey || undefined, relationshipTargetFile: currentFile || undefined, + insertBacklink, }); onCancel(); } catch (error) { @@ -418,6 +425,7 @@ export const ModifyNodeForm = ({ selectedRelationshipKey, currentFile, availableRelationships, + insertBacklink, ]); return ( @@ -568,6 +576,20 @@ export const ModifyNodeForm = ({ )} + {!isEditMode && hasEditorContext && ( +
+
Insert backlink
+
+ setInsertBacklink(e.target.checked)} + disabled={isSubmitting} + /> +
+
+ )} +