mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 21:03:42 +00:00
fix(tui): proper Kitty image ID management and cleanup
- Add allocateImageId() to generate unique image IDs - Add deleteKittyImage() and deleteAllKittyImages() functions - Image component now tracks its ID and has dispose() method - renderImage() returns imageId for tracking - DOSBox: reuse single image ID for all frames, delete on dispose Fixes image accumulation hitting terminal quota and lingering images after component close.
This commit is contained in:
parent
6515b1a3dd
commit
df1d5c40ea
4 changed files with 81 additions and 6 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
deleteKittyImage,
|
||||
getCapabilities,
|
||||
getImageDimensions,
|
||||
type ImageDimensions,
|
||||
|
|
@ -15,6 +16,8 @@ export interface ImageOptions {
|
|||
maxWidthCells?: number;
|
||||
maxHeightCells?: number;
|
||||
filename?: string;
|
||||
/** Kitty image ID. If provided, reuses this ID (for animations/updates). */
|
||||
imageId?: number;
|
||||
}
|
||||
|
||||
export class Image implements Component {
|
||||
|
|
@ -23,6 +26,7 @@ export class Image implements Component {
|
|||
private dimensions: ImageDimensions;
|
||||
private theme: ImageTheme;
|
||||
private options: ImageOptions;
|
||||
private imageId?: number;
|
||||
|
||||
private cachedLines?: string[];
|
||||
private cachedWidth?: number;
|
||||
|
|
@ -39,6 +43,12 @@ export class Image implements Component {
|
|||
this.theme = theme;
|
||||
this.options = options;
|
||||
this.dimensions = dimensions || getImageDimensions(base64Data, mimeType) || { widthPx: 800, heightPx: 600 };
|
||||
this.imageId = options.imageId;
|
||||
}
|
||||
|
||||
/** Get the Kitty image ID used by this image (if any). */
|
||||
getImageId(): number | undefined {
|
||||
return this.imageId;
|
||||
}
|
||||
|
||||
invalidate(): void {
|
||||
|
|
@ -57,9 +67,17 @@ export class Image implements Component {
|
|||
let lines: string[];
|
||||
|
||||
if (caps.images) {
|
||||
const result = renderImage(this.base64Data, this.dimensions, { maxWidthCells: maxWidth });
|
||||
const result = renderImage(this.base64Data, this.dimensions, {
|
||||
maxWidthCells: maxWidth,
|
||||
imageId: this.imageId,
|
||||
});
|
||||
|
||||
if (result) {
|
||||
// Store the image ID for later cleanup
|
||||
if (result.imageId) {
|
||||
this.imageId = result.imageId;
|
||||
}
|
||||
|
||||
// Return `rows` lines so TUI accounts for image height
|
||||
// First (rows-1) lines are empty (TUI clears them)
|
||||
// Last line: move cursor back up, then output image sequence
|
||||
|
|
@ -84,4 +102,15 @@ export class Image implements Component {
|
|||
|
||||
return lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the terminal image. Call this when done with the image
|
||||
* to free terminal resources.
|
||||
*/
|
||||
dispose(): void {
|
||||
if (this.imageId !== undefined) {
|
||||
process.stdout.write(deleteKittyImage(this.imageId));
|
||||
this.imageId = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue