// HokoriTemp - JavaScript principal let selectedFile = null; // Usar configuración del servidor si está disponible, sino usar valor por defecto const MAX_FILE_SIZE = (typeof SERVER_CONFIG !== 'undefined' && SERVER_CONFIG.maxFileSize) ? SERVER_CONFIG.maxFileSize : 16 * 1024 * 1024; // 16MB por defecto // DOM Elements const dropZone = document.getElementById('dropZone'); const fileInput = document.getElementById('fileInput'); const fileInfo = document.getElementById('fileInfo'); const fileName = document.getElementById('fileName'); const fileSize = document.getElementById('fileSize'); const removeFile = document.getElementById('removeFile'); const uploadForm = document.getElementById('uploadForm'); const uploadBtn = document.getElementById('uploadBtn'); const uploadBtnText = document.getElementById('uploadBtnText'); const uploadBtnLoading = document.getElementById('uploadBtnLoading'); const resultSection = document.getElementById('resultSection'); const emptyResultSection = document.getElementById('emptyResultSection'); const errorSection = document.getElementById('errorSection'); const errorMessage = document.getElementById('errorMessage'); const downloadLink = document.getElementById('downloadLink'); // Event Listeners dropZone.addEventListener('click', () => fileInput.click()); dropZone.addEventListener('dragover', handleDragOver); dropZone.addEventListener('dragleave', handleDragLeave); dropZone.addEventListener('drop', handleDrop); fileInput.addEventListener('change', handleFileSelect); removeFile.addEventListener('click', removeSelectedFile); uploadForm.addEventListener('submit', handleUpload); // Inicializar estado document.addEventListener('DOMContentLoaded', function() { // Mostrar el estado vacío del resultado al cargar emptyResultSection.classList.remove('hidden'); emptyResultSection.classList.add('fade-in'); }); function handleDragOver(e) { e.preventDefault(); dropZone.classList.add('dragover'); } function handleDragLeave(e) { e.preventDefault(); dropZone.classList.remove('dragover'); } function handleDrop(e) { e.preventDefault(); dropZone.classList.remove('dragover'); const files = e.dataTransfer.files; if (files.length > 0) { handleFile(files[0]); } } function handleFileSelect(e) { const file = e.target.files[0]; if (file) { handleFile(file); } } function handleFile(file) { // Validar tamaño del archivo if (file.size > MAX_FILE_SIZE) { showError(`El archivo es demasiado grande. Tamaño máximo: ${getMaxFileSizeMB()}MB`); return; } selectedFile = file; fileName.textContent = file.name; fileSize.textContent = formatFileSize(file.size); // Aplicar clase de advertencia si el archivo es grande (>10MB) if (file.size > 10 * 1024 * 1024) { fileInfo.classList.add('file-size-warning'); } else { fileInfo.classList.remove('file-size-warning'); } fileInfo.classList.remove('hidden'); uploadBtn.disabled = false; hideError(); } function removeSelectedFile() { selectedFile = null; fileInput.value = ''; fileInfo.classList.add('hidden'); fileInfo.classList.remove('file-size-warning', 'file-size-error'); uploadBtn.disabled = true; // Ocultar resultado si hay uno mostrado hideResult(); } function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } async function handleUpload(e) { e.preventDefault(); if (!selectedFile) { showError('Por favor selecciona un archivo'); return; } // Validar tamaño del archivo antes de subir if (selectedFile.size > MAX_FILE_SIZE) { showError(`El archivo es demasiado grande. Tamaño máximo: ${getMaxFileSizeMB()}MB`); return; } // Show loading state uploadBtn.disabled = true; uploadBtnText.classList.add('hidden'); uploadBtnLoading.classList.remove('hidden'); hideError(); hideResult(); const formData = new FormData(); formData.append('file', selectedFile); try { const response = await fetch('/upload', { method: 'POST', body: formData }); // Verificar si la respuesta es JSON válido const contentType = response.headers.get('content-type'); const isJson = contentType && contentType.includes('application/json'); // Manejar diferentes códigos de respuesta if (response.status === 413) { showError(`El archivo es demasiado grande. Tamaño máximo: ${getMaxFileSizeMB()}MB`); return; } if (!response.ok) { let errorMessage = `Error del servidor (${response.status})`; if (isJson) { try { const errorData = await response.json(); errorMessage = errorData.error || errorMessage; } catch (e) { console.error('Error parsing JSON response:', e); } } else { // Si no es JSON, intentar leer como texto try { const errorText = await response.text(); console.error('Error response:', errorText); // Detectar errores específicos basados en el contenido if (errorText.includes('Request Entity Too Large') || errorText.includes('413')) { errorMessage = `El archivo es demasiado grande. Tamaño máximo: ${getMaxFileSizeMB()}MB`; } else if (errorText.includes('413')) { errorMessage = `El archivo es demasiado grande. Tamaño máximo: ${getMaxFileSizeMB()}MB`; } else { errorMessage = `Error del servidor: ${response.statusText}`; } } catch (e) { console.error('Error reading response text:', e); } } showError(errorMessage); return; } if (isJson) { const result = await response.json(); if (result.success) { // Save to localStorage saveLinkToStorage(result); showResult(result.download_url); showNotification('Archivo subido exitosamente', 'success'); } else { showError(result.error || 'Error al subir el archivo'); } } else { showError('Respuesta inesperada del servidor'); } } catch (error) { console.error('Upload error:', error); // Determinar el tipo de error if (error.name === 'TypeError' && error.message.includes('Failed to fetch')) { showError('Error de conexión. Verifica tu conexión a internet e intenta de nuevo.'); } else if (error.name === 'TypeError' && error.message.includes('JSON')) { showError('Error al procesar la respuesta del servidor.'); } else { showError('Error inesperado. Intenta de nuevo.'); } } finally { // Reset loading state uploadBtn.disabled = false; uploadBtnText.classList.remove('hidden'); uploadBtnLoading.classList.add('hidden'); } } function saveLinkToStorage(result) { const links = JSON.parse(localStorage.getItem('tempFileLinks') || '[]'); const newLink = { id: result.file_id, url: result.download_url, filename: result.original_filename, expiresAt: result.expires_at, createdAt: new Date().toISOString() }; links.push(newLink); localStorage.setItem('tempFileLinks', JSON.stringify(links)); } function showResult(url) { downloadLink.value = url; resultSection.classList.remove('hidden'); resultSection.classList.add('fade-in'); emptyResultSection.classList.add('hidden'); } function showError(message) { errorMessage.textContent = message; errorSection.classList.remove('hidden'); showNotification(message, 'error'); } function hideError() { errorSection.classList.add('hidden'); } function hideResult() { resultSection.classList.add('hidden'); resultSection.classList.remove('fade-in'); emptyResultSection.classList.remove('hidden'); emptyResultSection.classList.add('fade-in'); } function copyLink() { downloadLink.select(); document.execCommand('copy'); // Show feedback const copyBtn = event.target; const originalText = copyBtn.textContent; copyBtn.textContent = '¡Copiado!'; setTimeout(() => { copyBtn.textContent = originalText; }, 2000); showNotification('Enlace copiado al portapapeles', 'success'); } function openLink() { window.open(downloadLink.value, '_blank'); } function resetForm() { removeSelectedFile(); hideResult(); hideError(); // Mostrar el estado vacío del resultado emptyResultSection.classList.remove('hidden'); } // Función para mostrar notificaciones function showNotification(message, type = 'info') { // Crear elemento de notificación const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; // Agregar al DOM document.body.appendChild(notification); // Mostrar con animación setTimeout(() => { notification.classList.add('show'); }, 100); // Ocultar después de 3 segundos setTimeout(() => { notification.classList.remove('show'); setTimeout(() => { document.body.removeChild(notification); }, 300); }, 3000); } // Función helper para obtener el tamaño máximo en MB function getMaxFileSizeMB() { return (typeof SERVER_CONFIG !== 'undefined' && SERVER_CONFIG.maxFileSizeMB) ? SERVER_CONFIG.maxFileSizeMB : MAX_FILE_SIZE / (1024 * 1024); } // Función para validar archivo antes de subir function validateFile(file) { const maxSize = MAX_FILE_SIZE; const maxSizeMB = getMaxFileSizeMB(); if (file.size > maxSize) { return { valid: false, message: `El archivo es demasiado grande. Tamaño máximo: ${maxSizeMB}MB` }; } return { valid: true }; }