Files
CRM_Montzar/apps/web/src/lib/activity-attachment.ts
T

70 lines
2.6 KiB
TypeScript
Raw Normal View History

import { FormFileTooLargeError, prepareFormFieldFile } from '@/lib/form-file-compress';
import { compressVoiceFile } from '@/lib/voice-note';
export const ACTIVITY_FILE_MAX_BYTES = 10 * 1024 * 1024;
const FILE_MIME_BY_EXT: Record<string, string> = {
pdf: 'application/pdf',
txt: 'text/plain',
csv: 'text/csv',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
xls: 'application/vnd.ms-excel',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
zip: 'application/zip',
};
const IMAGE_EXT = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp']);
const AUDIO_EXT = new Set(['webm', 'ogg', 'mp3', 'm4a', 'aac', 'wav', 'mpeg']);
export type PreparedAttachment = {
kind: 'image' | 'audio' | 'file';
name: string;
file: File;
previewUrl: string;
};
function extensionOf(name: string): string {
return name.split('.').pop()?.toLowerCase().replace(/[^a-z0-9]/g, '') ?? '';
}
function kindOf(file: File): 'image' | 'audio' | 'file' {
const type = file.type.toLowerCase().split(';')[0] ?? '';
const ext = extensionOf(file.name);
if (type.startsWith('image/') || IMAGE_EXT.has(ext)) return 'image';
if (type.startsWith('audio/') || AUDIO_EXT.has(ext)) return 'audio';
return 'file';
}
export async function prepareActivityAttachment(file: File): Promise<PreparedAttachment> {
const kind = kindOf(file);
if (kind === 'image') {
try {
const prepared = await prepareFormFieldFile(file);
return { kind, name: prepared.name, file: prepared.file, previewUrl: prepared.dataUrl };
} catch (error) {
if (error instanceof FormFileTooLargeError) {
throw new Error('حجم عکس باید زیر ۲۰۰ کیلوبایت باشد');
}
throw new Error('فشرده‌سازی عکس ناموفق بود.');
}
}
if (kind === 'audio') {
const compressed = await compressVoiceFile(file);
return {
kind,
name: compressed.name,
file: compressed,
previewUrl: URL.createObjectURL(compressed),
};
}
const ext = extensionOf(file.name);
const mime = FILE_MIME_BY_EXT[ext];
if (!mime) throw new Error('این نوع فایل مجاز نیست.');
if (file.size > ACTIVITY_FILE_MAX_BYTES) throw new Error('حجم فایل باید زیر ۱۰ مگابایت باشد');
const named = file.type === mime ? file : new File([file], file.name, { type: mime });
return { kind: 'file', name: named.name, file: named, previewUrl: '' };
}