From 64c2e0f88f6f6f433680c8d202367cd4f42c363f Mon Sep 17 00:00:00 2001 From: Netajam Date: Thu, 10 Apr 2025 10:43:50 +0200 Subject: [PATCH] v 1.0.6 --- src/commands.ts | 42 +++++++++++----------- src/main.ts | 31 +++++++++------- src/settings.ts | 9 ----- src/typings/obsidian.d.ts | 16 ++++++--- src/ui/FolderExclusionModal.ts | 2 +- src/uidUtils.ts | 3 -- styles.css | 65 +++++++++++++++++++++++++++++++--- tsconfig.json | 8 ++++- 8 files changed, 121 insertions(+), 55 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index afbe5b7..14de23b 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,4 +1,4 @@ -import { Editor, MarkdownView, TFile, TFolder, Notice, normalizePath, WorkspaceLeaf } from 'obsidian'; +import { Editor, MarkdownView, TFile, TFolder, Notice, normalizePath, WorkspaceLeaf, FileExplorerView } from 'obsidian'; import UIDGenerator from './main'; import * as uidUtils from './uidUtils'; @@ -126,7 +126,6 @@ export function handleCopyTitleUid(plugin: UIDGenerator, specificFile?: TFile): /** Logic for Folder Context Menu Action */ export async function handleCopyTitlesAndUidsFromFolder(plugin: UIDGenerator, folder: TFolder): Promise { - console.log(`[UIDGenerator] Copying titles+${plugin.settings.uidKey}s for folder: ${folder.path}`); const markdownFiles = plugin.app.vault.getMarkdownFiles(); const filesInFolder: TFile[] = []; const targetPath = folder.path; @@ -182,8 +181,6 @@ export async function handleCopyTitlesAndUidsForMultipleFiles(plugin: UIDGenerat return; } - console.log(`[UIDGenerator] Copying titles+${plugin.settings.uidKey}s for ${files.length} selected files via context menu.`); - let outputLines: string[] = []; let filesWithUidCount = 0; const formatExists = plugin.settings.copyFormatString; @@ -213,23 +210,34 @@ export async function handleCopyTitlesAndUidsForMultipleFiles(plugin: UIDGenerat /** Logic for Command Palette: Copy titles+UIDs for selected files in File Explorer */ export async function handleCopyTitlesAndUidsForSelection(plugin: UIDGenerator): Promise { - // Find the active File Explorer leaf/view - const fileExplorerLeaf = plugin.app.workspace.getLeavesOfType('file-explorer') - .find(leaf => (leaf.view as any).selectedFiles && plugin.app.workspace.activeLeaf === leaf); + // 1. Find the active File Explorer leaf more reliably + let fileExplorerLeaf: WorkspaceLeaf | undefined = undefined; + const explorerLeaves = plugin.app.workspace.getLeavesOfType('file-explorer'); + if (explorerLeaves.length > 0) { + // Prefer the active leaf if it's a file explorer + if (plugin.app.workspace.activeLeaf && plugin.app.workspace.activeLeaf.view.getViewType() === 'file-explorer') { + fileExplorerLeaf = plugin.app.workspace.activeLeaf; + } else { + fileExplorerLeaf = explorerLeaves[0]; + } + } - if (!fileExplorerLeaf || !(fileExplorerLeaf.view as any).selectedFiles) { - new Notice("No active file explorer with selected files found."); + if (!fileExplorerLeaf) { + new Notice("No active file explorer found."); return; } - // Access selected files - const selectedPaths: string[] = (fileExplorerLeaf.view as any).selectedFiles || []; - - if (selectedPaths.length === 0) { + // 2. Assert the view type and check for selectedFiles property + const view = fileExplorerLeaf.view as FileExplorerView; + if (!view || !view.selectedFiles || view.selectedFiles.length === 0) { new Notice("No files selected in the file explorer."); return; } + // 3. Get the selected paths + const selectedPaths: string[] = view.selectedFiles; + + // 4. Filter for Markdown files const filesToProcess: TFile[] = []; for (const path of selectedPaths) { const file = plugin.app.vault.getAbstractFileByPath(path); @@ -243,7 +251,7 @@ export async function handleCopyTitlesAndUidsForSelection(plugin: UIDGenerator): return; } - // Delegate to the same logic used by the context menu + // 5. Delegate to the multi-file handler (no changes needed here) await handleCopyTitlesAndUidsForMultipleFiles(plugin, filesToProcess); } @@ -256,7 +264,6 @@ export async function handleClearUIDsInFolder(plugin: UIDGenerator, folderPath: const folder = plugin.app.vault.getAbstractFileByPath(normalizedFolderPath); if (!folder || !(folder instanceof TFolder)) { new Notice(`Folder not found or path is not a folder: ${folderPath}`); return; } - console.log(`[UIDGenerator] Starting UID clearing process for folder: ${folder.path} using key "${plugin.settings.uidKey}"`); new Notice(`Clearing ${plugin.settings.uidKey}s in "${folder.name}"... This may take a moment.`); const markdownFiles = plugin.app.vault.getMarkdownFiles(); @@ -275,7 +282,6 @@ export async function handleClearUIDsInFolder(plugin: UIDGenerator, folderPath: return; } - console.log(`[UIDGenerator] Found ${filesToProcess.length} markdown files to process.`); let clearedCount = 0; let errorCount = 0; @@ -293,7 +299,6 @@ export async function handleClearUIDsInFolder(plugin: UIDGenerator, folderPath: message += ` Encountered ${errorCount} errors (check console).`; } new Notice(message, 10000); - console.log(`[UIDGenerator] UID clearing finished. Removed: ${clearedCount}, Errors: ${errorCount}`); } @@ -327,7 +332,6 @@ export async function handleAutoGenerateUid(plugin: UIDGenerator, file: TFile | } // Generate and set - console.log(`[UIDGenerator] Auto-generating ${plugin.settings.uidKey} for: ${file.path}`); const newUid = uidUtils.generateUID(); await uidUtils.setUID(plugin, file, newUid, false); } @@ -347,7 +351,6 @@ export async function handleAddMissingUidsInScope(plugin: UIDGenerator): Promise const noticeMessage = `Processing ${totalFiles} files for missing UIDs...`; const notice = new Notice(noticeMessage, 0); // Show notice indefinitely until updated/hidden - console.log(`[UIDGenerator] Starting bulk check for missing UIDs. Scope: ${plugin.settings.autoGenerationScope}.`); try { // Wrap the loop for final notice update for (let i = 0; i < totalFiles; i++) { @@ -422,6 +425,5 @@ export async function handleAddMissingUidsInScope(plugin: UIDGenerator): Promise } new Notice(summary, 10000 + errorCount * 100); // Show longer if errors - console.log(`[UIDGenerator] ${summary.replace(/\n- /g, ', ')}`); } } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 61267b9..f2e6cee 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,7 @@ import { App, Editor, MarkdownView, Notice, Plugin, TFile, TFolder, - debounce, Menu, TAbstractFile, WorkspaceLeaf + debounce, Menu, TAbstractFile, WorkspaceLeaf, + FileExplorerView } from 'obsidian'; import { UIDGeneratorSettings, DEFAULT_SETTINGS, UIDSettingTab } from './settings'; import * as commands from './commands'; @@ -10,7 +11,6 @@ export default class UIDGenerator extends Plugin { settings: UIDGeneratorSettings; async onload() { - console.log('Loading UID Generator Plugin v7 (files-menu)'); await this.loadSettings(); // --- Ribbon Icon --- @@ -98,16 +98,24 @@ export default class UIDGenerator extends Plugin { name: `Copy titles+${this.settings.uidKey}s for selected files`, checkCallback: (checking: boolean): boolean | void => { const fileExplorerLeaf = this.app.workspace.getLeavesOfType('file-explorer') - ?.find(leaf => (leaf.view as any).selectedFiles && this.app.workspace.activeLeaf === leaf); + ?.find(leaf => leaf.view.getViewType() === 'file-explorer' && this.app.workspace.activeLeaf === leaf); // More robust check - let markdownSelected = false; - if (fileExplorerLeaf) { - const selectedPaths: string[] = (fileExplorerLeaf.view as any).selectedFiles || []; - markdownSelected = selectedPaths.some(path => { - const file = this.app.vault.getAbstractFileByPath(path); - return file instanceof TFile && file.extension === 'md'; - }); - } + + let markdownSelected = false; + if (fileExplorerLeaf) { + // Use the augmented interface with a type assertion + const view = fileExplorerLeaf.view as FileExplorerView; // <-- Use the interface + const selectedPaths: string[] = view.selectedFiles || []; // <-- Access via typed view + + // Check if at least one selected file is markdown + markdownSelected = selectedPaths.some(path => { + // 'this' refers to the Plugin instance in main.ts + // 'plugin' refers to the Plugin instance in commands.ts + // Make sure to use the correct variable (this or plugin) depending on the file + const file = this.app.vault.getAbstractFileByPath(path); // Or plugin.app.vault... + return file instanceof TFile && file.extension === 'md'; + }); + } const canRun = !!fileExplorerLeaf && markdownSelected; @@ -166,7 +174,6 @@ export default class UIDGenerator extends Plugin { } onunload() { - console.log('Unloading UID Generator Plugin v7 (files-menu)'); } // --- Settings Management --- diff --git a/src/settings.ts b/src/settings.ts index c38e0ab..25d0a46 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -118,23 +118,15 @@ export class UIDSettingTab extends PluginSettingTab { new FolderExclusionModal(this.app, this.plugin, () => this.display()).open(); })); - // Display the current list of excluded folders (read-only in this view) const exclusionListEl = containerEl.createEl('ul', { cls: 'uid-exclusion-list' }); if (this.plugin.settings.autoGenerationExclusions.length > 0) { - // Sort before displaying for consistency const sortedExclusions = [...this.plugin.settings.autoGenerationExclusions].sort(); sortedExclusions.forEach(folderPath => { exclusionListEl.createEl('li', { text: folderPath }); }); } else { - // Display message if no folders are excluded exclusionListEl.createEl('li', { text: 'No folders excluded.' }); } - // Basic styling for the list - exclusionListEl.style.marginTop = '5px'; - exclusionListEl.style.marginBottom = '15px'; - exclusionListEl.style.paddingLeft = '20px'; - exclusionListEl.style.listStyle = 'none'; // Or 'disc', 'circle' etc. } new Setting(containerEl) @@ -227,7 +219,6 @@ export class UIDSettingTab extends PluginSettingTab { autoGenWasOn = true; this.plugin.settings.autoGenerateUid = false; await this.plugin.saveSettings(); - console.log("[UIDGenerator] Automatic UID generation temporarily disabled due to manual clear action."); } try { diff --git a/src/typings/obsidian.d.ts b/src/typings/obsidian.d.ts index fd1995f..7cac508 100644 --- a/src/typings/obsidian.d.ts +++ b/src/typings/obsidian.d.ts @@ -1,5 +1,5 @@ -// src/obsidian.d.ts -import 'obsidian'; +// src/typings/obsidian.d.ts +import 'obsidian'; declare module 'obsidian' { interface Workspace { @@ -7,11 +7,19 @@ declare module 'obsidian' { name: 'files-menu', callback: ( menu: Menu, - files: TAbstractFile[], + files: TAbstractFile[], // Note: it's an array source: string, leaf?: WorkspaceLeaf ) => any, ctx?: any ): EventRef; } -} \ No newline at end of file + + + interface FileExplorerView extends View { + selectedFiles?: string[]; + } + + + +} diff --git a/src/ui/FolderExclusionModal.ts b/src/ui/FolderExclusionModal.ts index b9b9ba1..3a2fd08 100644 --- a/src/ui/FolderExclusionModal.ts +++ b/src/ui/FolderExclusionModal.ts @@ -1,4 +1,4 @@ -import { App, Modal, TFolder, Setting, debounce } from 'obsidian'; +import { App, Modal, TFolder, debounce } from 'obsidian'; import UIDGenerator from '../main'; export class FolderExclusionModal extends Modal { diff --git a/src/uidUtils.ts b/src/uidUtils.ts index aa40e98..85ac152 100644 --- a/src/uidUtils.ts +++ b/src/uidUtils.ts @@ -59,7 +59,6 @@ export async function setUID(plugin: UIDGenerator, file: TFile, uid: string, ove initialUidExists = currentUid !== undefined && currentUid !== null && currentUid !== ''; // Check before potential modification if (initialUidExists && !overwrite) { - console.log(`[UIDGenerator] ${key} already exists for ${file.path}, not overwriting.`); uidWasSetOrOverwritten = false; // Explicitly false return; // Exit processor } @@ -83,7 +82,6 @@ export async function setUID(plugin: UIDGenerator, file: TFile, uid: string, ove if (uidWasSetOrOverwritten) { // Determine action based on initial state and overwrite flag const action = initialUidExists && overwrite ? 'Overwrote' : 'Set'; - console.log(`[UIDGenerator] ${action} ${key} for ${file.path}.`); } return uidWasSetOrOverwritten; @@ -112,7 +110,6 @@ export async function removeUID(plugin: UIDGenerator, file: TFile): Promise