/** * 文件:progress-indicator.ts * 作用:进度指示和用户反馈管理 */ import { Notice } from 'obsidian'; export interface ProgressOptions { showProgress?: boolean; duration?: number; autoHide?: boolean; } class GlobalProgressManager { private static instance: GlobalProgressManager | null = null; private currentNotice: Notice | null = null; private startTime: number = 0; static getInstance(): GlobalProgressManager { if (!GlobalProgressManager.instance) { GlobalProgressManager.instance = new GlobalProgressManager(); } return GlobalProgressManager.instance; } start(message: string, options: ProgressOptions = {}): void { // 如果已有通知,先关闭 if (this.currentNotice) { this.currentNotice.hide(); } this.startTime = Date.now(); const { duration = 10000 } = options; // 默认10秒自动消失,防止卡住 this.currentNotice = new Notice(`🔄 ${message}...`, duration); } update(message: string, progress?: number): void { if (!this.currentNotice) return; const progressText = progress !== undefined ? ` (${Math.round(progress)}%)` : ''; this.currentNotice.setMessage(`🔄 ${message}${progressText}...`); } finish(message: string, success: boolean = true): void { if (this.currentNotice) { this.currentNotice.hide(); this.currentNotice = null; } const duration = Date.now() - this.startTime; const durationText = duration > 1000 ? ` (${(duration / 1000).toFixed(1)}s)` : ''; const icon = success ? '✅' : '❌'; new Notice(`${icon} ${message}${durationText}`, success ? 3000 : 5000); } error(message: string): void { if (this.currentNotice) { this.currentNotice.hide(); this.currentNotice = null; } const duration = Date.now() - this.startTime; const durationText = duration > 1000 ? ` (${(duration / 1000).toFixed(1)}s)` : ''; new Notice(`❌ ${message}${durationText}`, 5000); } hide(): void { if (this.currentNotice) { this.currentNotice.hide(); this.currentNotice = null; } } } export class ProgressIndicator { private manager = GlobalProgressManager.getInstance(); start(message: string, options: ProgressOptions = {}): void { this.manager.start(message, options); } update(message: string, progress?: number): void { this.manager.update(message, progress); } finish(message: string, success: boolean = true): void { this.manager.finish(message, success); } error(message: string): void { this.manager.error(message); } hide(): void { this.manager.hide(); } } export class BatchProgressIndicator { private currentProgress: ProgressIndicator | null = null; private totalItems: number = 0; private completedItems: number = 0; private failedItems: number = 0; start(totalItems: number, operation: string): void { this.totalItems = totalItems; this.completedItems = 0; this.failedItems = 0; this.currentProgress = new ProgressIndicator(); this.currentProgress.start(`${operation} (0/${totalItems})`); } updateItem(itemName: string, success: boolean = true): void { if (success) { this.completedItems++; } else { this.failedItems++; } const completed = this.completedItems + this.failedItems; const progress = (completed / this.totalItems) * 100; if (this.currentProgress) { this.currentProgress.update( `处理中: ${itemName} (${completed}/${this.totalItems})`, progress ); } } finish(operation: string): void { const successCount = this.completedItems; const failCount = this.failedItems; const total = this.totalItems; let message = `${operation}完成`; if (failCount === 0) { message += ` - 全部成功 (${successCount}/${total})`; } else { message += ` - 成功: ${successCount}, 失败: ${failCount}`; } if (this.currentProgress) { this.currentProgress.finish(message, failCount === 0); } } }