diff --git a/src/main.ts b/src/main.ts index 6e03b6a..86bd5b3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -43,8 +43,9 @@ import { patchOpenFile, unpatchOpenFile, addKeyListeners, removeKeyListeners } f import { patchFilemanager, unpatchFilemanager } from 'patchFileManager'; import { EditorSelection } from '@codemirror/state'; -import { patchImportFunctions, unpatchImportFunctions } from "patchImportFunctions"; +import { patchImportFunctions, unpatchImportFunctions } from "patchImportFunctions"; +import { patchFileExplorer, unpatchFileExplorer } from "patchFileExplorer"; import { monkeyPatchConsole, unpatchConsole } from "patchConsole"; // Default plugin settings @@ -150,6 +151,7 @@ export default class ImportAttachments extends Plugin { folderElements.forEach((folder: Element) => { if (folder.parentNode && folder.parentNode instanceof HTMLElement) { + // console.log(folder); if (this.settings.hideAttachmentFolders) { folder.parentNode.classList.add('import-plugin-hidden'); } @@ -236,7 +238,7 @@ export default class ImportAttachments extends Plugin { this.addSettingTab(new ImportAttachmentsSettingTab(this.app, this)); // Set up the mutation observer for hiding folders - this.setupObserver(); + // this.setupObserver(); // Monkey patches of the openFile function if (Platform.isDesktopApp) { @@ -832,12 +834,31 @@ export default class ImportAttachments extends Plugin { } async openAttachmentsFolder() { -/* + + // Monkey-path file explorer to hide attachment folders + patchFileExplorer(this); + + return; + + // Get the file explorer plugin const fileExplorer = this.app.internalPlugins.getPluginById('file-explorer'); // Check if the plugin is loaded and enabled if (fileExplorer) { + + const leaves = this.app.workspace.getLeavesOfType('file-explorer'); + for (const leaf of leaves) { + console.log(leaf); + const viewInstance = leaf.view; + if (viewInstance) { + + + break; + } + } + + console.log(fileExplorer); const viewFactory = fileExplorer.views['file-explorer']; // Create a new instance of the view to identify its class @@ -847,41 +868,30 @@ export default class ImportAttachments extends Plugin { // Identify the class used in createItemDom const viewClass = viewInstance.constructor; - // Find the JJ class by exploring the prototype - // console.log('viewClass:', viewClass.prototype.createItemDom); + // Log the createItemDom method to inspect it + console.log('viewClass createFolderDom:', viewClass.prototype.createFolderDom); - // Use a dummy instance to explore properties (assuming createItemDom creates JJ instances) - const dummyItem = viewClass.prototype.createItemDom.call(viewInstance, {}); // Pass an empty object as an argument - - // Log the dummy item to inspect it - // console.log('dummyItem:', dummyItem); - - // Get the JJ class from the dummy item - const JJClass = dummyItem.constructor; - - // Log the JJ class to ensure it's identified correctly - console.log('JJClass:', JJClass.prototype.updateTitle); - - // Patch the JJ class prototype - if (JJClass.prototype.updateTitle) { - const originalUpdateTitle = JJClass.prototype.updateTitle; - JJClass.prototype.updateTitle = function(...args: any) { - console.log('Custom behavior before updateTitle'); - console.log(args); - const result = originalUpdateTitle.apply(this, args); - console.log('Custom behavior after updateTitle'); + // Patch the createItemDom method in viewClass prototype + if (viewClass.prototype.createFolderDom) { + const originalCreateFolderDom = viewClass.prototype.createFolderDom; + viewClass.prototype.createFolderDom = function(...args) { + console.log('Custom behavior before createFolderDom'); + const result = originalCreateFolderDom.apply(this, args); + console.log(result); + console.log('Custom behavior after createFolderDom'); return result; }; - console.log('PATCHED'); + console.log('createFolderDom PATCHED'); } else { - console.error('updateTitle method not found on JJ prototype'); + console.error('createFolderDom method not found on viewClass prototype'); } + + } else { console.error('File Explorer plugin not found or not enabled'); } - return; -*/ + const md_active_file = this.app.workspace.getActiveFile(); @@ -906,10 +916,6 @@ export default class ImportAttachments extends Plugin { const absAttachmentsFolderPath = Utils.joinPaths(this.vaultPath,attachmentsFolderPath); - if(!absAttachmentsFolderPath) return; - - // TODO: Ask whether to create an Attachment folder - // Open the folder in the system's default file explorer // eslint-disable-next-line @typescript-eslint/no-var-requires const { shell } = require('electron'); diff --git a/src/patchFileExplorer.ts b/src/patchFileExplorer.ts new file mode 100644 index 0000000..73c832d --- /dev/null +++ b/src/patchFileExplorer.ts @@ -0,0 +1,152 @@ +// patchImportFunctions.ts + +/* eslint-disable @typescript-eslint/no-inferrable-types */ + +import { TFolder,WorkspaceLeaf, View, FileExplorerItem } from 'obsidian'; +import ImportAttachments from 'main'; + +// Define a type for the view class with the required methods +interface FileExplorerView extends View { + createFolderDom(folder: TFolder): FileExplorerItem; +} + +// Save a reference to the original method for the monkey patch +let originalCreateFolderDom: ((folder: TFolder) => FileExplorerItem) | null = null; +let viewClass: { new(leaf: WorkspaceLeaf): FileExplorerView } | null = null; + +function unpatchFileExplorer() { + if (originalCreateFolderDom && viewClass) { + viewClass.prototype.createFolderDom = originalCreateFolderDom; + originalCreateFolderDom = null; + } +} + +function matchesPatternWithHolder(plugin: ImportAttachments, filePath: string): boolean { + // Check if filePath starts with startsWidth or contains /startsWidth + const startsWithMatch = filePath.startsWith(plugin.folderPathStartsWith) || filePath.includes(`/${plugin.folderPathStartsWith}`); + + // Check if filePath ends with endsWidth + const endsWithMatch = filePath.endsWith(plugin.folderPathEndsWith); + + // Return true only if both conditions are met + return startsWithMatch && endsWithMatch; +} + +function matchesPatternWithoutHolder(plugin: ImportAttachments, filePath: string): boolean { + const folderName = plugin.settings.folderPath; + return filePath.endsWith(`/${folderName}`) || filePath === folderName; +} + +function patchFileExplorer(plugin: ImportAttachments) { + if (originalCreateFolderDom) { return; } + + const leaves = plugin.app.workspace.getLeavesOfType('file-explorer'); + for (const leaf of leaves) { + const viewInstance = leaf.view as FileExplorerView; + originalCreateFolderDom = viewInstance.constructor.prototype.createFolderDom; + viewClass = viewInstance.constructor as { new(leaf: WorkspaceLeaf): FileExplorerView }; + break; + } + + if (!viewClass) { + console.error("file-explorer plugin could not be patched."); + return; + } + + viewClass.prototype.createFolderDom = function(this: FileExplorerView, folder: TFolder): unknown { + if(!originalCreateFolderDom) { + console.error('Something went wrong in patching file-explorer plugin.') + return; + } + + const result = originalCreateFolderDom.apply(this, [folder]); + console.log(result); + if(result) { + const folderName = result.file.name; + let hidden = false; + if (plugin.settings.folderPath.includes("${notename}") && matchesPatternWithHolder(plugin,folderName)) { + console.log("FOUND",folderName); + hidden = true; + + } else if (matchesPatternWithoutHolder(plugin,folderName)) { + console.log("FOUND",folderName); + hidden = true; + } + + if(hidden) result.el.toggleClass("import-plugin-hidden",true); + + console.log(result.constructor); + console.log('Custom behavior after createFolderDom'); + } + return result; + }; + + console.log("PATCHED"); +} + +export { patchFileExplorer, unpatchFileExplorer }; + +/* + function matchesPatternWithHolder(filePath: string): boolean { + // Check if filePath starts with startsWidth or contains /startsWidth + const startsWithMatch = filePath.startsWith(plugin.folderPathStartsWith) || filePath.includes(`/${plugin.folderPathStartsWith}`); + + // Check if filePath ends with endsWidth + const endsWithMatch = filePath.endsWith(plugin.folderPathEndsWith); + + // Return true only if both conditions are met + return startsWithMatch && endsWithMatch; + } + + function matchesPatternWithoutHolder(filePath: string): boolean { + const folderName = plugin.settings.folderPath; + return filePath.endsWith(`/${folderName}`) || filePath === folderName; + } + + Vault.prototype.onChange = function (this: Vault, eventType: string, filePath: string, oldPath?: string, stat?: FileStats) { + if (!originalOnChange) { + throw new Error("Could not execute the original onChange function."); + } + + // const fileExplorerPlugin = plugin.app.internalPlugins.getPluginById('file-explorer'); + + // if(filePath.endsWith('.xyz')) { + // // console.log("XYZ:",eventType); + // // console.log(originalOnChange); + // originalOnChange.call(this, eventType, filePath, oldPath, stat); + // return; + // } + + // if(filePath.endsWith('.md')) { + // // console.log("MD:",eventType); + // return; + // } + + if (eventType === 'folder-created') { + const placeholder = "${notename}"; + + if (plugin.settings.folderPath.includes(placeholder) && matchesPatternWithHolder(filePath)) { + // console.log("1",filePath) + // console.log(TFolder); + + // Handle folder creation event manually + const newFolder = new TFolder(this, filePath); + this.fileMap[filePath] = newFolder; + // debugger + this.addChild(newFolder); + + this.trigger("create", this.fileMap[filePath]); + return; + } else if (matchesPatternWithoutHolder(filePath)) { + console.log("2",filePath) + } + } + + originalOnChange.call(this, eventType, filePath, oldPath, stat); + }; + + // const fileExplorer = plugin.app.internalPlugins.getPluginById('file-explorer'); + // const xyz = fileExplorer.views['file-explorer'] + // console.log(xyz); + + */ \ No newline at end of file diff --git a/src/patchImportFunctions.ts b/src/patchImportFunctions.ts index 29943bb..89d7c5c 100644 --- a/src/patchImportFunctions.ts +++ b/src/patchImportFunctions.ts @@ -8,7 +8,6 @@ import ImportAttachments from 'main'; // Save a reference to the original method for the monkey patch let originalGetAvailablePathForAttachments: ((fileName: string, extension: string, currentFile: TFile | null) => Promise) | null = null; let originalSaveAttachment: ((fileName: string, fileExtension: string, fileData: ArrayBuffer) => Promise) | null = null; -let originalOnChange: ((eventType: string, filePath: string, oldPath?: string, stat?: FileStats) => void) | null = null; let data: ArrayBuffer | null = null; function unpatchImportFunctions() { @@ -21,11 +20,6 @@ function unpatchImportFunctions() { App.prototype.saveAttachment = originalSaveAttachment; originalSaveAttachment = null; } - - if(originalOnChange) { - Vault.prototype.onChange = originalOnChange; - originalOnChange = null; - } } function patchImportFunctions(plugin: ImportAttachments) { @@ -79,12 +73,13 @@ function patchImportFunctions(plugin: ImportAttachments) { return newAttachmentFile; } - return; - + /* if (!originalOnChange) { originalOnChange = Vault.prototype.onChange; } + */ + /* function matchesPatternWithHolder(filePath: string): boolean { // Check if filePath starts with startsWidth or contains /startsWidth const startsWithMatch = filePath.startsWith(plugin.folderPathStartsWith) || filePath.includes(`/${plugin.folderPathStartsWith}`); @@ -108,44 +103,46 @@ function patchImportFunctions(plugin: ImportAttachments) { // const fileExplorerPlugin = plugin.app.internalPlugins.getPluginById('file-explorer'); - if(filePath.endsWith('.xyz')) { - // console.log("XYZ:",eventType); - // console.log(originalOnChange); - originalOnChange.call(this, eventType, filePath, oldPath, stat); - return; - } - - if(filePath.endsWith('.md')) { - // console.log("MD:",eventType); - return; - } - - // if (eventType === 'folder-created') { - // const placeholder = "${notename}"; - - // if (plugin.settings.folderPath.includes(placeholder) && matchesPatternWithHolder(filePath)) { - // // console.log("1",filePath) - // // console.log(TFolder); - - // // Handle folder creation event manually - // const newFolder = new TFolder(this, filePath); - // this.fileMap[filePath] = newFolder; - // // debugger - // this.addChild(newFolder); - - // this.trigger("create", this.fileMap[filePath]); - // return; - // } else if (matchesPatternWithoutHolder(filePath)) { - // console.log("2",filePath) - // } + // if(filePath.endsWith('.xyz')) { + // // console.log("XYZ:",eventType); + // // console.log(originalOnChange); + // originalOnChange.call(this, eventType, filePath, oldPath, stat); + // return; // } + // if(filePath.endsWith('.md')) { + // // console.log("MD:",eventType); + // return; + // } + + if (eventType === 'folder-created') { + const placeholder = "${notename}"; + + if (plugin.settings.folderPath.includes(placeholder) && matchesPatternWithHolder(filePath)) { + // console.log("1",filePath) + // console.log(TFolder); + + // Handle folder creation event manually + const newFolder = new TFolder(this, filePath); + this.fileMap[filePath] = newFolder; + // debugger + this.addChild(newFolder); + + this.trigger("create", this.fileMap[filePath]); + return; + } else if (matchesPatternWithoutHolder(filePath)) { + console.log("2",filePath) + } + } + originalOnChange.call(this, eventType, filePath, oldPath, stat); }; // const fileExplorer = plugin.app.internalPlugins.getPluginById('file-explorer'); // const xyz = fileExplorer.views['file-explorer'] // console.log(xyz); + + */ } export { patchImportFunctions, unpatchImportFunctions }; diff --git a/src/types/obsidian-augment.d.ts b/src/types/obsidian-augment.d.ts index 93d1a27..b9442b6 100644 --- a/src/types/obsidian-augment.d.ts +++ b/src/types/obsidian-augment.d.ts @@ -4,31 +4,44 @@ import 'obsidian'; import { EditorView } from '@codemirror/view'; declare module 'obsidian' { - interface App { - openWithDefaultApp(filepath: string): Promise; - saveAttachment(fileName: string, fileExtension: string, fileData: ArrayBuffer): Promise; - } + interface App { + openWithDefaultApp(filepath: string): Promise; + saveAttachment(fileName: string, fileExtension: string, fileData: ArrayBuffer): Promise; + } - interface Vault { - getConfig(configName: string): unknown; - getAvailablePathForAttachments(fileName: string, extension: string, currentFile: TFile | null): Promise; - onChange(eventType: string, filePath: string, oldPath?: string, stat?: FileStats): void; - } + interface Vault { + getConfig(configName: string): unknown; + getAvailablePathForAttachments(fileName: string, extension: string, currentFile: TFile | null): Promise; + onChange(eventType: string, filePath: string, oldPath?: string, stat?: FileStats): void; + } - interface MenuItem { - dom: HTMLElement; - callback: () => void; - } + interface MenuItem { + dom: HTMLElement; + callback: () => void; + } - interface Menu { - items: MenuItem[]; - } + interface Menu { + items: MenuItem[]; + } - interface FileManager { - promptForDeletion(file: TAbstractFile): Promise; - } + interface FileManager { + promptForDeletion(file: TAbstractFile): Promise; + } + + interface Editor { + cm: EditorView; + } + + interface FileExplorerItem { + el: HTMLDivElement; + selfEl: HTMLDivElement; + innerEl: HTMLDivElement; + coverEl: HTMLDivElement; + childrenEl: HTMLDivElement; + collapseEl: HTMLDivElement; + collapsed: boolean; + collapsible: boolean; + file: TFile; + } - interface Editor { - cm: EditorView; - } } diff --git a/styles/styles.css b/styles/styles.css index 634fb3c..a440c32 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -1,15 +1,7 @@ -.import-plugin-hidden { - height: 0; - overflow: hidden; +.nav-files-container:not(.import-plugin-hidden) .import-plugin-hidden { + display: none; } -/* -.nav-files-container:not(.show-unsupported) .is-unsupported { - text-color: red; - display: block !important; -} -*/ - .import-plugin table { width: 100%; border-collapse: collapse;