Files
note2any/src/core/progress-indicator.ts
2025-10-16 18:10:27 +08:00

151 lines
4.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 文件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);
}
}
}