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 = { 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 { 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: '' }; }