From 5106b6f471c2760e3dcdd4e24bd7bb67aa4508b9 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Tue, 31 Dec 2024 23:06:49 +0100 Subject: [PATCH] Fix file explorer folder overview depth issue and also added a tooltip above the depth slider --- src/folderOverview/FileExplorer.ts | 33 ++++++++++--------- src/folderOverview/FolderOverview.ts | 48 +++++++++++++--------------- src/folderOverview/ListStyle.ts | 8 ++++- src/folderOverview/ModalSettings.ts | 1 + 4 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/folderOverview/FileExplorer.ts b/src/folderOverview/FileExplorer.ts index f9bdaa0..b17309d 100644 --- a/src/folderOverview/FileExplorer.ts +++ b/src/folderOverview/FileExplorer.ts @@ -61,6 +61,7 @@ export class FileExplorerOverview { if (!folderElement && !tFolder) return; // wait until the file explorer is loaded + const sourceFolderPath = tFolder?.path || ''; folderElement = document.querySelectorAll('.nav-files-container')[0] as HTMLElement; if (!folderElement) return; @@ -108,7 +109,7 @@ export class FileExplorerOverview { folderOverview.on('vault-change', handleVaultChange); if (tFolder instanceof TFolder) { - await this.addFiles(tFolder.children, overviewList, folderOverview); + await this.addFiles(tFolder.children, overviewList, folderOverview, sourceFolderPath); } newFolderElement.querySelectorAll('div.tree-item-icon').forEach((el) => { @@ -117,7 +118,7 @@ export class FileExplorerOverview { const path = el.parentElement?.getAttribute('data-path'); if (!path) return; const folder = plugin.app.vault.getAbstractFileByPath(path); - this.handleCollapseClick(el, plugin, yaml, this.pathBlacklist, source, folderOverview, folder); + this.handleCollapseClick(el, plugin, yaml, this.pathBlacklist, sourceFolderPath, folderOverview, folder); } } }); @@ -131,15 +132,16 @@ export class FileExplorerOverview { }; } - async addFiles(files: TAbstractFile[], childrenElement: HTMLElement, folderOverview: FolderOverview) { + async addFiles(files: TAbstractFile[], childrenElement: HTMLElement, folderOverview: FolderOverview, sourceFolderPath: string) { const plugin = folderOverview.plugin; - const sortedFiles = folderOverview.sortFiles(files); + const allFiles = await folderOverview.filterFiles(files, plugin, sourceFolderPath, folderOverview.yaml.depth, folderOverview.pathBlacklist); + const sortedFiles = folderOverview.sortFiles(allFiles); const folders = sortedFiles.filter(child => child instanceof TFolder); const otherFiles = sortedFiles.filter(child => child instanceof TFile); for (const child of folders) { - await this.createFolderEL(plugin, child, folderOverview, childrenElement); + await this.createFolderEL(plugin, child, folderOverview, childrenElement, sourceFolderPath); } for (const child of otherFiles) { @@ -148,7 +150,7 @@ export class FileExplorerOverview { } - async handleCollapseClick(el: HTMLElement, plugin: FolderNotesPlugin, yaml: yamlSettings, pathBlacklist: string[], sourcePath: string, folderOverview: FolderOverview, folder?: TFolder | undefined | null | TAbstractFile) { + async handleCollapseClick(el: HTMLElement, plugin: FolderNotesPlugin, yaml: yamlSettings, pathBlacklist: string[], sourceFolderPath: string, folderOverview: FolderOverview, folder?: TFolder | undefined | null | TAbstractFile) { el.classList.toggle('is-collapsed'); if (el.classList.contains('is-collapsed')) { if (!(folder instanceof TFolder)) return; @@ -161,13 +163,12 @@ export class FileExplorerOverview { if (!folderElement) return; const childrenElement = folderElement.createDiv({ cls: 'tree-item-children nav-folder-children' }); let files = folderOverview.sortFiles(folder.children); - files = folderOverview.filterFiles(files, plugin, folder.path, yaml.depth || 1, pathBlacklist); - await this.addFiles(files, childrenElement, folderOverview); + files = await folderOverview.filterFiles(files, plugin, folder.path, yaml.depth || 1, pathBlacklist); + await this.addFiles(files, childrenElement, folderOverview, sourceFolderPath); } } - async createFolderEL(plugin: FolderNotesPlugin, child: TFolder, folderOverview: FolderOverview, childrenElement: HTMLElement) { - console.log('createFolderEL'); + async createFolderEL(plugin: FolderNotesPlugin, child: TFolder, folderOverview: FolderOverview, childrenElement: HTMLElement, sourceFolderPath: string) { const pathBlacklist = folderOverview.pathBlacklist; const source = folderOverview.source; const folderNote = getFolderNote(plugin, child.path); @@ -181,7 +182,6 @@ export class FileExplorerOverview { const svg = ''; if (yaml.includeTypes.includes('folder')) { - console.log('folder'); folderElement = childrenElement.createDiv({ cls: 'tree-item nav-folder', }); @@ -202,7 +202,7 @@ export class FileExplorerOverview { folderTitleText.onclick = () => { const collapseIcon = folderTitle?.querySelectorAll('.tree-item-icon')[0] as HTMLElement; if (collapseIcon) { - this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, child); } } } @@ -250,14 +250,15 @@ export class FileExplorerOverview { folderTitle?.classList.remove('is-collapsed'); const childrenElement = folderElement?.createDiv({ cls: 'tree-item-children nav-folder-children' }); if (childrenElement) { - await this.addFiles(child.children, childrenElement, folderOverview); + await this.addFiles(child.children, childrenElement, folderOverview, sourceFolderPath); } } else { - await this.addFiles(child.children, childrenElement, folderOverview); + await this.addFiles(child.children, childrenElement, folderOverview, sourceFolderPath); } } else { folderTitle?.classList.add('is-collapsed'); } + if (folderNote) { folderTitle?.classList.add('has-folder-note') } if (folderNote && child.children.length === 1 && yaml.disableCollapseIcon) { folderTitle?.classList.add('fn-has-no-files') } @@ -272,13 +273,12 @@ export class FileExplorerOverview { if (collapseIcon) { collapseIcon.innerHTML = svg; collapseIcon.onclick = () => { - this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, sourceFolderPath, folderOverview, child); } } } async createFileEL(plugin: FolderNotesPlugin, child: TFile, folderOverview: FolderOverview, childrenElement: HTMLElement) { - console.log('createFileEL'); const yaml = folderOverview.yaml; const pathBlacklist = folderOverview.pathBlacklist; @@ -300,7 +300,6 @@ export class FileExplorerOverview { if (!allTypes.includes(extension) && !includeTypes.includes('other')) return; } - console.log('file'); const fileElement = childrenElement.createDiv({ cls: 'tree-item nav-file', }); diff --git a/src/folderOverview/FolderOverview.ts b/src/folderOverview/FolderOverview.ts index ecc596e..06dbc85 100644 --- a/src/folderOverview/FolderOverview.ts +++ b/src/folderOverview/FolderOverview.ts @@ -77,7 +77,7 @@ export class FolderOverview { disableCollapseIcon: yaml?.disableCollapseIcon ?? plugin.settings.defaultOverview.disableCollapseIcon, alwaysCollapse: yaml?.alwaysCollapse ?? plugin.settings.defaultOverview.alwaysCollapse, }; - + const customChild = new CustomMarkdownRenderChild(el, this); ctx.addChild(customChild); @@ -180,10 +180,8 @@ export class FolderOverview { } else if (sourceFolder) { files = sourceFolder.children; } - console.log('sourceFolderPath', sourceFolderPath); - files = this.getAllFiles(files, sourceFolderPath, this.yaml.depth); - console.log('files', files); + files = await this.filterFiles(files, plugin, sourceFolderPath, this.yaml.depth, this.pathBlacklist); if (!this.yaml.includeTypes.includes('folder')) { @@ -234,7 +232,6 @@ export class FolderOverview { const overviewListEl = el.childNodes[0].childNodes[1]; if (overviewListEl && overviewListEl.childNodes.length === 0) { - console.log('overviewListEl childNodes', overviewListEl.childNodes); if (this.yaml.style === 'explorer') { const overview = el.childNodes[0]; if (!overview.childNodes[2]) { @@ -267,32 +264,31 @@ export class FolderOverview { async filterFiles(files: TAbstractFile[], plugin: FolderNotesPlugin, sourceFolderPath: string, depth: number, pathBlacklist: string[]) { const filteredFiles = await Promise.all(files.map(async (file) => { const folderPath = getFolderPathFromString(file.path); - - if ( - (pathBlacklist.includes(file.path) && !this.yaml.showFolderNotes) || - !folderPath.startsWith(sourceFolderPath) && sourceFolderPath !== '/' || - file.path === this.sourceFilePath || - (await getExcludedFolder(plugin, file.path, true))?.excludeFromFolderOverview - ) { + const isBlacklisted = pathBlacklist.includes(file.path); + const isSubfolder = folderPath.startsWith(sourceFolderPath) && sourceFolderPath !== '/'; + const isSourceFile = file.path === this.sourceFilePath; + const isExcludedFromOverview = (await getExcludedFolder(plugin, file.path, true))?.excludeFromFolderOverview; + + if ((isBlacklisted && !this.yaml.showFolderNotes) || !isSubfolder || isSourceFile || isExcludedFromOverview) { return null; } - + const fileDepth = file.path.split('/').length - sourceFolderPath.split('/').length; return fileDepth <= depth ? file : null; })); - + return filteredFiles.filter(file => file !== null); } - + sortFiles(files: TAbstractFile[]): TAbstractFile[] { const yaml = this.yaml; - + if (!yaml?.sortBy) { yaml.sortBy = this.plugin.settings.defaultOverview.sortBy ?? 'name'; yaml.sortByAsc = this.plugin.settings.defaultOverview.sortByAsc ?? false; } - + files.sort((a, b) => { if (a instanceof TFolder && !(b instanceof TFolder)) { return -1; @@ -300,13 +296,13 @@ export class FolderOverview { if (!(a instanceof TFolder) && b instanceof TFolder) { return 1; } - + if (a instanceof TFolder && b instanceof TFolder) { return yaml.sortByAsc ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name); } - + if (a instanceof TFile && b instanceof TFile) { if (yaml.sortBy === 'created') { return yaml.sortByAsc ? a.stat.ctime - b.stat.ctime : b.stat.ctime - a.stat.ctime; @@ -321,9 +317,9 @@ export class FolderOverview { return 0; }); - + return files; - } + } removeEmptyFolders(ul: HTMLUListElement | HTMLLIElement, depth: number, yaml: yamlSettings) { const childrensToRemove: ChildNode[] = []; @@ -349,10 +345,10 @@ export class FolderOverview { const getDepth = (filePath: string) => { return filePath.split('/').length - sourceFolderPath.split('/').length; }; - + files.forEach((file) => { const fileDepth = getDepth(file.path); - + if (file instanceof TFolder) { if (fileDepth < depth) { allFiles.push(...this.getAllFiles(file.children, sourceFolderPath, depth)); @@ -361,11 +357,11 @@ export class FolderOverview { allFiles.push(file); } }); - + return allFiles; } - - + + fileMenu(file: TFile, e: MouseEvent) { const plugin = this.plugin; diff --git a/src/folderOverview/ListStyle.ts b/src/folderOverview/ListStyle.ts index 2f6ad28..83c48ac 100644 --- a/src/folderOverview/ListStyle.ts +++ b/src/folderOverview/ListStyle.ts @@ -31,6 +31,7 @@ export function renderListOverview(plugin: FolderNotesPlugin, ctx: MarkdownPostP goThroughFolders(plugin, folderItem, file, folderOverview.yaml.depth, sourceFolderPath, ctx, folderOverview.yaml, folderOverview.pathBlacklist, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview); } }); + files.forEach((file) => { if (file instanceof TFile) { addFileList(plugin, ul, folderOverview.pathBlacklist, file, folderOverview.yaml.includeTypes, folderOverview.yaml.disableFileTag, folderOverview); @@ -66,11 +67,12 @@ async function goThroughFolders(plugin: FolderNotesPlugin, list: HTMLLIElement | depth--; } - let allFiles = await folderOverview.filterFiles(folder.children, plugin, sourceFolderPath, depth, pathBlacklist); + const allFiles = await folderOverview.filterFiles(folder.children, plugin, sourceFolderPath, depth, pathBlacklist); const files = folderOverview.sortFiles(allFiles.filter((file) => !(file instanceof TFolder))); const folders = folderOverview.sortFiles(allFiles.filter((file) => file instanceof TFolder)); const ul = list.createEl('ul', { cls: 'folder-overview-list' }); + folders.forEach((file) => { if (file instanceof TFolder) { const folderItem = addFolderList(plugin, ul, pathBlacklist, file, folderOverview); @@ -78,6 +80,7 @@ async function goThroughFolders(plugin: FolderNotesPlugin, list: HTMLLIElement | goThroughFolders(plugin, folderItem, file, depth, sourceFolderPath, ctx, yaml, pathBlacklist, includeTypes, disableFileTag, folderOverview); } }); + files.forEach((file) => { if (file instanceof TFile) { addFileList(plugin, ul, pathBlacklist, file, includeTypes, disableFileTag, folderOverview); @@ -99,14 +102,17 @@ function addFileList(plugin: FolderNotesPlugin, list: HTMLUListElement | HTMLLIE const allTypes = ['md', 'canvas', 'pdf', ...imageTypes, ...videoTypes, ...audioTypes]; if (!allTypes.includes(file.extension) && !includeTypes.includes('other')) return; } + if (!folderOverview.yaml.showFolderNotes) { 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; diff --git a/src/folderOverview/ModalSettings.ts b/src/folderOverview/ModalSettings.ts index 326a651..2585645 100644 --- a/src/folderOverview/ModalSettings.ts +++ b/src/folderOverview/ModalSettings.ts @@ -245,6 +245,7 @@ export class FolderOverviewSettings extends Modal { slider .setValue(this.yaml?.depth || 2) .setLimits(1, 10, 1) + .setDynamicTooltip() .onChange(async (value) => { this.yaml.depth = value; if (this.defaultSettings) {