andy-stack_vaultkeeper-ai/Conversations/Attachment.ts
Andrew Beal d2e7b47c65 refactor: centralize icon handling and improve attachment UI
- Move icon name logic to Attachment and Reference classes
- Create reusable setElementIcon Svelte action in ElementHelper
- Update ChatArea and ChatAttachments to use new icon helper
- Add visual separator and background color for message attachments
- Fix duplicate URIs in drag-and-drop file handling
- Improve attachment icon centering with flexbox layout
2025-12-23 20:18:27 +00:00

88 lines
No EOL
2.7 KiB
TypeScript

import type { AIProvider } from "Enums/ApiProvider";
import { isAudioFile, isImageFile, isKnownFileType, isTextFile, isVideoFile } from "Enums/FileType";
import { MimeTypeToFileTypes } from "Enums/FileTypeMimeTypeMapping";
import { toMimeType } from "Enums/MimeType";
export class Attachment {
public fileName: string;
public mimeType: string;
public base64: string;
public fileID: Partial<Record<AIProvider, string>>;
constructor(
fileName: string,
mimeType: string,
base64: string,
fileID: Partial<Record<AIProvider, string>> = {}
) {
this.fileName = fileName;
this.mimeType = mimeType;
this.base64 = base64;
this.fileID = fileID;
}
public getFileID(provider: AIProvider): string | undefined {
return this.fileID[provider];
}
public setFileID(provider: AIProvider, id: string): void {
this.fileID[provider] = id;
}
public deleteFileID(provider: AIProvider): boolean {
if (provider in this.fileID) {
delete this.fileID[provider];
return true;
}
return false;
}
public approximateFileSizeMB() {
// get the approximate MB size of the base64 string rounded to 2 decimal places
const paddingBytes = this.base64.endsWith("==") ? 2 : this.base64.endsWith("=") ? 1 : 0;
const byteSize = (this.base64.length * 3 / 4) - paddingBytes;
const megaByteSize = byteSize / 1000000;
return Math.round((megaByteSize + Number.EPSILON) * 100) / 100;
}
public getIconName(): string {
const fileTypes = MimeTypeToFileTypes[toMimeType(this.mimeType)];
if (fileTypes.some((fileType) => isTextFile(fileType))) {
return "file-text";
}
if (fileTypes.some((fileType) => isImageFile(fileType))) {
return "file-image";
}
if (fileTypes.some((fileType) => isAudioFile(fileType))) {
return "file-music";
}
if (fileTypes.some((fileType) => isVideoFile(fileType))) {
return "file-play";
}
if (fileTypes.some((fileType) => isKnownFileType(fileType))) {
return "file";
}
return "file";
}
public static isAttachmentData(this: void, data: unknown): data is {
fileName: string;
mimeType: string;
base64: string;
fileID?: Partial<Record<AIProvider, string>>;
} {
return (
data !== null &&
typeof data === "object" &&
"fileName" in data &&
"mimeType" in data &&
"base64" in data &&
typeof data.fileName === "string" &&
typeof data.mimeType === "string" &&
typeof data.base64 === "string" &&
(!("fileID" in data) || typeof data.fileID === "object")
);
}
}