diff --git a/app/components/messages/MessageInput.vue b/app/components/messages/MessageInput.vue index 0ea253e..08199fa 100644 --- a/app/components/messages/MessageInput.vue +++ b/app/components/messages/MessageInput.vue @@ -184,6 +184,16 @@ const caption = ref('') const isDragging = ref(false) const stickerModes = ref([]) +// File size limits (in bytes) - should match server +const MAX_SIZES: Record = { + image: 16 * 1024 * 1024, // 16 MB + video: 64 * 1024 * 1024, // 64 MB + audio: 16 * 1024 * 1024, // 16 MB + document: 100 * 1024 * 1024, // 100 MB +} + +const toast = useToast() + // Audio recorder const { isRecording, @@ -242,12 +252,48 @@ const handleFileSelect = (event: Event, type: string) => { } } +const getFileMediaType = (file: File): string => { + if (file.type.startsWith('image/')) return 'image' + if (file.type.startsWith('video/')) return 'video' + if (file.type.startsWith('audio/')) return 'audio' + return 'document' +} + +const formatFileSize = (bytes: number): string => { + if (bytes === 0) return '0 B' + const k = 1024 + const sizes = ['B', 'KB', 'MB', 'GB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}` +} + const addFiles = (files: File[]) => { // Limit to 10 files const remaining = 10 - selectedFiles.value.length const toAdd = files.slice(0, remaining) - // Use spread operator to trigger reactivity - selectedFiles.value = [...selectedFiles.value, ...toAdd] + + // Validate file sizes + const validFiles: File[] = [] + for (const file of toAdd) { + const mediaType = getFileMediaType(file) + const maxSize = MAX_SIZES[mediaType] + + if (file.size > maxSize) { + toast.add({ + title: 'Archivo muy grande', + description: `${file.name} (${formatFileSize(file.size)}) excede el límite de ${formatFileSize(maxSize)} para ${mediaType}`, + color: 'error', + duration: 5000 + }) + } else { + validFiles.push(file) + } + } + + if (validFiles.length > 0) { + // Use spread operator to trigger reactivity + selectedFiles.value = [...selectedFiles.value, ...validFiles] + } } const handleDrop = (event: DragEvent) => { diff --git a/app/pages/messages/index.vue b/app/pages/messages/index.vue index ff1c552..600580e 100644 --- a/app/pages/messages/index.vue +++ b/app/pages/messages/index.vue @@ -548,8 +548,23 @@ const handleSendMessage = async (content: string, files: File[], caption: string // Reload messages messages.value = await $fetch(`/api/messages/${instanceId}/${chatId}`) - } catch (e) { + } catch (e: any) { console.error('Error sending message:', e) + + // Extract error message from response + let errorMessage = 'Error al enviar el mensaje' + if (e?.data?.message) { + errorMessage = e.data.message + } else if (e?.message) { + errorMessage = e.message + } + + toast.add({ + title: 'Error de envío', + description: errorMessage, + color: 'error', + duration: 5000 + }) } }