From 4962ac52361c48799cadf9acd13ea66611aae263 Mon Sep 17 00:00:00 2001 From: Lost Paul <70213368+LostPaul@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:05:58 +0200 Subject: [PATCH] Save progress --- manifest-beta.json | 2 +- src/Commands.ts | 51 +- src/ExcludeFolders/ExcludeFolder.ts | 2 + src/ExcludeFolders/ExcludePattern.ts | 1 + .../functions/folderFunctions.ts | 21 +- src/events/MutationObserver.ts | 4 +- src/events/handleClick.ts | 9 +- src/events/handleCreate.ts | 12 +- src/events/handleRename.ts | 24 +- src/folderOverview/FileExplorer.ts | 474 +++++++++++------- src/folderOverview/FolderOverview.ts | 24 +- src/functions/folderNoteFunctions.ts | 18 +- src/globals.d.ts | 11 - src/main.ts | 98 ++-- src/modals/ConfirmCreation.ts | 2 +- src/modals/NewFolderName.ts | 1 - 16 files changed, 454 insertions(+), 300 deletions(-) diff --git a/manifest-beta.json b/manifest-beta.json index 51a5354..f8e1848 100644 --- a/manifest-beta.json +++ b/manifest-beta.json @@ -1,7 +1,7 @@ { "id": "folder-notes", "name": "Folder notes", - "version": "1.7.23-9-beta", + "version": "1.7.23-10-beta", "minAppVersion": "0.15.0", "description": "Create notes within folders that can be accessed without collapsing the folder, similar to the functionality offered in Notion.", "author": "Lost Paul", diff --git a/src/Commands.ts b/src/Commands.ts index 4487426..37f64b9 100644 --- a/src/Commands.ts +++ b/src/Commands.ts @@ -4,10 +4,11 @@ import { getFolderNote, createFolderNote, deleteFolderNote, turnIntoFolderNote, import { ExcludedFolder } from './ExcludeFolders/ExcludeFolder'; import { getFolderPathFromString } from './functions/utils'; import { getExcludedFolderByPattern } from './ExcludeFolders/functions/patternFunctions'; -import { getDetachedFolder, getExcludedFolder, getExcludedFoldersByPath } from './ExcludeFolders/functions/folderFunctions'; +import { addExcludedFolder, deleteExcludedFolder, getDetachedFolder, getExcludedFolder, getExcludedFoldersByPath, updateExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; import ExcludedFolderSettings from './ExcludeFolders/modals/ExcludeFolderSettings' import { ExcludePattern } from './ExcludeFolders/ExcludePattern'; import PatternSettings from './ExcludeFolders/modals/PatternSettings'; +import { loadFolderClasses } from './functions/styleFunctions'; export class Commands { plugin: FolderNotesPlugin; @@ -34,6 +35,7 @@ export class Commands { turnIntoFolderNote(this.plugin, file, folder, folderNote); } }); + this.plugin.addCommand({ id: 'create-folder-note', name: 'Create folder note with a new folder for the active note in the current folder', @@ -58,6 +60,7 @@ export class Commands { this.plugin.saveSettings(); } }) + this.plugin.addCommand({ id: 'create-folder-note-for-current-folder', name: 'Create markdown folder note for current folder of active note', @@ -199,7 +202,7 @@ export class Commands { } fileCommands() { - this.plugin.registerEvent(this.app.workspace.on('file-menu', (menu: Menu, file: TAbstractFile) => { + this.plugin.registerEvent(this.app.workspace.on('file-menu', async (menu: Menu, file: TAbstractFile) => { let folder: TAbstractFile | TFolder | null = file.parent; if (file instanceof TFile) { if (this.plugin.settings.storageLocation === 'insideFolder') { @@ -217,14 +220,14 @@ export class Commands { if (folder instanceof TFolder) { const folderNote = getFolderNote(this.plugin, folder.path); - const excludedFolder = getExcludedFolder(this.plugin, folder.path, true) + const excludedFolder = await getExcludedFolder(this.plugin, folder.path, true) if (folderNote?.path === file.path && !excludedFolder?.detached) { return; } } else if (file.parent instanceof TFolder) { folder = file.parent; } } - menu.addItem((item) => { + menu.addItem(async (item) => { if (Platform.isDesktop && !Platform.isTablet && this.plugin.settings.useSubmenus) { item .setTitle('Folder Note Commands') @@ -276,10 +279,10 @@ export class Commands { }); } if (!(file instanceof TFolder)) return; - const excludedFolder = getExcludedFolder(this.plugin, file.path, false) + const excludedFolder = await getExcludedFolder(this.plugin, file.path, false) const detachedExcludedFolder = getDetachedFolder(this.plugin, file.path) - - if (excludedFolder) { + + if (excludedFolder && !excludedFolder.hideNote) { // I'm not sure if I'm ever going to add this because of the possibility that a folder got more than one excluded // subMenu.addItem((item) => { // item.setTitle('Manage excluded folder') @@ -339,7 +342,6 @@ export class Commands { item.setTitle('Detach folder note') .setIcon('unlink') .onClick(() => { - console.log('folderNote', folderNote) detachFolderNote(this.plugin, folderNote); }); }); @@ -353,6 +355,39 @@ export class Commands { }); }); + if (this.plugin.settings.hideFolderNote) { + if (excludedFolder?.hideNote) { + subMenu.addItem((item) => { + item.setTitle('Hide folder note in explorer') + .setIcon('eye-off') + .onClick(() => { + this.plugin.settings.excludeFolders = this.plugin.settings.excludeFolders.filter( + (folder) => (folder.path !== file.path) && folder.hideNote); + this.plugin.saveSettings(false); + loadFolderClasses(true, file, this.plugin); + }); + }); + } else { + subMenu.addItem((item) => { + item.setTitle('Show folder note in explorer') + .setIcon('eye') + .onClick(() => { + const excludedFolder = new ExcludedFolder(file.path, this.plugin.settings.excludeFolders.length, undefined, this.plugin); + excludedFolder.hideNote = true; + excludedFolder.subFolders = false; + excludedFolder.disableSync = false; + excludedFolder.disableAutoCreate = false; + excludedFolder.disableFolderNote = false; + excludedFolder.enableCollapsing = false; + excludedFolder.excludeFromFolderOverview = false; + excludedFolder.hideInSettings = true; + addExcludedFolder(this.plugin, excludedFolder, false); + loadFolderClasses(true, file, this.plugin); + }); + }); + } + } + } else { subMenu.addItem((item) => { item.setTitle('Create markdown folder note') diff --git a/src/ExcludeFolders/ExcludeFolder.ts b/src/ExcludeFolders/ExcludeFolder.ts index 5a56fdb..e53e963 100644 --- a/src/ExcludeFolders/ExcludeFolder.ts +++ b/src/ExcludeFolders/ExcludeFolder.ts @@ -14,6 +14,7 @@ export class ExcludedFolder { hideInSettings: boolean; detached: boolean; detachedFilePath?: string; + hideNote: boolean; constructor(path: string, position: number, id: string | undefined, plugin: FolderNotesPlugin) { this.type = 'folder'; this.id = id || crypto.randomUUID(); @@ -27,5 +28,6 @@ export class ExcludedFolder { this.excludeFromFolderOverview = plugin.settings.excludeFolderDefaultSettings.excludeFromFolderOverview; this.string = ''; this.hideInSettings = false; + this.hideNote = false; } } \ No newline at end of file diff --git a/src/ExcludeFolders/ExcludePattern.ts b/src/ExcludeFolders/ExcludePattern.ts index e342890..cbcae8f 100644 --- a/src/ExcludeFolders/ExcludePattern.ts +++ b/src/ExcludeFolders/ExcludePattern.ts @@ -14,6 +14,7 @@ export class ExcludePattern { hideInSettings: boolean; detached: boolean; detachedFilePath?: string; + hideNote: boolean; constructor(pattern: string, position: number, id: string | undefined, plugin: FolderNotesPlugin) { this.type = 'pattern'; this.id = id || crypto.randomUUID(); diff --git a/src/ExcludeFolders/functions/folderFunctions.ts b/src/ExcludeFolders/functions/folderFunctions.ts index 295cf75..e41f5a6 100644 --- a/src/ExcludeFolders/functions/folderFunctions.ts +++ b/src/ExcludeFolders/functions/folderFunctions.ts @@ -11,12 +11,12 @@ import { getWhitelistedFolder } from './whitelistFolderFunctions'; import { WhitelistedFolder } from '../WhitelistFolder'; import { WhitelistedPattern } from '../WhitelistPattern'; -export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, includeDetached: boolean, pathOnly?: boolean, ignoreWhitelist?: boolean) { +export async function getExcludedFolder(plugin: FolderNotesPlugin, path: string, includeDetached: boolean, pathOnly?: boolean, ignoreWhitelist?: boolean) { let excludedFolder = {} as ExcludedFolder | ExcludePattern | undefined; const whitelistedFolder = getWhitelistedFolder(plugin, path) as WhitelistedFolder | WhitelistedPattern | undefined; const folderName = getFolderNameFromPathString(path); - let matchedPatterns = getExcludedFoldersByPattern(plugin, folderName); - const excludedFolders = getExcludedFoldersByPath(plugin, path); + let matchedPatterns = await getExcludedFoldersByPattern(plugin, folderName); + const excludedFolders = await getExcludedFoldersByPath(plugin, path); if (pathOnly) { matchedPatterns = []; } let combinedExcludedFolders = [...matchedPatterns, ...excludedFolders]; @@ -31,7 +31,9 @@ export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, inclu 'enableCollapsing', 'excludeFromFolderOverview', 'detached', - 'hideInSettings' + 'hideInSettings', + 'hideNote', + 'id' ]; if (combinedExcludedFolders.length > 0) { @@ -51,14 +53,12 @@ export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, inclu if (excludedFolder?.detached) { ignoreWhitelist = true; } if (whitelistedFolder && excludedFolder && !ignoreWhitelist) { - console.log('whitelistedFolder', whitelistedFolder) excludedFolder.disableAutoCreate ? excludedFolder.disableAutoCreate = !whitelistedFolder.enableAutoCreate : ''; excludedFolder.disableFolderNote ? excludedFolder.disableFolderNote = !whitelistedFolder.enableFolderNote : ''; excludedFolder.disableSync ? excludedFolder.disableSync = !whitelistedFolder.enableSync : ''; excludedFolder.enableCollapsing = whitelistedFolder.enableCollapsing; excludedFolder.excludeFromFolderOverview ? excludedFolder.excludeFromFolderOverview = !whitelistedFolder.showInFolderOverview : ''; } else if (excludedFolder && Object.keys(excludedFolder).length === 0) { - console.log('Hello from the other side') excludedFolder = { type: 'folder', id: '', @@ -72,7 +72,8 @@ export function getExcludedFolder(plugin: FolderNotesPlugin, path: string, inclu position: 0, excludeFromFolderOverview: false, hideInSettings: false, - detached: false + detached: false, + hideNote: false, } } @@ -118,12 +119,12 @@ export function getExcludedFoldersByPath(plugin: FolderNotesPlugin, path: string }); } -export function addExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder) { +export function addExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder, reloadStyles = true) { plugin.settings.excludeFolders.push(excludedFolder); - plugin.saveSettings(true); + plugin.saveSettings(reloadStyles); } -export function deleteExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder) { +export async function deleteExcludedFolder(plugin: FolderNotesPlugin, excludedFolder: ExcludedFolder) { plugin.settings.excludeFolders = plugin.settings.excludeFolders.filter((folder) => folder.id !== excludedFolder.id || folder.type === 'pattern'); plugin.saveSettings(true); resyncArray(plugin); diff --git a/src/events/MutationObserver.ts b/src/events/MutationObserver.ts index 98d2e1a..f5afc94 100644 --- a/src/events/MutationObserver.ts +++ b/src/events/MutationObserver.ts @@ -53,7 +53,7 @@ export async function addObserver(plugin: FolderNotesPlugin) { const breadcrumbs = element.parentElement?.querySelectorAll('span.view-header-breadcrumb'); if (!breadcrumbs) return; let path = ''; - breadcrumbs.forEach((breadcrumb: HTMLElement) => { + breadcrumbs.forEach(async (breadcrumb: HTMLElement) => { if (breadcrumb.hasAttribute('old-name')) { path += breadcrumb.getAttribute('old-name') + '/'; } else { @@ -66,7 +66,7 @@ export async function addObserver(plugin: FolderNotesPlugin) { breadcrumb.setAttribute('old-name', folder.name || ''); breadcrumb.innerText = folder.newName || ''; } - const excludedFolder = getExcludedFolder(plugin, folderPath, true) + const excludedFolder = await getExcludedFolder(plugin, folderPath, true) if (excludedFolder?.disableFolderNote) return; const folderNote = getFolderNote(plugin, folderPath); if (folderNote) { diff --git a/src/events/handleClick.ts b/src/events/handleClick.ts index 5c3f209..bfe1978 100644 --- a/src/events/handleClick.ts +++ b/src/events/handleClick.ts @@ -13,7 +13,7 @@ export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNot const folderPath = event.target.getAttribute('data-path'); if (!folderPath) { return; } - const excludedFolder = getExcludedFolder(plugin, folderPath, true); + const excludedFolder = await getExcludedFolder(plugin, folderPath, true); if (excludedFolder?.disableFolderNote) { event.target.onclick = null; event.target.click(); @@ -38,7 +38,7 @@ export async function handleViewHeaderClick(event: MouseEvent, plugin: FolderNot } else if (event.altKey || Keymap.isModEvent(event) === 'tab') { if ((plugin.settings.altKey && event.altKey) || (plugin.settings.ctrlKey && Keymap.isModEvent(event) === 'tab')) { await createFolderNote(plugin, folderPath, true, undefined, true); - addCSSClassToTitleEL(folderPath, 'has-folder-note'); + addCSSClassToTitleEL(plugin, folderPath, 'has-folder-note'); removeCSSClassFromEL(folderPath, 'has-not-folder-note'); return; } @@ -59,7 +59,7 @@ export async function handleFolderClick(event: MouseEvent, plugin: FolderNotesPl const folderPath = event.target.parentElement?.getAttribute('data-path'); if (!folderPath) { return; } - const excludedFolder = getExcludedFolder(plugin, folderPath, true); + const excludedFolder = await getExcludedFolder(plugin, folderPath, true); if (excludedFolder?.disableFolderNote) { event.target.onclick = null; event.target.click(); @@ -70,7 +70,6 @@ export async function handleFolderClick(event: MouseEvent, plugin: FolderNotesPl } const folderNote = getFolderNote(plugin, folderPath); - console.log('folderNote', folderNote); if (folderNote) { if (plugin.settings.openByClick) { @@ -87,7 +86,7 @@ export async function handleFolderClick(event: MouseEvent, plugin: FolderNotesPl } else if (event.altKey || Keymap.isModEvent(event) === 'tab') { if ((plugin.settings.altKey && event.altKey) || (plugin.settings.ctrlKey && Keymap.isModEvent(event) === 'tab')) { await createFolderNote(plugin, folderPath, true, undefined, true); - addCSSClassToTitleEL(folderPath, 'has-folder-note'); + addCSSClassToTitleEL(plugin, folderPath, 'has-folder-note'); removeCSSClassFromEL(folderPath, 'has-not-folder-note'); return; } diff --git a/src/events/handleCreate.ts b/src/events/handleCreate.ts index f5bde1c..0d883a6 100644 --- a/src/events/handleCreate.ts +++ b/src/events/handleCreate.ts @@ -4,13 +4,13 @@ import { createFolderNote, getFolder, getFolderNote } from 'src/functions/folder import { getExcludedFolder } from 'src/ExcludeFolders/functions/folderFunctions'; import { removeCSSClassFromEL, addCSSClassToTitleEL } from 'src/functions/styleFunctions'; -export function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin) { +export async function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin) { if (!plugin.app.workspace.layoutReady) return; const folder = file.parent; if (folder instanceof TFolder) { if (plugin.isEmptyFolderNoteFolder(folder)) { - addCSSClassToTitleEL(folder.path, 'only-has-folder-note'); + addCSSClassToTitleEL(plugin, folder.path, 'only-has-folder-note'); } else { removeCSSClassFromEL(folder.path, 'only-has-folder-note'); } @@ -22,8 +22,8 @@ export function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin) { const folderNote = getFolderNote(plugin, folder.path); if (folderNote && folderNote.path === file.path) { - addCSSClassToTitleEL(folder.path, 'has-folder-note'); - addCSSClassToTitleEL(file.path, 'is-folder-note'); + addCSSClassToTitleEL(plugin, folder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, file.path, 'is-folder-note'); return; } @@ -45,12 +45,12 @@ export function handleCreate(file: TAbstractFile, plugin: FolderNotesPlugin) { openFile = false; } - const excludedFolder = getExcludedFolder(plugin, file.path, true); + const excludedFolder = await getExcludedFolder(plugin, file.path, true); if (excludedFolder?.disableAutoCreate) return; const folderNote = getFolderNote(plugin, file.path); if (folderNote) return; createFolderNote(plugin, file.path, openFile, undefined, true); - addCSSClassToTitleEL(file.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, file.path, 'has-folder-note'); } \ No newline at end of file diff --git a/src/events/handleRename.ts b/src/events/handleRename.ts index d4635bd..d57fe50 100644 --- a/src/events/handleRename.ts +++ b/src/events/handleRename.ts @@ -12,7 +12,7 @@ export function handleRename(file: TAbstractFile, oldPath: string, plugin: Folde const isRename = (file.parent?.path === getFolderPathFromString(oldPath)) if (folder instanceof TFolder) { if (plugin.isEmptyFolderNoteFolder(folder)) { - addCSSClassToTitleEL(folder.path, 'only-has-folder-note'); + addCSSClassToTitleEL(plugin, folder.path, 'only-has-folder-note'); } else { removeCSSClassFromEL(folder.path, 'only-has-folder-note'); } @@ -20,7 +20,7 @@ export function handleRename(file: TAbstractFile, oldPath: string, plugin: Folde if (oldFolder instanceof TFolder) { if (plugin.isEmptyFolderNoteFolder(oldFolder)) { - addCSSClassToTitleEL(oldFolder.path, 'only-has-folder-note'); + addCSSClassToTitleEL(plugin, oldFolder.path, 'only-has-folder-note'); } else { removeCSSClassFromEL(oldFolder.path, 'only-has-folder-note'); } @@ -52,7 +52,7 @@ export function handleFileMove(file: TFile, oldPath: string, plugin: FolderNotes } -export function handleFolderRename(file: TFolder, oldPath: string, plugin: FolderNotesPlugin) { +export async function handleFolderRename(file: TFolder, oldPath: string, plugin: FolderNotesPlugin) { const fileName = plugin.settings.folderNoteName.replace('{{folder_name}}', file.name); const oldFileName = plugin.settings.folderNoteName.replace('{{folder_name}}', getFileNameFromPathString(oldPath)); // console.log(fileName) @@ -63,7 +63,7 @@ export function handleFolderRename(file: TFolder, oldPath: string, plugin: Folde if (!(folderNote instanceof TFile)) return; - const excludedFolder = getExcludedFolder(plugin, file.path, true); + const excludedFolder = await getExcludedFolder(plugin, file.path, true); if (excludedFolder?.disableSync && !folderNote) { return removeCSSClassFromEL(file.path, 'has-folder-note'); } @@ -91,7 +91,7 @@ export function handleFolderRename(file: TFolder, oldPath: string, plugin: Folde plugin.app.fileManager.renameFile(folderNote, newPath); } -export function handleFileRename(file: TFile, oldPath: string, plugin: FolderNotesPlugin) { +export async function handleFileRename(file: TFile, oldPath: string, plugin: FolderNotesPlugin) { const oldFileName = removeExtension(getFileNameFromPathString(oldPath)); const newFileName = file.basename; if (oldFileName === newFileName) { return; } @@ -100,15 +100,15 @@ export function handleFileRename(file: TFile, oldPath: string, plugin: FolderNot const folderName = extractFolderName(plugin.settings.folderNoteName, file.basename) || file.basename; const oldFolderName = extractFolderName(plugin.settings.folderNoteName, oldFileName) || oldFileName; const newFolder = getFolderNoteFolder(plugin, file, file.basename); - let excludedFolder = getExcludedFolder(plugin, newFolder?.path || '', true); + let excludedFolder = await getExcludedFolder(plugin, newFolder?.path || '', true); const detachedExcludedFolder = getDetachedFolder(plugin, newFolder?.path || '') const folderNote = getFolderNote(plugin, oldPath, plugin.settings.storageLocation, file); if (!excludedFolder?.disableFolderNote && folderName === newFolder?.name && !detachedExcludedFolder) { - addCSSClassToTitleEL(file.path, 'is-folder-note'); - addCSSClassToTitleEL(newFolder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, file.path, 'is-folder-note'); + addCSSClassToTitleEL(plugin, newFolder.path, 'has-folder-note'); return; } else if (excludedFolder?.disableFolderNote || (folderName !== newFolder?.name)) { removeCSSClassFromEL(file.path, 'is-folder-note'); @@ -143,9 +143,9 @@ export function handleFileRename(file: TFile, oldPath: string, plugin: FolderNot }); } if (folderName === newFolder?.name) { - addCSSClassToTitleEL(file.path, 'is-folder-note'); + addCSSClassToTitleEL(plugin, file.path, 'is-folder-note'); removeCSSClassFromEL(oldFolder?.path, 'has-folder-note'); - addCSSClassToTitleEL(newFolder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, newFolder.path, 'has-folder-note'); return; } @@ -175,8 +175,8 @@ async function renameFolderOnFileRename(file: TFile, oldPath: string, oldFolder: removeCSSClassFromEL(file.path, 'is-folder-note'); return; } else if (newFolderName === oldFolder.name) { - addCSSClassToTitleEL(oldFolder.path, 'has-folder-note'); - addCSSClassToTitleEL(file.path, 'is-folder-note'); + addCSSClassToTitleEL(plugin, oldFolder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, file.path, 'is-folder-note'); return; } diff --git a/src/folderOverview/FileExplorer.ts b/src/folderOverview/FileExplorer.ts index 475d2da..cdbf52c 100644 --- a/src/folderOverview/FileExplorer.ts +++ b/src/folderOverview/FileExplorer.ts @@ -9,230 +9,338 @@ import { FolderOverview, yamlSettings } from './FolderOverview'; import FolderNameModal from 'src/modals/FolderName'; import NewFolderNameModal from 'src/modals/NewFolderName'; -export async function renderFileExplorer(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, root: HTMLElement, yaml: yamlSettings, pathBlacklist: string[], folderOverview: FolderOverview) { - const folder = getEl(yaml.folderPath) - let folderElement = folder?.parentElement; - const source = ctx.sourcePath; - const overviewList = folderOverview.listEl; - overviewList?.empty(); - if (!overviewList) return; +export class FileExplorerOverview { + plugin: FolderNotesPlugin; + folderOverview: FolderOverview; + pathBlacklist: string[]; + source: string; + yaml: yamlSettings; + root: HTMLElement; - - let tFolder = plugin.app.vault.getAbstractFileByPath(yaml.folderPath); - if (!tFolder && yaml.folderPath.trim() == '') { - if (ctx.sourcePath.includes('/')) { - tFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath)); - } else { - yaml.folderPath = '/'; - tFolder = plugin.app.vault.getAbstractFileByPath('/'); - } + eventListeners: (() => void)[] = []; + constructor(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, root: HTMLElement, yaml: yamlSettings, pathBlacklist: string[], folderOverview: FolderOverview) { + this.plugin = plugin; + this.folderOverview = folderOverview; + this.pathBlacklist = pathBlacklist; + this.source = ctx.sourcePath; + this.yaml = yaml; + this.root = root; } - if (!folderElement && !tFolder) return; + disconnectListeners() { + this.eventListeners.forEach((unregister) => { + unregister(); + }); + this.eventListeners = []; + } - folderElement = document.querySelectorAll('.nav-files-container')[0] as HTMLElement; - if (!folderElement) return; - const newFolderElement = folderElement.cloneNode(true) as HTMLElement; - newFolderElement.querySelectorAll('div.nav-folder-title').forEach((el) => { - const folder = plugin.app.vault.getAbstractFileByPath(el.getAttribute('data-path') || ''); - if (!(folder instanceof TFolder)) return; - if (yaml.storeFolderCondition) { - if (folder.collapsed) { - el.classList.add('is-collapsed'); + async renderFileExplorer() { + this.disconnectListeners(); + const plugin = this.plugin; + const ctx = this.folderOverview.ctx; + const root = this.folderOverview.root; + const yaml = this.folderOverview.yaml; + const folderOverview = this.folderOverview; + const folder = getEl(yaml.folderPath) + let folderElement = folder?.parentElement; + const source = ctx.sourcePath; + const overviewList = folderOverview.listEl; + overviewList?.empty(); + if (!overviewList) return; + + let tFolder = plugin.app.vault.getAbstractFileByPath(yaml.folderPath); + if (!tFolder && yaml.folderPath.trim() == '') { + if (ctx.sourcePath.includes('/')) { + tFolder = plugin.app.vault.getAbstractFileByPath(getFolderPathFromString(ctx.sourcePath)); } else { - el.classList.remove('is-collapsed'); + yaml.folderPath = '/'; + tFolder = plugin.app.vault.getAbstractFileByPath('/'); } - } else { - if (el.parentElement?.classList.contains('is-collapsed')) { - folder.collapsed = true; + } + + if (!folderElement && !tFolder) return; + // wait until the file explorer is loaded + + + folderElement = document.querySelectorAll('.nav-files-container')[0] as HTMLElement; + console.log('folderElement', folderElement); + if (!folderElement) return; + const newFolderElement = folderElement.cloneNode(true) as HTMLElement; + console.log('newFolderElement', newFolderElement); + + newFolderElement.querySelectorAll('div.nav-folder-title').forEach((el) => { + const folder = plugin.app.vault.getAbstractFileByPath(el.getAttribute('data-path') || ''); + if (!(folder instanceof TFolder)) return; + if (yaml.storeFolderCondition) { + if (folder.collapsed) { + el.classList.add('is-collapsed'); + } else { + el.classList.remove('is-collapsed'); + } } else { - folder.collapsed = false; + if (el.parentElement?.classList.contains('is-collapsed')) { + folder.collapsed = true; + } else { + folder.collapsed = false; + } } - } - if (el.classList.contains('has-folder-note')) { - const folderNote = getFolderNote(plugin, folder.path); - if (folderNote) { pathBlacklist.push(folderNote.path); } - } - }); + if (el.classList.contains('has-folder-note')) { + const folderNote = getFolderNote(plugin, folder.path); + if (folderNote) { folderOverview.pathBlacklist.push(folderNote.path); } + } + }); - folderOverview.on('vault-change', async () => { - renderFileExplorer(plugin, ctx, root, yaml, pathBlacklist, folderOverview); - }); + const debouncedRenderFileExplorer = this.debounce(() => this.renderFileExplorer(), 300); - if (tFolder instanceof TFolder) { - addFiles(tFolder.children, overviewList, folderOverview); + const handleVaultChange = () => { + debouncedRenderFileExplorer(); + } + + this.eventListeners.push(() => { + folderOverview.off('vault-change', handleVaultChange); + }); + + folderOverview.on('vault-change', handleVaultChange); + + if (tFolder instanceof TFolder) { + this.addFiles(tFolder.children, overviewList, folderOverview); + } + + newFolderElement.querySelectorAll('div.tree-item-icon').forEach((el) => { + if (el instanceof HTMLElement) { + el.onclick = () => { + 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); + } + } + }); } - newFolderElement.querySelectorAll('div.tree-item-icon').forEach((el) => { - if (el instanceof HTMLElement) { - el.onclick = () => { - const path = el.parentElement?.getAttribute('data-path'); - if (!path) return; - const folder = plugin.app.vault.getAbstractFileByPath(path); - handleCollapseClick(el, plugin, yaml, pathBlacklist, source, folderOverview, folder); + debounce(func: Function, wait: number) { + let timeout: number | undefined; + return (...args: any[]) => { + clearTimeout(timeout); + timeout = window.setTimeout(() => func.apply(this, args), wait); + }; + } + + addFiles(files: TAbstractFile[], childrenElement: HTMLElement, folderOverview: FolderOverview) { + const plugin = folderOverview.plugin; + const pathBlacklist = folderOverview.pathBlacklist; + const yaml = folderOverview.yaml; + const folders = folderOverview.sortFiles(files.filter((file) => file instanceof TFolder)); + const filesWithoutFolders = folderOverview.sortFiles(files.filter((file) => !(file instanceof TFolder))); + + for (const child of folders) { + if (child instanceof TFolder) { + this.createFolderEL(plugin, child, folderOverview, childrenElement); } } - }); -} -async function addFiles(files: TAbstractFile[], childrenElement: HTMLElement, folderOverview: FolderOverview) { - const plugin = folderOverview.plugin; - const pathBlacklist = folderOverview.pathBlacklist; - const yaml = folderOverview.yaml; - const folders = folderOverview.sortFiles(files.filter((file) => file instanceof TFolder)); - const filesWithoutFolders = folderOverview.sortFiles(files.filter((file) => !(file instanceof TFolder))); + for (const child of filesWithoutFolders) { + if (child instanceof TFile) { + if (pathBlacklist.includes(child.path) && !yaml.showFolderNotes) { continue; } + const extension = child.extension.toLowerCase() == 'md' ? 'markdown' : child.extension.toLowerCase(); + const includeTypes = yaml.includeTypes; - for (const child of folders) { - if (child instanceof TFolder) { - createFolderEL(plugin, child, folderOverview, childrenElement); + if (includeTypes.length > 0 && !includeTypes.includes('all')) { + if ((extension === 'md' || extension === 'markdown') && !includeTypes.includes('markdown')) continue; + if (extension === 'canvas' && !includeTypes.includes('canvas')) continue; + if (extension === 'pdf' && !includeTypes.includes('pdf')) continue; + const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp']; + if (imageTypes.includes(extension) && !includeTypes.includes('image')) continue; + const videoTypes = ['mp4', 'webm', 'ogv', 'mov', 'mkv']; + if (videoTypes.includes(extension) && !includeTypes.includes('video')) continue; + const audioTypes = ['mp3', 'wav', 'm4a', '3gp', 'flac', 'ogg', 'oga', 'opus']; + if (audioTypes.includes(extension) && includeTypes.includes('audio')) continue; + const allTypes = ['markdown', 'md', 'canvas', 'pdf', ...imageTypes, ...videoTypes, ...audioTypes]; + if (!allTypes.includes(extension) && !includeTypes.includes('other')) continue; + } + + const fileElement = childrenElement.createDiv({ + cls: 'tree-item nav-file', + }); + + const fileTitle = fileElement.createDiv({ + cls: 'tree-item-self is-clickable nav-file-title pointer-cursor', + attr: { + 'data-path': child.path, + 'draggable': 'true' + }, + }) + + fileTitle.addEventListener('dragover', e => { + e.preventDefault(); + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder) { + plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: child.parent?.name || '' })); + const folderEL = folderOverview.getElFromOverview(child.parent?.path || '') + if (folderEL) { + folderEL.parentElement?.classList.add('is-being-dragged-over'); + } + } + }); + + fileTitle.addEventListener('dragleave', e => { + const folderEL = folderOverview.getElFromOverview(child.parent?.path || '') + if (folderEL) { + folderEL.parentElement?.classList.remove('is-being-dragged-over'); + } + }); + + fileTitle.addEventListener('drop', e => { + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder) { + plugin.app.fileManager.renameFile(draggable.file, child.parent?.path + '/' + draggable.file.name); + } + }); + + fileTitle.onclick = () => { + plugin.app.workspace.openLinkText(child.path, child.path, true); + } + + fileTitle.oncontextmenu = (e) => { + folderOverview.fileMenu(child, e); + } + + fileTitle.createDiv({ + cls: 'tree-item-inner nav-file-title-content', + text: child.basename, + }); + + if (child.extension !== 'md' && !yaml.disableFileTag) { + fileTitle.createDiv({ + cls: 'nav-file-tag', + text: child.extension + }); + } + } } } - for (const child of filesWithoutFolders) { - if (child instanceof TFile) { - if (pathBlacklist.includes(child.path) && !yaml.showFolderNotes) { continue; } - const extension = child.extension.toLowerCase() == 'md' ? 'markdown' : child.extension.toLowerCase(); - const includeTypes = yaml.includeTypes; + handleCollapseClick(el: HTMLElement, plugin: FolderNotesPlugin, yaml: yamlSettings, pathBlacklist: string[], sourcePath: string, folderOverview: FolderOverview, folder?: TFolder | undefined | null | TAbstractFile) { + el.classList.toggle('is-collapsed'); + if (el.classList.contains('is-collapsed')) { + if (!(folder instanceof TFolder)) return; + folder.collapsed = true; + el.parentElement?.parentElement?.childNodes[1]?.remove(); + } else { + if (!(folder instanceof TFolder)) return; + folder.collapsed = false; + const folderElement = el.parentElement?.parentElement; + 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); + this.addFiles(files, childrenElement, folderOverview); + } + } - if (includeTypes.length > 0 && !includeTypes.includes('all')) { - if ((extension === 'md' || extension === 'markdown') && !includeTypes.includes('markdown')) continue; - if (extension === 'canvas' && !includeTypes.includes('canvas')) continue; - if (extension === 'pdf' && !includeTypes.includes('pdf')) continue; - const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp']; - if (imageTypes.includes(extension) && !includeTypes.includes('image')) continue; - const videoTypes = ['mp4', 'webm', 'ogv', 'mov', 'mkv']; - if (videoTypes.includes(extension) && !includeTypes.includes('video')) continue; - const audioTypes = ['mp3', 'wav', 'm4a', '3gp', 'flac', 'ogg', 'oga', 'opus']; - if (audioTypes.includes(extension) && includeTypes.includes('audio')) continue; - const allTypes = ['markdown', 'md', 'canvas', 'pdf', ...imageTypes, ...videoTypes, ...audioTypes]; - if (!allTypes.includes(extension) && !includeTypes.includes('other')) continue; - } + async createFolderEL(plugin: FolderNotesPlugin, child: TFolder, folderOverview: FolderOverview, childrenElement: HTMLElement) { + const pathBlacklist = folderOverview.pathBlacklist; + const source = folderOverview.source; + const folderNote = getFolderNote(plugin, child.path); + const yaml = folderOverview.yaml; + let folderTitle: HTMLElement | null = null; + let folderElement: HTMLElement | null = null; - const fileElement = childrenElement.createDiv({ - cls: 'tree-item nav-file', + if (folderNote) { pathBlacklist.push(folderNote.path); } + const excludedFolder = await getExcludedFolder(plugin, child.path, true); + if (excludedFolder?.excludeFromFolderOverview) { return; } + const svg = ''; + if (yaml.includeTypes.includes('folder')) { + folderElement = childrenElement.createDiv({ + cls: 'tree-item nav-folder', }); - - const fileTitle = fileElement.createDiv({ - cls: 'tree-item-self is-clickable nav-file-title pointer-cursor', + folderTitle = folderElement.createDiv({ + cls: 'tree-item-self is-clickable nav-folder-title', attr: { 'data-path': child.path, 'draggable': 'true' }, }) - fileTitle.onclick = () => { - plugin.app.workspace.openLinkText(child.path, child.path, true); - } - - fileTitle.oncontextmenu = (e) => { - folderOverview.fileMenu(child, e); - } - - fileTitle.createDiv({ - cls: 'tree-item-inner nav-file-title-content', - text: child.basename, + folderTitle.draggable = true; + folderTitle.addEventListener('dragstart', e => { + const dragManager = plugin.app.dragManager; + const dragData = dragManager.dragFolder(e, child); + dragManager.onDragStart(e, dragData); + folderTitle?.classList.add('is-being-dragged'); }); - if (child.extension !== 'md' && !yaml.disableFileTag) { - fileTitle.createDiv({ - cls: 'nav-file-tag', - text: child.extension - }); + folderTitle.addEventListener('dragend', e => { + folderTitle?.classList.remove('is-being-dragged'); + }); + + folderTitle.addEventListener('dragover', e => { + e.preventDefault(); + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder) { + folderElement?.classList.add('is-being-dragged-over'); + plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.move-into-folder", { folder: child.name })); + } + }); + + folderTitle.addEventListener('dragleave', e => { + folderElement?.classList.remove('is-being-dragged-over'); + }); + + // handle the drop event + folderTitle.addEventListener('drop', e => { + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder) { + plugin.app.fileManager.renameFile(draggable.file, child.path + '/' + draggable.file.name); + } + }); + + folderTitle.oncontextmenu = (e) => { + folderOverview.folderMenu(child, e); } } - } -} - -function handleCollapseClick(el: HTMLElement, plugin: FolderNotesPlugin, yaml: yamlSettings, pathBlacklist: string[], sourcePath: string, folderOverview: FolderOverview, folder?: TFolder | undefined | null | TAbstractFile) { - console.log('el', el); - el.classList.toggle('is-collapsed'); - console.log('el', el); - if (el.classList.contains('is-collapsed')) { - if (!(folder instanceof TFolder)) return; - folder.collapsed = true; - el.parentElement?.parentElement?.childNodes[1]?.remove(); - } else { - if (!(folder instanceof TFolder)) return; - folder.collapsed = false; - const folderElement = el.parentElement?.parentElement; - 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); - addFiles(files, childrenElement, folderOverview); - } -} - -function createFolderEL(plugin: FolderNotesPlugin, child: TFolder, folderOverview: FolderOverview, childrenElement: HTMLElement) { - const pathBlacklist = folderOverview.pathBlacklist; - const source = folderOverview.source; - const folderNote = getFolderNote(plugin, child.path); - const yaml = folderOverview.yaml; - let folderTitle: HTMLElement | null = null; - let folderElement: HTMLElement | null = null; - - if (folderNote) { pathBlacklist.push(folderNote.path); } - const excludedFolder = getExcludedFolder(plugin, child.path, true); - if (excludedFolder?.excludeFromFolderOverview) { return; } - const svg = ''; - if (yaml.includeTypes.includes('folder')) { - folderElement = childrenElement.createDiv({ - cls: 'tree-item nav-folder', - }); - folderTitle = folderElement.createDiv({ - cls: 'tree-item-self is-clickable nav-folder-title', - attr: { - 'data-path': child.path, - 'draggable': 'true' - }, - }) - - folderTitle.oncontextmenu = (e) => { - folderOverview.folderMenu(child, e); - } - } - - if (!child.collapsed) { - if (yaml.includeTypes.includes('folder')) { - folderTitle?.classList.remove('is-collapsed'); - const childrenElement = folderElement?.createDiv({ cls: 'tree-item-children nav-folder-children' }); - if (childrenElement) { - addFiles(child.children, childrenElement, folderOverview); + if (!child.collapsed) { + if (yaml.includeTypes.includes('folder')) { + folderTitle?.classList.remove('is-collapsed'); + const childrenElement = folderElement?.createDiv({ cls: 'tree-item-children nav-folder-children' }); + if (childrenElement) { + this.addFiles(child.children, childrenElement, folderOverview); + } + } else { + this.addFiles(child.children, childrenElement, folderOverview); } } else { - addFiles(child.children, childrenElement, folderOverview); + folderTitle?.classList.add('is-collapsed'); } - } 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') } + if (folderNote) { folderTitle?.classList.add('has-folder-note') } + if (folderNote && child.children.length === 1 && yaml.disableCollapseIcon) { folderTitle?.classList.add('fn-has-no-files') } - const collapseIcon = folderTitle?.createDiv({ - cls: 'tree-item-icon collapse-icon nav-folder-collapse-indicator fn-folder-overview-collapse-icon', - }); + const collapseIcon = folderTitle?.createDiv({ + cls: 'tree-item-icon collapse-icon nav-folder-collapse-indicator fn-folder-overview-collapse-icon', + }); - if (child.collapsed) { - collapseIcon?.classList.add('is-collapsed'); - } - if (collapseIcon) { - collapseIcon.innerHTML = svg; - collapseIcon.onclick = () => { - handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + if (child.collapsed) { + collapseIcon?.classList.add('is-collapsed'); + } + if (collapseIcon) { + collapseIcon.innerHTML = svg; + collapseIcon.onclick = () => { + this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + } } - } - const folderTitleText = folderTitle?.createDiv({ - cls: 'tree-item-inner nav-folder-title-content', - text: child.name, - }); + const folderTitleText = folderTitle?.createDiv({ + cls: 'tree-item-inner nav-folder-title-content', + text: child.name, + }); - if (folderTitleText && !folderNote) { - folderTitleText.onclick = () => { - const collapseIcon = folderTitle?.querySelectorAll('.tree-item-icon')[0] as HTMLElement; - if (collapseIcon) { - handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + if (folderTitleText && !folderNote) { + folderTitleText.onclick = () => { + const collapseIcon = folderTitle?.querySelectorAll('.tree-item-icon')[0] as HTMLElement; + if (collapseIcon) { + this.handleCollapseClick(collapseIcon, plugin, yaml, pathBlacklist, source, folderOverview, child); + } } } } diff --git a/src/folderOverview/FolderOverview.ts b/src/folderOverview/FolderOverview.ts index 806c2c2..c11c18d 100644 --- a/src/folderOverview/FolderOverview.ts +++ b/src/folderOverview/FolderOverview.ts @@ -5,7 +5,7 @@ import { FolderOverviewSettings } from './ModalSettings'; import { getExcludedFolder } from '../ExcludeFolders/functions/folderFunctions'; import { getFolderPathFromString } from '../functions/utils'; import { getEl } from 'src/functions/styleFunctions'; -import { renderFileExplorer } from './FileExplorer'; +import { FileExplorerOverview } from './FileExplorer'; import { renderListOverview } from './ListStyle'; import NewFolderNameModal from 'src/modals/NewFolderName'; import { CustomEventEmitter } from 'src/events/EventEmitter'; @@ -46,7 +46,7 @@ export class FolderOverview { root: HTMLElement; listEl: HTMLUListElement; - private eventListeners: (() => void)[] = []; + eventListeners: (() => void)[] = []; constructor(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, source: string, el: HTMLElement) { this.emitter = new CustomEventEmitter(); let yaml: yamlSettings = parseYaml(source); @@ -216,11 +216,12 @@ export class FolderOverview { } else if (this.yaml.style === 'list') { renderListOverview(plugin, ctx, root, this.yaml, this.pathBlacklist, this); } else if (this.yaml.style === 'explorer') { + const fileExplorerOverview = new FileExplorerOverview(plugin, ctx, root, this.yaml, this.pathBlacklist, this); if (this.plugin.app.workspace.layoutReady) { - renderFileExplorer(plugin, ctx, root, this.yaml, this.pathBlacklist, this); + fileExplorerOverview.renderFileExplorer(); } else { this.plugin.app.workspace.onLayoutReady(() => { - renderFileExplorer(plugin, ctx, root, this.yaml, this.pathBlacklist, this); + fileExplorerOverview.renderFileExplorer(); }); } } @@ -256,12 +257,12 @@ export class FolderOverview { } filterFiles(files: TAbstractFile[], plugin: FolderNotesPlugin, sourceFolderPath: string, depth: number, pathBlacklist: string[]) { - return files.filter((file) => { + return files.filter(async (file) => { if (pathBlacklist.includes(file.path) && !this.yaml.showFolderNotes) { return false; } const folderPath = getFolderPathFromString(file.path); if (!folderPath.startsWith(sourceFolderPath) && sourceFolderPath !== '/') { return false; } if (file.path === this.sourceFilePath) { return false; } - const excludedFolder = getExcludedFolder(plugin, file.path, true); + const excludedFolder = await getExcludedFolder(plugin, file.path, true); if (excludedFolder?.excludeFromFolderOverview) { return false; } if ((file.path.split('/').length - sourceFolderPath.split('/').length) - 1 < depth) { return true; @@ -355,7 +356,7 @@ export class FolderOverview { fileMenu.addSeparator(); fileMenu.addItem((item) => { - item.setTitle('Rename'); + item.setTitle(window.i18next.t("plugins.file-explorer.menu-opt-rename")); item.setIcon('pencil'); item.onClick(async () => { plugin.app.fileManager.promptForFileRename(file) @@ -363,7 +364,7 @@ export class FolderOverview { }); fileMenu.addItem((item) => { - item.setTitle('Delete'); + item.setTitle(window.i18next.t("plugins.file-explorer.menu-opt-delete")); item.setIcon('trash'); item.dom.addClass('is-warning'); item.dom.setAttribute('data-section', 'danger') @@ -406,6 +407,13 @@ export class FolderOverview { plugin.app.workspace.trigger('file-menu', folderMenu, folder, "folder-overview-folder-context-menu", null); folderMenu.showAtPosition({ x: e.pageX, y: e.pageY }); } + + getElFromOverview(path: string): HTMLElement | null { + const el = this.listEl.querySelector(`[data-path="${path}"]`) as HTMLElement | null; + return el; + } + + } export async function updateYaml(plugin: FolderNotesPlugin, ctx: MarkdownPostProcessorContext, el: HTMLElement, yaml: yamlSettings) { diff --git a/src/functions/folderNoteFunctions.ts b/src/functions/folderNoteFunctions.ts index f0561ff..0024c08 100644 --- a/src/functions/folderNoteFunctions.ts +++ b/src/functions/folderNoteFunctions.ts @@ -62,12 +62,9 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st const folderNote = getFolderNote(plugin, folderPath) removeCSSClassFromEL(folderNote?.path, 'is-folder-note'); const folder = plugin.app.vault.getAbstractFileByPath(folderPath) as TFolder; - console.log('folderNote', folderNote); - console.log('fileName', fileName) if (!folderNote || folderNote.basename !== fileName) return; let count = 1; let newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split('.').pop()}`; - console.log(newName) while (count < 100 && plugin.app.vault.getAbstractFileByPath(newName)) { count++; newName = removeExtension(folderNote.path) + ` (${count}).${folderNote.path.split('.').pop()}`; @@ -90,7 +87,6 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st if (!existingNote) { let content = ''; if (extension !== '.md') { - console.log('create 1') if (plugin.settings.templatePath && folderNoteType.split('.').pop() == plugin.settings.templatePath.split('.').pop()) { const templateFile = plugin.app.vault.getAbstractFileByPath(plugin.settings.templatePath); if (templateFile instanceof TFile) { @@ -114,8 +110,7 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st content = '{}' } } - console.log('create 2') - console.log('path', path) + file = await plugin.app.vault.create(path, content); } else { file = existingNote; @@ -150,8 +145,8 @@ export async function createFolderNote(plugin: FolderNotesPlugin, folderPath: st const folder = plugin.app.vault.getAbstractFileByPath(folderPath); if (!(folder instanceof TFolder)) return; - addCSSClassToTitleEL(path, 'is-folder-note', true); - addCSSClassToTitleEL(folder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, path, 'is-folder-note', true); + addCSSClassToTitleEL(plugin, folder.path, 'has-folder-note'); } export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, folder: TFolder, folderNote?: TFile | null | TAbstractFile, skipConfirmation?: boolean) { @@ -196,8 +191,8 @@ export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, } await plugin.app.fileManager.renameFile(file, path); - addCSSClassToTitleEL(path, 'is-folder-note', true); - addCSSClassToTitleEL(folder.path, 'has-folder-note'); + addCSSClassToTitleEL(plugin, path, 'is-folder-note', true); + addCSSClassToTitleEL(plugin, folder.path, 'has-folder-note'); if (plugin.activeFolderDom) { plugin.activeFolderDom.removeClass('fn-is-active'); @@ -209,7 +204,7 @@ export async function turnIntoFolderNote(plugin: FolderNotesPlugin, file: TFile, } export async function tempDisableSync(plugin: FolderNotesPlugin, folder: TFolder): Promise<[excludedFolder: ExcludedFolder | undefined,excludedFolderExisted: boolean, disabledSync: boolean]> { - let excludedFolder = getExcludedFolder(plugin, folder.path, false); + let excludedFolder = await getExcludedFolder(plugin, folder.path, false); let excludedFolderExisted = true; let disabledSync = false; @@ -331,7 +326,6 @@ export function detachFolderNote(plugin: FolderNotesPlugin, file: TFile) { excludedFolder.excludeFromFolderOverview = false; excludedFolder.detached = true; excludedFolder.detachedFilePath = file.path; - console.log('excludedFolder', excludedFolder); addExcludedFolder(plugin, excludedFolder); } diff --git a/src/globals.d.ts b/src/globals.d.ts index 09d9599..7bc4834 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,17 +1,6 @@ import { Plugin, TAbstractFile, View, WorkspaceLeaf } from 'obsidian'; declare module 'obsidian' { - interface App { - internalPlugins: { - plugins: { - [pluginId: string]: Plugin & { - [pluginImplementations: string]: unknown; - }; - }; - enablePlugin: (id: string) => Promise; - disablePlugin: (id: string) => Promise; - }; - } interface Setting { createList: (list: ListComponent | ((list: ListComponent) => void)) => ListComponent; } diff --git a/src/main.ts b/src/main.ts index ad3fb07..f01f10b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,7 +15,7 @@ import './functions/ListComponent'; import { handleDelete } from './events/handleDelete'; import { addCSSClassToTitleEL, getEl, loadFileClasses, removeCSSClassFromEL } from './functions/styleFunctions'; import { getExcludedFolder } from './ExcludeFolders/functions/folderFunctions'; -import { ClipBoardManager } from 'obsidian-typings' +import { ClipBoardManager, FileExplorerView, InternalPlugin, InternalPluginName, InternalPlugins } from 'obsidian-typings' export default class FolderNotesPlugin extends Plugin { observer: MutationObserver; settings: FolderNotesSettings; @@ -28,6 +28,10 @@ export default class FolderNotesPlugin extends Plugin { hoverLinkTriggered = false; tabManager: TabManager; settingsOpened = false; + + private fileExplorerPlugin!: InternalPlugin; + private fileExplorerView!: FileExplorerView; + async onload() { console.log('loading folder notes plugin'); await this.loadSettings(); @@ -51,43 +55,7 @@ export default class FolderNotesPlugin extends Plugin { new Commands(this.app, this).registerCommands(); - this.app.workspace.onLayoutReady(() => { - if (this.settings.frontMatterTitle.enabled) { - this.fmtpHandler = new FrontMatterTitlePluginHandler(this); - } - this.tabManager = new TabManager(this); - this.tabManager.updateTabs(); - - const view = this.app.workspace.getLeavesOfType('markdown')[0]?.view; - if (!view) { return; } - const plugin = this; - // @ts-ignore - const originalHandleDragOver = view.editMode.clipboardManager.constructor.prototype.handleDragOver; - // @ts-ignore - view.editMode.clipboardManager.constructor.prototype.handleDragOver = function (evt, ...args) { - const { draggable } = plugin.app.dragManager; - if (draggable && draggable.file instanceof TFolder && getFolderNote(plugin, draggable.file.path)) { - plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.insert-link-here")); - } else { - originalHandleDragOver.call(this, evt, ...args); - } - }; - - // @ts-ignore - const originalHandleDrop = view.editMode.clipboardManager.constructor.prototype.handleDrop; - // @ts-ignore - view.editMode.clipboardManager.constructor.prototype.handleDrop = function (evt, ...args) { - const { draggable } = plugin.app.dragManager; - if (draggable && draggable.file instanceof TFolder && getFolderNote(plugin, draggable.file.path)) { - const folderNote = getFolderNote(plugin, draggable.file.path); - if (draggable?.type === "folder" && draggable.file instanceof TFolder && folderNote) { - draggable.file = folderNote; - draggable.type = "file"; - } - } - return originalHandleDrop.call(this, evt, ...args); - } - }); + this.app.workspace.onLayoutReady(this.onLayoutReady.bind(this)); await addObserver(this); @@ -166,6 +134,48 @@ export default class FolderNotesPlugin extends Plugin { } } + onLayoutReady() { + if (this.settings.frontMatterTitle.enabled) { + this.fmtpHandler = new FrontMatterTitlePluginHandler(this); + } + this.tabManager = new TabManager(this); + this.tabManager.updateTabs(); + + const view = this.app.workspace.getLeavesOfType('markdown')[0]?.view; + if (!view) { return; } + const plugin = this; + // @ts-ignore + const originalHandleDragOver = view.editMode.clipboardManager.constructor.prototype.handleDragOver; + // @ts-ignore + view.editMode.clipboardManager.constructor.prototype.handleDragOver = function (evt, ...args) { + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder && getFolderNote(plugin, draggable.file.path)) { + plugin.app.dragManager.setAction(window.i18next.t("interface.drag-and-drop.insert-link-here")); + } else { + originalHandleDragOver.call(this, evt, ...args); + } + }; + + // @ts-ignore + const originalHandleDrop = view.editMode.clipboardManager.constructor.prototype.handleDrop; + // @ts-ignore + view.editMode.clipboardManager.constructor.prototype.handleDrop = function (evt, ...args) { + const { draggable } = plugin.app.dragManager; + if (draggable && draggable.file instanceof TFolder && getFolderNote(plugin, draggable.file.path)) { + const folderNote = getFolderNote(plugin, draggable.file.path); + if (draggable?.type === "folder" && draggable.file instanceof TFolder && folderNote) { + draggable.file = folderNote; + draggable.type = "file"; + } + } + return originalHandleDrop.call(this, evt, ...args); + } + + const fileExplorerPluginInstance = this.app.internalPlugins.getEnabledPluginById(InternalPluginName.FileExplorer); + + + } + handleOverviewBlock(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) { const observer = new MutationObserver(() => { @@ -184,8 +194,16 @@ export default class FolderNotesPlugin extends Plugin { subtree: true, }); try { - const folderOverview = new FolderOverview(this, ctx, source, el); - folderOverview.create(this, parseYaml(source), el, ctx); + if (this.app.workspace.layoutReady) { + const folderOverview = new FolderOverview(this, ctx, source, el); + folderOverview.create(this, parseYaml(source), el, ctx); + } else { + this.app.workspace.onLayoutReady(() => { + console.log('layout ready'); + const folderOverview = new FolderOverview(this, ctx, source, el); + folderOverview.create(this, parseYaml(source), el, ctx); + }); + } } catch (e) { new Notice('Error creating folder overview (folder notes plugin) - check console for more details'); console.error(e); diff --git a/src/modals/ConfirmCreation.ts b/src/modals/ConfirmCreation.ts index 2f859b1..059142b 100644 --- a/src/modals/ConfirmCreation.ts +++ b/src/modals/ConfirmCreation.ts @@ -65,7 +65,7 @@ export default class ConfirmationModal extends Modal { const folders = this.app.vault.getAllLoadedFiles().filter((file) => file.parent instanceof TFolder); for (const folder of folders) { if (folder instanceof TFolder) { - const excludedFolder = getExcludedFolder(this.plugin, folder.path, true); + const excludedFolder = await getExcludedFolder(this.plugin, folder.path, true); if (excludedFolder) continue; if (folder.path === templateFolderPath) continue; const folderNote = getFolderNote(this.plugin, folder.path); diff --git a/src/modals/NewFolderName.ts b/src/modals/NewFolderName.ts index 073a4c3..5aeb047 100644 --- a/src/modals/NewFolderName.ts +++ b/src/modals/NewFolderName.ts @@ -22,7 +22,6 @@ export default class NewFolderNameModal extends Modal { this.modalEl.classList.add('mod-file-rename') const modalTitle = this.modalEl.querySelector('div.modal-title') - console.log(modalTitle) if (modalTitle) { modalTitle.textContent = 'Folder title' }