import { Plugin } from "obsidian"; export enum RecordingStatus { Idle = "idle", Recording = "recording", Paused = "paused", Processing = "processing", } export class StatusBar { plugin: Plugin; statusBarItem: HTMLElement | null = null; status: RecordingStatus = RecordingStatus.Idle; private listeners: Array<(status: RecordingStatus) => void> = []; private meterBars: HTMLElement[] = []; constructor(plugin: Plugin) { this.plugin = plugin; this.statusBarItem = this.plugin.addStatusBarItem(); this.updateStatusBarItem(); } onChange(listener: (status: RecordingStatus) => void): void { this.listeners.push(listener); } offChange(listener: (status: RecordingStatus) => void): void { this.listeners = this.listeners.filter((fn) => fn !== listener); } updateStatus(status: RecordingStatus) { this.status = status; this.updateStatusBarItem(); this.listeners.forEach((fn) => fn(status)); } updateInputLevel(level: number): void { if (this.status !== RecordingStatus.Recording) return; const clampedLevel = Math.max(0, Math.min(1, level)); const activeBars = Math.round(clampedLevel * this.meterBars.length); this.meterBars.forEach((bar, index) => { bar.toggleClass("nibbleai-meter-bar-active", index < activeBars); }); } updateStatusBarItem() { if (!this.statusBarItem) return; this.statusBarItem.empty(); this.statusBarItem.removeClass("nibbleai-status-recording"); this.statusBarItem.removeClass("nibbleai-status-paused"); this.statusBarItem.removeClass("nibbleai-status-processing"); this.statusBarItem.removeClass("nibbleai-status-idle"); this.meterBars = []; switch (this.status) { case RecordingStatus.Recording: this.statusBarItem.addClass("nibbleai-status-recording"); this.statusBarItem.createSpan({ text: "NibbleAI " }); this.createInputMeter(); break; case RecordingStatus.Paused: this.statusBarItem.addClass("nibbleai-status-paused"); this.statusBarItem.setText("NibbleAI Paused"); break; case RecordingStatus.Processing: this.statusBarItem.addClass("nibbleai-status-processing"); this.statusBarItem.setText("NibbleAI Processing..."); break; case RecordingStatus.Idle: default: this.statusBarItem.addClass("nibbleai-status-idle"); this.statusBarItem.setText("NibbleAI Idle"); break; } } private createInputMeter(): void { if (!this.statusBarItem) return; const meter = this.statusBarItem.createSpan({ cls: "nibbleai-input-meter", attr: { "aria-label": "Recording input level" }, }); for (let i = 0; i < 8; i++) { this.meterBars.push( meter.createSpan({ cls: "nibbleai-meter-bar" }) ); } } remove() { if (this.statusBarItem) { this.statusBarItem.remove(); } } }