Merge pull request #25 from IdanLib/code-review-2b

Code review 2b
This commit is contained in:
Idan Liberman 2025-08-03 01:19:06 +03:00 committed by GitHub
commit d65390304b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 142 additions and 119 deletions

View file

@ -23,6 +23,16 @@ Here are some examples of how you might set up FastForwardLink:
![demo](./plugin_demo.gif)
## Version Updates
### Version 1.1
Some improvements include:
- You can now temporarily by pass forwarding with a designated command!
- Source code refactored and better organized for future conributors.
- Better robust event and error handling and messaging.
## Features
- **Multiple Links, One Target**: Set multiple links to redirect to a single target note for quick navigation between related topics or abbreviations. Organize synonyms or alternate spellings for easier access.

242
main.ts
View file

@ -1,6 +1,7 @@
import { getLinkpath, Plugin, Notice, TFolder, TFile } from "obsidian";
import RedirectSettingsTab from "components/Settings";
// --- Setup ---
interface RedirectSettings {
openInNewTab: boolean;
switchToNewTab: boolean;
@ -11,70 +12,163 @@ const DEFAULT_SETTINGS: RedirectSettings = {
switchToNewTab: false,
};
// --- Main Plugin Class ---
export default class RedirectPlugin extends Plugin {
// --- Properties ---
settings: RedirectSettings;
redirectsFolder: TFolder | null = null;
isMovingNote = false;
isBypassRedirect = false;
// --- Lifecycle methods and commands---
async onload() {
await this.loadSettings();
this.addSettingTab(new RedirectSettingsTab(this.app, this));
this.app.workspace.onLayoutReady(async () => {
await this.createRedirectsFolder();
await this.redirect();
});
this.app.workspace.on("file-open", this.handleFileOpen);
this.addCommand({
id: "paste-redirect-syntax",
name: "Paste redirect syntax onto selection",
editorCallback: (editor, view) => {
const selection = editor.getSelection();
editor.replaceSelection(`::>[[${selection}]]`);
const { ch, line } = editor.getCursor();
if (!selection) {
editor.setCursor({
ch: ch - 2,
line: line,
});
}
},
});
this.addCommand({
id: "bypass-forwarding",
name: "Bypass forwarding to target note",
callback: () => {
this.isBypassRedirect = true;
new Notice("Bypassing redirects.");
},
});
}
onunload() {
this.app.workspace.off("file-open", this.handleFileOpen);
}
// --- Event Handlers ---
handleFileOpen = async (file: TFile) => {
if (this.isMovingNote) return;
if (this.isBypassRedirect) {
this.isBypassRedirect = false;
return;
}
await this.redirect();
};
async changeSettings(newTab: boolean, switchToTab: boolean): Promise<void> {
this.settings.openInNewTab = newTab;
this.settings.switchToNewTab = switchToTab;
await this.saveSettings();
}
// --- Core Logic ---
private async redirect(): Promise<void> {
const fileAndContent = await this.getCurrentFile();
if (!fileAndContent) return;
const { currentFile, content } = fileAndContent;
const targetNoteFile = this.getTargetFile(content);
if (!targetNoteFile) return;
await this.moveRedirectNote(currentFile);
await this.openTargetNote(targetNoteFile);
}
// --- Helper functions ---
private async moveRedirectNote(
redirectingNote: TFile | null
): Promise<TFile | void> {
if (
!redirectingNote ||
redirectingNote.path === `_forwards/${redirectingNote.name}`
) {
return;
}
new Notice(
`Moving ${redirectingNote.name} to the _forwards folder.`,
2000
);
if (!this.redirectsFolder) {
await this.createRedirectsFolder();
}
try {
this.isMovingNote = true;
const redirectingNoteInFolder = await this.app.vault.copy(
redirectingNote,
`/_forwards/${redirectingNote.name}`
);
if (this.settings.openInNewTab) {
await this.openTargetNote(redirectingNoteInFolder);
}
// Delay deletion to avoid race condition where the original note is deleted before the new note is fully opened in the UI.
setTimeout(async () => {
await this.deleteNote(redirectingNote);
this.isMovingNote = false;
}, 500);
} catch (error) {
this.isMovingNote = false;
console.error(error);
}
}
private async openTargetNote(targetNoteFile: TFile) {
await this.app.workspace.openLinkText(
targetNoteFile.name,
targetNoteFile.path,
this.settings.openInNewTab,
{ active: this.settings.switchToNewTab }
);
}
private async createRedirectsFolder() {
try {
this.redirectsFolder = await this.app.vault.createFolder(
"/_forwards"
);
} catch (error) {
new Notice("Failed to create the `_forwards` folder.");
console.error(error);
console.warn(
"`_forwards` folder not created or already exists.",
error
);
}
}
private async redirect() {
private async getCurrentFile(): Promise<{
currentFile: TFile;
content: string;
} | null> {
const currentFile = this.app.workspace.getActiveFile();
if (!currentFile) {
return;
return null;
}
const currentFileContent = (await this.getCurrentFileContent(
currentFile
)) as string;
const targetNoteFile = this.getTargetFile(currentFileContent);
if (!targetNoteFile) {
return;
}
if (currentFile.path !== `_forwards/${currentFile.name}`) {
new Notice(
`Moving ${currentFile.name} to the _forwards folder.`,
2000
);
await this.moveRedirectNote(currentFile);
}
await this.app.workspace.openLinkText(
targetNoteFile.name,
targetNoteFile.path,
this.settings.openInNewTab,
{ active: this.settings.switchToNewTab }
);
return {
currentFile: currentFile,
content: (await this.getCurrentFileContent(currentFile)) || "",
};
}
private async getCurrentFileContent(
@ -85,7 +179,6 @@ export default class RedirectPlugin extends Plugin {
} catch (error) {
new Notice(`Cannot read ${currentFile}.`);
console.error(`Failed to read ${currentFile} content: `, error);
return null;
}
}
@ -116,46 +209,6 @@ export default class RedirectPlugin extends Plugin {
return targetNoteFile;
}
private async moveRedirectNote(
redirectingNote: TFile | null
): Promise<TFile | void> {
if (!redirectingNote) {
return;
}
if (!this.redirectsFolder) {
await this.createRedirectsFolder();
}
try {
this.isMovingNote = true;
const redirectingNoteInFolder = await this.app.vault.copy(
redirectingNote,
`/_forwards/${redirectingNote.name}`
);
if (this.settings.openInNewTab) {
await this.app.workspace.openLinkText(
redirectingNoteInFolder.name,
redirectingNoteInFolder.path,
this.settings.openInNewTab,
{
active: this.settings.switchToNewTab,
}
);
}
// Delay deletion to avoid race condition where the original note is deleted before the new note is fully opened in the UI.
setTimeout(async () => {
await this.deleteNote(redirectingNote);
this.isMovingNote = false;
}, 500);
} catch (error) {
this.isMovingNote = false;
console.error(error);
}
}
private async deleteNote(orgRedirectingNote: TFile): Promise<void> {
try {
await this.app.fileManager.trashFile(orgRedirectingNote);
@ -168,48 +221,7 @@ export default class RedirectPlugin extends Plugin {
}
}
async onload() {
await this.loadSettings();
this.addSettingTab(new RedirectSettingsTab(this.app, this));
this.app.workspace.onLayoutReady(async () => {
await this.createRedirectsFolder();
await this.redirect();
});
this.app.workspace.on("file-open", this.handleFileOpen);
this.addCommand({
id: "paste-redirect-syntax",
name: "Paste redirect syntax onto selection",
editorCallback: (editor, view) => {
const selection = editor.getSelection();
editor.replaceSelection(`::>[[${selection}]]`);
const { ch, line } = editor.getCursor();
if (!selection) {
editor.setCursor({
ch: ch - 2,
line: line,
});
}
},
});
this.addCommand({
id: "bypass-redirect",
name: "Bypass redirect to target note",
callback: () => {
this.isBypassRedirect = true;
new Notice("Bypassing redirects.");
},
});
}
onunload() {
this.app.workspace.off("file-open", this.handleFileOpen);
}
// --- Settings Persistence ---
async loadSettings() {
try {
this.settings = Object.assign(

View file

@ -1,10 +1,10 @@
{
"id": "fast-forward-link",
"name": "FastForwardLink",
"version": "1.0.1",
"version": "1.1.0",
"minAppVersion": "0.15.0",
"description": "Fast-forward multiple links to a single target note. Create custom link shorthands (like `ps` > `photoshop`) to create synonyms, streamline navigation, and keep your vault organized.",
"author": "Idan Liberman",
"isDesktopOnly": false,
"fundingUrl": "https://buymeacoffee.com/idanlib"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "fast-forward-link",
"version": "1.0.0",
"version": "1.1.0",
"description": "Forward multiple links to a single note with ease.",
"main": "main.js",
"scripts": {

View file

@ -1,3 +1,4 @@
{
"1.0.0": "0.15.0",
"1.1.0": "0.15.0"
}
}