diff --git a/package-lock.json b/package-lock.json index 5b725e1..cb24ca7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@tsconfig/strictest": "^2.0.5", "@types/node": "^22.13.10", "moment": "^2.30.1", + "monkey-around": "^3.0.0", "obsidian": "^1.8.7", "obsidian-dev-utils": "^19.8.2", "obsidian-typings": "^2.35.0", diff --git a/package.json b/package.json index edbc467..e9d5ac4 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@tsconfig/strictest": "^2.0.5", "@types/node": "^22.13.10", "moment": "^2.30.1", + "monkey-around": "^3.0.0", "obsidian": "^1.8.7", "obsidian-dev-utils": "^19.8.2", "obsidian-typings": "^2.35.0", diff --git a/src/BacklinkFullPathPlugin.ts b/src/BacklinkFullPathPlugin.ts index b3044c6..89d42a7 100644 --- a/src/BacklinkFullPathPlugin.ts +++ b/src/BacklinkFullPathPlugin.ts @@ -1,8 +1,28 @@ -import { PluginBase } from 'obsidian-dev-utils/obsidian/Plugin/PluginBase'; -import { EmptySettings } from 'obsidian-dev-utils/obsidian/Plugin/EmptySettings'; -import type { PluginSettingTab } from 'obsidian'; +import type { + PluginSettingTab, + TFile +} from 'obsidian'; +import type { + BacklinkPlugin, + BacklinkView, + ResultDom, + ResultDomResult, + TreeDom +} from 'obsidian-typings'; -export class BacklinkFullPathPlugin extends PluginBase { +import { around } from 'monkey-around'; +import { invokeAsyncSafely } from 'obsidian-dev-utils/Async'; +import { getPrototypeOf } from 'obsidian-dev-utils/Object'; +import { EmptySettings } from 'obsidian-dev-utils/obsidian/Plugin/EmptySettings'; +import { PluginBase } from 'obsidian-dev-utils/obsidian/Plugin/PluginBase'; +import { + InternalPluginName, + ViewType +} from 'obsidian-typings/implementations'; + +type AddResultFn = (file: TFile, result: ResultDomResult, content: string, shouldShowTitle?: boolean) => ResultDom; + +export class BacklinkFullPathPlugin extends PluginBase { protected override createPluginSettings(): EmptySettings { return new EmptySettings(); } @@ -11,7 +31,67 @@ export class BacklinkFullPathPlugin extends PluginBase { return null; } - protected override async onLayoutReady(): Promise { + protected override onLayoutReady(): void { + const backlinksCorePlugin = this.app.internalPlugins.getPluginById(InternalPluginName.Backlink); + if (!backlinksCorePlugin) { + return; + } + // eslint-disable-next-line consistent-this,@typescript-eslint/no-this-alias + const plugin = this; + this.register(around(getPrototypeOf(backlinksCorePlugin.instance), { + onUserEnable: (next: () => void) => + function onUserEnablePatched(this: BacklinkPlugin): void { + next.call(this); + plugin.onBacklinksCorePluginEnable(); + } + })); + + if (backlinksCorePlugin.enabled) { + plugin.onBacklinksCorePluginEnable(); + } + } + + private addResult(next: AddResultFn, treeDom: TreeDom, file: TFile, result: ResultDomResult, content: string, shouldShowTitle?: boolean): ResultDom { + const basename = file.basename; + const name = file.name; + try { + file.basename = file.path; + file.name = file.path; + return next.call(treeDom, file, result, content, shouldShowTitle); + } finally { + file.basename = basename; + file.name = name; + } + } + + private async getBacklinkView(): Promise { + const backlinksLeaf = this.app.workspace.getLeavesOfType(ViewType.Backlink)[0]; + if (!backlinksLeaf) { + return null; + } + + await backlinksLeaf.loadIfDeferred(); + return backlinksLeaf.view as BacklinkView; + } + + private onBacklinksCorePluginEnable(): void { + invokeAsyncSafely(() => this.patchBacklinksPane()); + } + + private async patchBacklinksPane(): Promise { + const backlinkView = await this.getBacklinkView(); + if (!backlinkView) { + return; + } + + // eslint-disable-next-line consistent-this,@typescript-eslint/no-this-alias + const plugin = this; + this.register(around(getPrototypeOf(backlinkView.backlink.backlinkDom), { + addResult: (next: AddResultFn): AddResultFn => + function addResultPatched(this: TreeDom, file, result, content, shouldShowTitle?) { + return plugin.addResult(next, this, file, result, content, shouldShowTitle); + } + })); } }