mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 16:30:27 +00:00
Improve component lifecycle management by converting DiffService and StatusBarService to extend Component class, ensuring proper cleanup and event handling. Add automatic service cleanup in DependencyService during deregistration. Refine error handling in AI function responses to return error messages instead of Error objects for better serialization. Update user rejection messaging to provide clearer guidance to AI about stopping actions.
87 lines
No EOL
2.8 KiB
TypeScript
87 lines
No EOL
2.8 KiB
TypeScript
import type VaultkeeperAIPlugin from "main";
|
|
import { Resolve } from "./DependencyService";
|
|
import { Services } from "./Services";
|
|
import { Component } from "obsidian";
|
|
|
|
export class StatusBarService extends Component {
|
|
|
|
private readonly plugin: VaultkeeperAIPlugin;
|
|
private statusBarItem: HTMLElement | null;
|
|
private currentInputTokens: number = 0;
|
|
private currentOutputTokens: number = 0;
|
|
private animationFrame: number | null = null;
|
|
|
|
public constructor() {
|
|
super();
|
|
this.plugin = Resolve<VaultkeeperAIPlugin>(Services.VaultkeeperAIPlugin);
|
|
}
|
|
|
|
override onunload(): void {
|
|
this.removeStatusBarMessage();
|
|
}
|
|
|
|
public setStatusBarMessage(message: string) {
|
|
if (this.statusBarItem == null) {
|
|
this.createStatusBarMessage();
|
|
}
|
|
|
|
this.statusBarItem?.empty();
|
|
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;
|
|
}
|
|
|
|
private createStatusBarMessage() {
|
|
this.statusBarItem?.remove();
|
|
this.statusBarItem = this.plugin.addStatusBarItem();
|
|
this.statusBarItem.empty();
|
|
}
|
|
} |