LibreChat/client/src/utils/files.ts
2024-07-10 16:38:02 -04:00

171 lines
3.7 KiB
TypeScript

import { excelMimeTypes, QueryKeys } from 'librechat-data-provider';
import type { QueryClient } from '@tanstack/react-query';
import type { TFile } from 'librechat-data-provider';
import SheetPaths from '~/components/svg/Files/SheetPaths';
import TextPaths from '~/components/svg/Files/TextPaths';
import FilePaths from '~/components/svg/Files/FilePaths';
import CodePaths from '~/components/svg/Files/CodePaths';
export const partialTypes = ['text/x-'];
const textDocument = {
paths: TextPaths,
fill: '#FF5588',
title: 'Document',
};
const spreadsheet = {
paths: SheetPaths,
fill: '#10A37F',
title: 'Spreadsheet',
};
const codeFile = {
paths: CodePaths,
fill: '#FF6E3C',
// TODO: make this dynamic to the language
title: 'Code',
};
export const fileTypes = {
/* Category matches */
file: {
paths: FilePaths,
fill: '#0000FF',
title: 'File',
},
text: textDocument,
// application:,
/* Partial matches */
csv: spreadsheet,
pdf: textDocument,
'text/x-': codeFile,
/* Exact matches */
// 'application/json':,
// 'text/html':,
// 'text/css':,
// image,
};
// export const getFileType = (type = '') => {
// let fileType = fileTypes.file;
// const exactMatch = fileTypes[type];
// const partialMatch = !exactMatch && partialTypes.find((type) => type.includes(type));
// const category = (!partialMatch && (type.split('/')[0] ?? 'text') || 'text');
// if (exactMatch) {
// fileType = exactMatch;
// } else if (partialMatch) {
// fileType = fileTypes[partialMatch];
// } else if (fileTypes[category]) {
// fileType = fileTypes[category];
// }
// if (!fileType) {
// fileType = fileTypes.file;
// }
// return fileType;
// };
export const getFileType = (
type = '',
): {
paths: React.FC;
fill: string;
title: string;
} => {
// Direct match check
if (fileTypes[type]) {
return fileTypes[type];
}
if (excelMimeTypes.test(type)) {
return spreadsheet;
}
// Partial match check
const partialMatch = partialTypes.find((partial) => type.includes(partial));
if (partialMatch && fileTypes[partialMatch]) {
return fileTypes[partialMatch];
}
// Category check
const category = type.split('/')[0] || 'text';
if (fileTypes[category]) {
return fileTypes[category];
}
// Default file type
return fileTypes.file;
};
/**
* Format a date string to a human readable format
* @example
* formatDate('2020-01-01T00:00:00.000Z') // '1 Jan 2020'
*/
export function formatDate(dateString: string) {
const months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const date = new Date(dateString);
const day = date.getDate();
const month = months[date.getMonth()];
const year = date.getFullYear();
return `${day} ${month} ${year}`;
}
/**
* Adds a file to the query cache
*/
export function addFileToCache(queryClient: QueryClient, newfile: TFile) {
const currentFiles = queryClient.getQueryData<TFile[]>([QueryKeys.files]);
if (!currentFiles) {
console.warn('No current files found in cache, skipped updating file query cache');
return;
}
const fileIndex = currentFiles.findIndex((file) => file.file_id === newfile.file_id);
if (fileIndex > -1) {
console.warn('File already exists in cache, skipped updating file query cache');
return;
}
queryClient.setQueryData<TFile[]>(
[QueryKeys.files],
[
{
...newfile,
},
...currentFiles,
],
);
}
export function formatBytes(bytes: number, decimals = 2) {
if (bytes === 0) {
return 0;
}
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm));
}