Status-Bar: Live-Widget mit Klick-Pause
Zeigt Aufnahme/Pausiert-Status, Event-Zähler, Wort-Delta, Session-Dauer. Klick togglet Pause. Updates jede Sekunde. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
50af0eb802
commit
eb58de96fe
1 changed files with 67 additions and 0 deletions
67
src/ui/status-bar.ts
Normal file
67
src/ui/status-bar.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import type LogfirePlugin from '../main';
|
||||||
|
|
||||||
|
export class StatusBar {
|
||||||
|
private el: HTMLElement;
|
||||||
|
private intervalId: ReturnType<typeof setInterval> | null = null;
|
||||||
|
private wordsAdded = 0;
|
||||||
|
private eventCount = 0;
|
||||||
|
|
||||||
|
constructor(private plugin: LogfirePlugin) {
|
||||||
|
this.el = plugin.addStatusBarItem();
|
||||||
|
this.el.addClass('logfire-status-bar');
|
||||||
|
this.el.addEventListener('click', () => this.onClick());
|
||||||
|
}
|
||||||
|
|
||||||
|
start(): void {
|
||||||
|
this.plugin.eventBus.onEvent('*', (event) => {
|
||||||
|
this.eventCount++;
|
||||||
|
const wa = event.payload.wordsAdded;
|
||||||
|
if (typeof wa === 'number') {
|
||||||
|
this.wordsAdded += wa;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
this.intervalId = setInterval(() => this.update(), 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy(): void {
|
||||||
|
if (this.intervalId !== null) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
this.intervalId = null;
|
||||||
|
}
|
||||||
|
this.el.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
private update(): void {
|
||||||
|
const paused = this.plugin.isPaused();
|
||||||
|
const indicator = paused ? '\u23F8' : '\u{1F534}';
|
||||||
|
const state = paused ? 'Pausiert' : 'Aufnahme';
|
||||||
|
const duration = this.formatDuration(this.plugin.sessionManager.sessionDurationMs);
|
||||||
|
const words = this.wordsAdded > 0 ? ` | +${this.wordsAdded}w` : '';
|
||||||
|
|
||||||
|
this.el.textContent = `${indicator} ${state} | ${this.eventCount} Events${words} | ${duration}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onClick(): void {
|
||||||
|
if (this.plugin.isPaused()) {
|
||||||
|
this.plugin.resume();
|
||||||
|
} else {
|
||||||
|
this.plugin.pause();
|
||||||
|
}
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private formatDuration(ms: number): string {
|
||||||
|
if (ms <= 0) return '0:00';
|
||||||
|
const totalSeconds = Math.floor(ms / 1000);
|
||||||
|
const hours = Math.floor(totalSeconds / 3600);
|
||||||
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
||||||
|
const seconds = totalSeconds % 60;
|
||||||
|
|
||||||
|
if (hours > 0) {
|
||||||
|
return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
return `${minutes}:${String(seconds).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue