mirror of
https://github.com/lostpaul/obsidian-folder-notes.git
synced 2026-07-22 07:40:24 +00:00
Automatically update folder overview
& remove listeners when closing the file
This commit is contained in:
parent
5d3a77d711
commit
52b0905d0d
3 changed files with 140 additions and 63 deletions
|
|
@ -55,15 +55,9 @@ export async function renderFileExplorer(plugin: FolderNotesPlugin, ctx: Markdow
|
|||
}
|
||||
});
|
||||
|
||||
function handleVaultChange(eventType: string) {
|
||||
folderOverview.on('vault-change', async () => {
|
||||
renderFileExplorer(plugin, ctx, root, yaml, pathBlacklist, folderOverview);
|
||||
console.log(eventType);
|
||||
}
|
||||
|
||||
plugin.app.vault.on('rename', () => handleVaultChange('renamed'));
|
||||
plugin.app.vault.on('create', () => handleVaultChange('created'));
|
||||
plugin.app.vault.on('delete', () => handleVaultChange('deleted'));
|
||||
|
||||
});
|
||||
|
||||
if (tFolder instanceof TFolder && !yaml.folderPath.trim().includes('/')) {
|
||||
addFiles(tFolder.children, overviewList, folderOverview);
|
||||
|
|
@ -143,31 +137,7 @@ async function addFiles(files: TAbstractFile[], childrenElement: HTMLElement, fo
|
|||
}
|
||||
|
||||
fileTitle.oncontextmenu = (e) => {
|
||||
const fileMenu = new Menu();
|
||||
fileMenu.addSeparator();
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Rename');
|
||||
item.setIcon('pencil');
|
||||
item.onClick(async () => {
|
||||
plugin.app.fileManager.promptForFileRename(child)
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Delete');
|
||||
item.setIcon('trash');
|
||||
item.dom.addClass('is-warning');
|
||||
item.dom.setAttribute('data-section', 'danger')
|
||||
item.onClick(() => {
|
||||
plugin.app.fileManager.promptForDeletion(child)
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addSeparator();
|
||||
|
||||
plugin.app.workspace.trigger('file-menu', fileMenu, child, "folder-overview-file-context-menu", null);
|
||||
fileMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
||||
folderOverview.fileMenu(child, e);
|
||||
}
|
||||
|
||||
fileTitle.createDiv({
|
||||
|
|
@ -229,32 +199,7 @@ function createFolderEL(plugin: FolderNotesPlugin, child: TFolder, folderOvervie
|
|||
})
|
||||
|
||||
folderTitle.oncontextmenu = (e) => {
|
||||
const fileMenu = new Menu();
|
||||
fileMenu.addSeparator();
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Rename');
|
||||
item.setIcon('pencil');
|
||||
item.onClick(async () => {
|
||||
console.log('child', child)
|
||||
new NewFolderNameModal(plugin.app, plugin, child).open();
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Delete');
|
||||
item.setIcon('trash');
|
||||
item.dom.addClass('is-warning');
|
||||
item.dom.setAttribute('data-section', 'danger')
|
||||
item.onClick(() => {
|
||||
plugin.app.fileManager.promptForFolderDeletion(child)
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addSeparator();
|
||||
|
||||
plugin.app.workspace.trigger('file-menu', fileMenu, child, "folder-overview-file-context-menu", null);
|
||||
fileMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
||||
folderOverview.folderMenu(child, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { MarkdownPostProcessorContext, parseYaml, TAbstractFile, TFolder, TFile, stringifyYaml, Notice } from 'obsidian';
|
||||
import { MarkdownPostProcessorContext, parseYaml, TAbstractFile, TFolder, TFile, stringifyYaml, Notice, Menu, MarkdownRenderChild } from 'obsidian';
|
||||
import { getFolderNote } from '../functions/folderNoteFunctions';
|
||||
import FolderNotesPlugin from '../main';
|
||||
import { FolderOverviewSettings } from './ModalSettings';
|
||||
|
|
@ -7,6 +7,8 @@ import { getFolderPathFromString } from '../functions/utils';
|
|||
import { getEl } from 'src/functions/styleFunctions';
|
||||
import { renderFileExplorer } from './FileExplorer';
|
||||
import { renderListOverview } from './ListStyle';
|
||||
import NewFolderNameModal from 'src/modals/NewFolderName';
|
||||
import { CustomEventEmitter } from 'src/events/EventEmitter';
|
||||
|
||||
|
||||
export type includeTypes = 'folder' | 'markdown' | 'canvas' | 'other' | 'pdf' | 'image' | 'audio' | 'video' | 'all';
|
||||
|
|
@ -30,6 +32,7 @@ export type yamlSettings = {
|
|||
};
|
||||
|
||||
export class FolderOverview {
|
||||
emitter: CustomEventEmitter;
|
||||
yaml: yamlSettings;
|
||||
plugin: FolderNotesPlugin;
|
||||
ctx: MarkdownPostProcessorContext;
|
||||
|
|
@ -42,7 +45,10 @@ export class FolderOverview {
|
|||
sourceFolder: TFolder | undefined;
|
||||
root: HTMLElement;
|
||||
listEl: HTMLUListElement;
|
||||
|
||||
private eventListeners: (() => void)[] = [];
|
||||
constructor(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, source: string, el: HTMLElement) {
|
||||
this.emitter = new CustomEventEmitter();
|
||||
let yaml: yamlSettings = parseYaml(source);
|
||||
if (!yaml) { yaml = {} as yamlSettings; }
|
||||
const includeTypes = yaml?.includeTypes || plugin.settings.defaultOverview.includeTypes || ['folder', 'markdown'];
|
||||
|
|
@ -71,24 +77,72 @@ export class FolderOverview {
|
|||
showFolderNotes: yaml?.showFolderNotes === undefined || yaml?.showFolderNotes === null ? plugin.settings.defaultOverview.showFolderNotes : yaml?.showFolderNotes,
|
||||
disableCollapseIcon: yaml?.disableCollapseIcon === undefined || yaml?.disableCollapseIcon === null ? plugin.settings.defaultOverview.disableCollapseIcon : yaml?.disableCollapseIcon,
|
||||
}
|
||||
|
||||
const customChild = new CustomMarkdownRenderChild(el, this);
|
||||
ctx.addChild(customChild);
|
||||
}
|
||||
|
||||
on(event: string, listener: (data?: any) => void) {
|
||||
this.emitter.on(event, listener);
|
||||
}
|
||||
|
||||
off(event: string, listener: (data?: any) => void) {
|
||||
this.emitter.off(event, listener);
|
||||
}
|
||||
|
||||
private emit(event: string, data?: any) {
|
||||
this.emitter.emit(event, data);
|
||||
}
|
||||
|
||||
handleVaultChange(eventType: string) {
|
||||
this.emit(`vault-change`, eventType);
|
||||
}
|
||||
|
||||
disconnectListeners() {
|
||||
this.eventListeners.forEach(unregister => unregister());
|
||||
this.eventListeners = [];
|
||||
}
|
||||
|
||||
registerListeners() {
|
||||
const plugin = this.plugin;
|
||||
const handleRename = () => this.handleVaultChange('renamed');
|
||||
const handleCreate = () => this.handleVaultChange('created');
|
||||
const handleDelete = () => this.handleVaultChange('deleted');
|
||||
|
||||
plugin.app.vault.on('rename', handleRename);
|
||||
plugin.app.vault.on('create', handleCreate);
|
||||
plugin.app.vault.on('delete', handleDelete);
|
||||
|
||||
this.eventListeners.push(() => plugin.app.vault.off('rename', handleRename));
|
||||
this.eventListeners.push(() => plugin.app.vault.off('create', handleCreate));
|
||||
this.eventListeners.push(() => plugin.app.vault.off('delete', handleDelete));
|
||||
}
|
||||
|
||||
create(plugin: FolderNotesPlugin, source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) {
|
||||
el.empty();
|
||||
el.parentElement?.classList.add('folder-overview-container');
|
||||
|
||||
const root = el.createEl('div', { cls: 'folder-overview' });
|
||||
this.root = root;
|
||||
|
||||
const titleEl = root.createEl('h1', { cls: 'folder-overview-title' });
|
||||
|
||||
const ul = root.createEl('ul', { cls: 'folder-overview-list' });
|
||||
this.listEl = ul;
|
||||
|
||||
if (this.yaml.includeTypes.length === 0) { return this.addEditButton(root); }
|
||||
let files: TAbstractFile[] = [];
|
||||
|
||||
const sourceFile = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath);
|
||||
if (!sourceFile) return;
|
||||
|
||||
let sourceFolderPath = this.yaml.folderPath || getFolderPathFromString(ctx.sourcePath);
|
||||
if (!ctx.sourcePath.includes('/')) {
|
||||
sourceFolderPath = '/';
|
||||
}
|
||||
|
||||
this.registerListeners();
|
||||
|
||||
let sourceFolder: TFolder | undefined;
|
||||
|
||||
if (sourceFolderPath !== '/') {
|
||||
|
|
@ -296,6 +350,64 @@ export class FolderOverview {
|
|||
});
|
||||
return allFiles;
|
||||
}
|
||||
|
||||
fileMenu(file: TFile, e: MouseEvent) {
|
||||
const plugin = this.plugin;
|
||||
const fileMenu = new Menu();
|
||||
fileMenu.addSeparator();
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Rename');
|
||||
item.setIcon('pencil');
|
||||
item.onClick(async () => {
|
||||
plugin.app.fileManager.promptForFileRename(file)
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addItem((item) => {
|
||||
item.setTitle('Delete');
|
||||
item.setIcon('trash');
|
||||
item.dom.addClass('is-warning');
|
||||
item.dom.setAttribute('data-section', 'danger')
|
||||
item.onClick(() => {
|
||||
plugin.app.fileManager.promptForDeletion(file)
|
||||
});
|
||||
});
|
||||
|
||||
fileMenu.addSeparator();
|
||||
|
||||
plugin.app.workspace.trigger('file-menu', fileMenu, file, "folder-overview-file-context-menu", null);
|
||||
fileMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
||||
}
|
||||
|
||||
folderMenu(folder: TFolder, e: MouseEvent) {
|
||||
const plugin = this.plugin;
|
||||
const folderMenu = new Menu();
|
||||
folderMenu.addSeparator();
|
||||
|
||||
folderMenu.addItem((item) => {
|
||||
item.setTitle('Rename');
|
||||
item.setIcon('pencil');
|
||||
item.onClick(async () => {
|
||||
new NewFolderNameModal(plugin.app, plugin, folder).open();
|
||||
});
|
||||
});
|
||||
|
||||
folderMenu.addItem((item) => {
|
||||
item.setTitle('Delete');
|
||||
item.setIcon('trash');
|
||||
item.dom.addClass('is-warning');
|
||||
item.dom.setAttribute('data-section', 'danger')
|
||||
item.onClick(() => {
|
||||
plugin.app.fileManager.promptForFolderDeletion(folder)
|
||||
});
|
||||
});
|
||||
|
||||
folderMenu.addSeparator();
|
||||
|
||||
plugin.app.workspace.trigger('file-menu', folderMenu, folder, "folder-overview-folder-context-menu", null);
|
||||
folderMenu.showAtPosition({ x: e.pageX, y: e.pageY });
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateYaml(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, el: HTMLElement, yaml: yamlSettings) {
|
||||
|
|
@ -332,4 +444,17 @@ export function getCodeBlockEndLine(text: string, startLine: number, count = 1)
|
|||
count++;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
class CustomMarkdownRenderChild extends MarkdownRenderChild {
|
||||
folderOverview: FolderOverview;
|
||||
constructor(el: HTMLElement, folderOverview: FolderOverview) {
|
||||
super(el);
|
||||
this.folderOverview = folderOverview;
|
||||
}
|
||||
|
||||
onunload() {
|
||||
this.folderOverview.disconnectListeners();
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ export function renderListOverview(plugin: FolderNotesPlugin, ctx: MarkdownPostP
|
|||
files = folderOverview.sortFiles(files.filter(f => f instanceof TFile));
|
||||
folders.forEach((file) => {
|
||||
if (file instanceof TFolder) {
|
||||
const folderItem = addFolderList(plugin, ul, folderOverview.pathBlacklist, file);
|
||||
const folderItem = addFolderList(plugin, ul, folderOverview.pathBlacklist, file, folderOverview);
|
||||
if (!folderItem) { return; }
|
||||
goThroughFolders(plugin, folderItem, file, folderOverview.yaml.depth, sourceFolderPath, ctx, folderOverview.yaml, folderOverview.pathBlacklist, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview);
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ export function renderListOverview(plugin: FolderNotesPlugin, ctx: MarkdownPostP
|
|||
});
|
||||
}
|
||||
|
||||
export function addFolderList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIElement, pathBlacklist: string[], folder: TFolder) {
|
||||
export function addFolderList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIElement, pathBlacklist: string[], folder: TFolder, folderOverview: FolderOverview) {
|
||||
const folderItem = list.createEl('li', { cls: 'folder-overview-list folder-list' });
|
||||
const folderNote = getFolderNote(plugin, folder.path);
|
||||
if (folderNote instanceof TFile) {
|
||||
|
|
@ -43,6 +43,9 @@ export function addFolderList(plugin: FolderNotesPlugin, list: HTMLUListElement
|
|||
} else {
|
||||
const folderName = folderItem.createEl('span', { cls: 'folder-overview-list-item folder-name-item' });
|
||||
folderName.innerText = folder.name;
|
||||
folderName.oncontextmenu = (e) => {
|
||||
folderOverview.folderMenu(folder, e);
|
||||
}
|
||||
}
|
||||
return folderItem;
|
||||
}
|
||||
|
|
@ -62,7 +65,7 @@ function goThroughFolders(plugin: FolderNotesPlugin, list: HTMLLIElement | HTMLU
|
|||
const ul = list.createEl('ul', { cls: 'folder-overview-list' });
|
||||
folders.forEach((file) => {
|
||||
if (file instanceof TFolder) {
|
||||
const folderItem = addFolderList(plugin, ul, pathBlacklist, file);
|
||||
const folderItem = addFolderList(plugin, ul, pathBlacklist, file, folderOverview);
|
||||
if (!folderItem) return;
|
||||
goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag, folderOverview);
|
||||
}
|
||||
|
|
@ -92,6 +95,10 @@ function addFileList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIE
|
|||
if (pathBlacklist.includes(file.path)) return;
|
||||
}
|
||||
const listItem = list.createEl('li', { cls: 'folder-overview-list file-link' });
|
||||
listItem.oncontextmenu = (e) => {
|
||||
e.stopImmediatePropagation();
|
||||
folderOverview.fileMenu(file, e);
|
||||
}
|
||||
const nameItem = listItem.createEl('div', { cls: 'folder-overview-list-item' });
|
||||
const link = nameItem.createEl('a', { cls: 'internal-link', href: file.path });
|
||||
link.innerText = file.basename;
|
||||
|
|
|
|||
Loading…
Reference in a new issue