feat: add basic handlers for file events

This commit is contained in:
Trey Wallis 2024-04-12 17:07:59 -06:00
parent 49f77c8e97
commit f0fd2b0909
4 changed files with 138 additions and 1 deletions

View file

@ -0,0 +1,50 @@
import { PluginEvent, EventCallback } from "./types";
export default class EventManager {
private static instance: EventManager;
private eventListeners: Record<PluginEvent, EventCallback[]>;
private constructor() {
this.eventListeners = {} as Record<PluginEvent, EventCallback[]>;
}
// Ensures only one instance is created
public static getInstance(): EventManager {
if (!EventManager.instance) {
EventManager.instance = new EventManager();
}
return EventManager.instance;
}
// Method to add an event listener
public on(eventName: PluginEvent, callback: EventCallback): void {
if (!this.eventListeners[eventName]) {
this.eventListeners[eventName] = [];
}
this.eventListeners[eventName].push(callback);
}
// Method to remove an event listener
public off(
eventName: PluginEvent,
callbackToRemove: EventCallback
): void {
if (!this.eventListeners[eventName]) {
return;
}
this.eventListeners[eventName] = this.eventListeners[eventName].filter(
(callback) => callback !== callbackToRemove
);
}
// Method to trigger all callbacks associated with an event
public emit(eventName: PluginEvent, ...data: unknown[]): void {
//console.log("[EventManager] emiting event:", eventName);
if (!this.eventListeners[eventName]) {
return;
}
this.eventListeners[eventName].forEach((callback) => {
callback(...data);
});
}
}

3
src/event/types.ts Normal file
View file

@ -0,0 +1,3 @@
export type PluginEvent = "rename-file" | "create-file" | "delete-file" | "modify-file";
export type EventCallback = (...data: unknown[]) => void;

View file

@ -1,4 +1,4 @@
import { Plugin, } from 'obsidian';
import { Plugin, TFile, } from 'obsidian';
import VaultExplorerView from './obsidian/vault-explorer-view';
import VaultExplorerSettingsTab from './obsidian/vault-explorer-settings-tab';
@ -6,6 +6,7 @@ import VaultExplorerSettingsTab from './obsidian/vault-explorer-settings-tab';
import { VaultExplorerPluginSettings } from './types';
import { VAULT_EXPLORER_VIEW } from './constants';
import _ from 'lodash';
import EventManager from './event/event-manager';
const DEFAULT_SETTINGS: VaultExplorerPluginSettings = {
@ -53,10 +54,41 @@ export default class VaultExplorerPlugin extends Plugin {
}
});
this.registerEvents();
this.addSettingTab(new VaultExplorerSettingsTab(this.app, this));
}
private registerEvents() {
//Callback if the file is renamed or moved
//This callback is already debounced by Obsidian
this.registerEvent(this.app.vault.on("rename", (file: TFile, oldPath: string) => {
if (file.extension !== "md") return;
EventManager.getInstance().emit("rename-file", oldPath, file.path);
}));
//Callback if a file is deleted
//This callback is already debounced by Obsidian
this.registerEvent(this.app.vault.on("delete", (file: TFile) => {
if (file.extension !== "md") return;
EventManager.getInstance().emit("delete-file", file.path);
}));
//Callback if a file is created
//This callback is already debounced by Obsidian
this.registerEvent(this.app.vault.on("create", (file: TFile) => {
if (file.extension !== "md") return;
EventManager.getInstance().emit("create-file", file.path);
}));
//Callback if a file is modified
//This callback is already debounced by Obsidian
this.registerEvent(this.app.vault.on("modify", (file: TFile) => {
if (file.extension !== "md") return;
EventManager.getInstance().emit("modify-file", file.path);
}));
}
onunload() {
}

View file

@ -8,6 +8,7 @@ import { useAppMount } from "./app-mount-provider";
import Checkbox from "./checkbox";
import Flex from "./flex";
import Stack from "./stack";
import EventManager from "src/event/event-manager";
export default function ReactView() {
const [folderPath, setFolderPath] = React.useState<string>("");
@ -27,6 +28,57 @@ export default function ReactView() {
setOnlyCreatedToday(settings.filters.onlyCreatedToday);
}, []);
const [, setRefreshTime] = React.useState(0);
//TODO optimize
React.useEffect(() => {
const handleRenameFile = (oldPath: string, newPath: string) => {
setRefreshTime(Date.now());
};
EventManager.getInstance().on("rename-file", handleRenameFile);
return () => {
EventManager.getInstance().off("rename-file", handleRenameFile);
};
}, []);
//TODO optimize
React.useEffect(() => {
const handleCreateFile = (oldPath: string, newPath: string) => {
setRefreshTime(Date.now());
};
EventManager.getInstance().on("create-file", handleCreateFile);
return () => {
EventManager.getInstance().off("create-file", handleCreateFile);
};
}, []);
//TODO optimize
React.useEffect(() => {
const handleDeleteFile = (oldPath: string, newPath: string) => {
setRefreshTime(Date.now());
};
EventManager.getInstance().on("delete-file", handleDeleteFile);
return () => {
EventManager.getInstance().off("delete-file", handleDeleteFile);
};
}, []);
//TODO optimize
//TODO should we use handle frontmatter change?
React.useEffect(() => {
const handleModifyFile = (oldPath: string, newPath: string) => {
setRefreshTime(Date.now());
};
EventManager.getInstance().on("modify-file", handleModifyFile);
return () => {
EventManager.getInstance().off("modify-file", handleModifyFile);
};
}, []);
React.useEffect(() => {
onSettingsChange({
...settings,