feat: add animated token counter to status bar

Implement smooth ease-out animation when updating input/output token counts in the status bar, replacing instant updates with a 1-second transition for better visual feedback.
This commit is contained in:
Andrew Beal 2025-10-17 22:40:12 +01:00
parent 47af43fe1f
commit 301a95befb
2 changed files with 49 additions and 1 deletions

View file

@ -139,7 +139,7 @@ export class ChatService {
}
public setStatusBarTokens(inputTokens: number, outputTokens: number): void {
this.statusBarService.setStatusBarMessage(`Input Tokens: ${inputTokens} / Output Tokens: ${outputTokens}`);
this.statusBarService.animateTokens(inputTokens, outputTokens);
}
private async streamRequestResponse(

View file

@ -7,6 +7,9 @@ export class StatusBarService {
private readonly plugin: AIAgentPlugin;
private statusBarItem: HTMLElement | null;
private currentInputTokens: number = 0;
private currentOutputTokens: number = 0;
private animationFrame: number | null = null;
public constructor() {
this.plugin = Resolve<AIAgentPlugin>(Services.AIAgentPlugin);
@ -21,7 +24,52 @@ export class StatusBarService {
this.statusBarItem?.createEl("span", { text: message });
}
public animateTokens(targetInputTokens: number, targetOutputTokens: number) {
// Cancel any ongoing animation
if (this.animationFrame !== null) {
cancelAnimationFrame(this.animationFrame);
}
const startInputTokens = this.currentInputTokens;
const startOutputTokens = this.currentOutputTokens;
const startTime = performance.now();
const duration = 1000;
const animate = (currentTime: number) => {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
// Ease-out cubic for smooth deceleration
const eased = 1 - Math.pow(1 - progress, 3);
// Calculate current values
this.currentInputTokens = Math.round(
startInputTokens + (targetInputTokens - startInputTokens) * eased
);
this.currentOutputTokens = Math.round(
startOutputTokens + (targetOutputTokens - startOutputTokens) * eased
);
this.setStatusBarMessage(
`Input Tokens: ${this.currentInputTokens} / Output Tokens: ${this.currentOutputTokens}`
);
// Continue animation if not complete
if (progress < 1) {
this.animationFrame = requestAnimationFrame(animate);
} else {
this.animationFrame = null;
}
};
this.animationFrame = requestAnimationFrame(animate);
}
public removeStatusBarMessage() {
if (this.animationFrame !== null) {
cancelAnimationFrame(this.animationFrame);
this.animationFrame = null;
}
this.statusBarItem?.remove();
this.statusBarItem = null;
}