2024-07-21 21:41:19 +02:00
|
|
|
// this file is responsible for managing files within chats.
|
|
|
|
|
|
2024-07-22 00:37:36 +02:00
|
|
|
import { DATA_VERSION, ValidObject } from "./Utility/typeSafety";
|
2024-07-21 23:32:20 +02:00
|
|
|
import StorageModel, { storageKeys } from "./storageModel";
|
|
|
|
|
import { parseValidObject, stringify } from "./Utility/utility";
|
2024-07-21 22:42:32 +02:00
|
|
|
|
2024-07-22 01:38:08 +02:00
|
|
|
import ChatModel from "./chatModel";
|
2024-07-22 00:37:36 +02:00
|
|
|
import { v4 } from "uuid";
|
2024-07-21 21:45:18 +02:00
|
|
|
|
|
|
|
|
export default class FileModel {
|
|
|
|
|
chatModel: ChatModel;
|
2024-07-21 23:32:20 +02:00
|
|
|
storageModel: StorageModel;
|
2024-07-21 21:45:18 +02:00
|
|
|
|
2024-07-21 22:42:32 +02:00
|
|
|
// handler
|
|
|
|
|
handleStringifiedFile = (stringifiedFile: string): void => {
|
2024-07-22 01:40:00 +02:00
|
|
|
const file: File | null = parseValidObject(stringifiedFile, FileReference);
|
2024-07-21 22:42:32 +02:00
|
|
|
if (file == null) return;
|
2024-07-22 00:37:36 +02:00
|
|
|
|
|
|
|
|
this.storeFile(file);
|
2024-07-21 22:42:32 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// methods
|
|
|
|
|
addFile = (file: File): void => {
|
|
|
|
|
this.chatModel.sendMessage("", file);
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
// storage
|
|
|
|
|
storeFile = (file: File): void => {
|
|
|
|
|
for (const fileContent of file.contentVersions) {
|
|
|
|
|
this.storeFileContent(file, fileContent);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
storeFileContent = (file: File, fileContent: FileContent): void => {
|
|
|
|
|
const fileContentName: string = FileModel.getFileContentName(fileContent);
|
|
|
|
|
const fileContentPath: string[] = FileModel.getFileContentPath(
|
|
|
|
|
file,
|
|
|
|
|
fileContentName
|
|
|
|
|
);
|
2024-07-22 00:37:36 +02:00
|
|
|
|
|
|
|
|
// check if fileContent already exists
|
2024-07-22 01:22:59 +02:00
|
|
|
const existingFileContent: string | null =
|
|
|
|
|
this.storageModel.read(fileContentPath);
|
2024-07-22 00:37:36 +02:00
|
|
|
if (existingFileContent != null) return;
|
|
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
const stringifiedContent: string = stringify(fileContent);
|
|
|
|
|
this.storageModel.write(fileContentPath, stringifiedContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listFileIds = (): string[] => {
|
|
|
|
|
return this.storageModel.list(storageKeys.chatFiles);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listFileContents = (file: File): string[] => {
|
|
|
|
|
const filePath: string[] = FileModel.getFilePath(file.id);
|
|
|
|
|
return this.storageModel.list(filePath);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getFile = (fileId: string): File | null => {
|
|
|
|
|
const filePath = FileModel.getFilePath(fileId);
|
2024-07-22 01:38:08 +02:00
|
|
|
const fileOrNull: File | null = this.storageModel.readStringifiable(
|
|
|
|
|
filePath,
|
|
|
|
|
FileReference
|
|
|
|
|
);
|
2024-07-21 23:32:20 +02:00
|
|
|
return fileOrNull;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getLatestFileContentName = (fileContentNames: string[]): string | null => {
|
|
|
|
|
return fileContentNames[fileContentNames.length - 1];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getFileContent = (
|
|
|
|
|
file: File,
|
|
|
|
|
fileContentName: string
|
|
|
|
|
): FileContent | null => {
|
|
|
|
|
const filePath = FileModel.getFileContentPath(file, fileContentName);
|
|
|
|
|
const fileContentOrNull: FileContent | null =
|
2024-07-22 01:38:08 +02:00
|
|
|
this.storageModel.readStringifiable(filePath, FileContentReference);
|
2024-07-21 23:32:20 +02:00
|
|
|
return fileContentOrNull;
|
|
|
|
|
};
|
|
|
|
|
|
2024-07-21 21:45:18 +02:00
|
|
|
// init
|
2024-07-21 23:32:20 +02:00
|
|
|
constructor(chatModel: ChatModel, storageModel: StorageModel) {
|
2024-07-21 21:45:18 +02:00
|
|
|
this.chatModel = chatModel;
|
2024-07-21 23:32:20 +02:00
|
|
|
this.storageModel = storageModel;
|
2024-07-21 21:45:18 +02:00
|
|
|
}
|
2024-07-21 21:41:19 +02:00
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
// utility
|
|
|
|
|
static getFilePath = (fileId: string): string[] => {
|
|
|
|
|
return [...storageKeys.chatFiles, fileId];
|
|
|
|
|
};
|
2024-07-21 20:54:18 +02:00
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
static getFileContentName = (fileContent: FileContent): string => {
|
2024-07-22 01:05:19 +02:00
|
|
|
return fileContent.creationDate + fileContent.id;
|
2024-07-21 23:32:20 +02:00
|
|
|
};
|
2024-07-21 20:54:18 +02:00
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
static getFileContentPath = (
|
|
|
|
|
file: File,
|
|
|
|
|
fileContentName: string
|
|
|
|
|
): string[] => {
|
2024-07-22 01:05:19 +02:00
|
|
|
const filePath: string[] = FileModel.getFilePath(file.id);
|
2024-07-21 23:32:20 +02:00
|
|
|
return [...filePath, fileContentName];
|
|
|
|
|
};
|
2024-07-22 00:37:36 +02:00
|
|
|
|
|
|
|
|
static createFile = (): File => {
|
|
|
|
|
return {
|
|
|
|
|
dataVersion: DATA_VERSION,
|
|
|
|
|
|
|
|
|
|
id: v4(),
|
2024-07-22 01:22:59 +02:00
|
|
|
contentVersions: [],
|
|
|
|
|
};
|
|
|
|
|
};
|
2024-07-21 20:54:18 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
// types
|
|
|
|
|
export interface File extends ValidObject {
|
2024-07-22 01:05:19 +02:00
|
|
|
id: string;
|
|
|
|
|
contentVersions: FileContent[];
|
2024-07-21 23:32:20 +02:00
|
|
|
}
|
2024-07-21 20:54:18 +02:00
|
|
|
|
2024-07-21 23:32:20 +02:00
|
|
|
export interface FileContent extends ValidObject {
|
2024-07-22 01:05:19 +02:00
|
|
|
id: string;
|
|
|
|
|
creationDate: string;
|
2024-07-21 23:32:20 +02:00
|
|
|
|
2024-07-22 01:05:19 +02:00
|
|
|
type: string;
|
2024-07-21 20:54:18 +02:00
|
|
|
}
|
2024-07-22 01:22:59 +02:00
|
|
|
|
|
|
|
|
// references
|
|
|
|
|
export const FileContentReference: FileContent = {
|
|
|
|
|
dataVersion: DATA_VERSION,
|
|
|
|
|
|
|
|
|
|
id: "",
|
|
|
|
|
creationDate: "",
|
|
|
|
|
|
|
|
|
|
type: "",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const FileReference: File = {
|
|
|
|
|
dataVersion: DATA_VERSION,
|
|
|
|
|
|
|
|
|
|
id: "",
|
|
|
|
|
contentVersions: [FileContentReference],
|
2024-07-22 01:38:08 +02:00
|
|
|
};
|