1- import { TFile , Notice } from "obsidian" ;
1+ import { TFile , Notice , FrontMatterCache } from "obsidian" ;
22import { useState , useRef , useEffect , useCallback , useMemo } from "react" ;
33import { QueryEngine } from "~/services/QueryEngine" ;
44import SearchBar from "./SearchBar" ;
@@ -356,7 +356,7 @@ const CurrentRelationships = ({ activeFile }: RelationshipSectionProps) => {
356356 } ;
357357 } , [ activeFile , plugin ] ) ;
358358
359- const loadCurrentRelationships = async ( ) => {
359+ const loadCurrentRelationships = useCallback ( async ( ) => {
360360 const fileCache = plugin . app . metadataCache . getFileCache ( activeFile ) ;
361361 if ( ! fileCache ?. frontmatter ) return ;
362362
@@ -423,7 +423,75 @@ const CurrentRelationships = ({ activeFile }: RelationshipSectionProps) => {
423423 }
424424
425425 setGroupedRelationships ( Array . from ( tempRelationships . values ( ) ) ) ;
426- } ;
426+ } , [ activeFile , plugin ] ) ;
427+
428+ const deleteRelationship = useCallback (
429+ async ( linkedFile : TFile , relationTypeId : string ) => {
430+ const relationType = plugin . settings . relationTypes . find (
431+ ( r ) => r . id === relationTypeId ,
432+ ) ;
433+ if ( ! relationType ) return ;
434+
435+ try {
436+ const removeLinkFromFrontmatter = async (
437+ file : TFile ,
438+ targetFileName : string ,
439+ relationTypeId : string ,
440+ ) => {
441+ await plugin . app . fileManager . processFrontMatter (
442+ file ,
443+ ( fm : FrontMatterCache ) => {
444+ const existingLinks = Array . isArray ( fm [ relationTypeId ] )
445+ ? fm [ relationTypeId ]
446+ : [ fm [ relationTypeId ] ] . filter ( Boolean ) ;
447+
448+ const linkToRemove = `[[${ targetFileName } ]]` ;
449+ const filteredLinks = existingLinks . filter (
450+ ( link ) => link !== linkToRemove ,
451+ ) ;
452+
453+ if ( filteredLinks . length === 0 ) {
454+ delete fm [ relationTypeId ] ;
455+ } else {
456+ fm [ relationTypeId ] = filteredLinks ;
457+ }
458+ } ,
459+ ) ;
460+ } ;
461+
462+ // Remove link from active file
463+ await removeLinkFromFrontmatter (
464+ activeFile ,
465+ linkedFile . name ,
466+ relationTypeId ,
467+ ) ;
468+
469+ // Remove reverse link from linked file
470+ await removeLinkFromFrontmatter (
471+ linkedFile ,
472+ activeFile . name ,
473+ relationTypeId ,
474+ ) ;
475+
476+ new Notice (
477+ `Successfully removed ${ relationType . label } with ${ linkedFile . basename } ` ,
478+ ) ;
479+
480+ loadCurrentRelationships ( ) ;
481+ } catch ( error ) {
482+ console . error ( "Failed to delete relationship:" , error ) ;
483+ new Notice (
484+ `Failed to delete relationship: ${ error instanceof Error ? error . message : "Unknown error" } ` ,
485+ ) ;
486+ }
487+ } ,
488+ [
489+ activeFile ,
490+ plugin . app . fileManager ,
491+ plugin . settings . relationTypes ,
492+ loadCurrentRelationships ,
493+ ] ,
494+ ) ;
427495
428496 if ( groupedRelationships . length === 0 ) return null ;
429497
@@ -445,20 +513,33 @@ const CurrentRelationships = ({ activeFile }: RelationshipSectionProps) => {
445513
446514 < ul className = "m-0 ml-6 list-none p-0" >
447515 { group . linkedFiles . map ( ( file ) => (
448- < li key = { file . path } className = "mt-1" >
516+ < li key = { file . path } className = "mt-1 flex items-center gap-2 " >
449517 < a
450518 href = "#"
451- className = "text-accent-text"
519+ className = "text-accent-text flex-1 "
452520 onClick = { ( e ) => {
453521 e . preventDefault ( ) ;
454- plugin . app . workspace . openLinkText (
522+ void plugin . app . workspace . openLinkText (
455523 file . path ,
456524 activeFile . path ,
457525 ) ;
458526 } }
459527 >
460528 { file . basename }
461529 </ a >
530+ < button
531+ className = "!text-muted hover:!text-error flex h-6 w-6 cursor-pointer items-center justify-center border-0 !bg-transparent text-sm"
532+ onClick = { ( e ) => {
533+ e . preventDefault ( ) ;
534+ void deleteRelationship (
535+ file ,
536+ group . relationTypeOptions . id ,
537+ ) ;
538+ } }
539+ title = "Delete relationship"
540+ >
541+ ×
542+ </ button >
462543 </ li >
463544 ) ) }
464545 </ ul >
0 commit comments