// Initialize Alpine store for API key management document.addEventListener('alpine:init', () => { Alpine.store('chat', { get key() { return localStorage.getItem('key') || ''; }, set key(value) { localStorage.setItem('key', value); } }); }); function submitKey(event) { event.preventDefault(); const keyValue = document.getElementById("apiKey").value; localStorage.setItem("key", keyValue); // Show brief visual confirmation const button = event.submitter; const originalIcon = button.innerHTML; button.innerHTML = ''; button.classList.add('bg-green-600'); button.classList.remove('bg-blue-600', 'hover:bg-blue-700'); setTimeout(() => { button.innerHTML = originalIcon; button.classList.remove('bg-green-600'); button.classList.add('bg-blue-600', 'hover:bg-blue-700'); }, 1000); document.getElementById("apiKey").blur(); } function genAudio(event) { event.preventDefault(); const input = document.getElementById("input").value; const key = localStorage.getItem("key"); if (!input.trim()) { showNotification('error', 'Please enter text to convert to speech'); return; } if (!key) { showNotification('warning', 'API key is not set. Please set your API key first.'); return; } tts(key, input); } function showNotification(type, message) { // Remove any existing notification const existingNotification = document.getElementById('notification'); if (existingNotification) { existingNotification.remove(); } // Create new notification const notification = document.createElement('div'); notification.id = 'notification'; notification.classList.add( 'fixed', 'top-24', 'right-4', 'z-50', 'p-4', 'rounded-lg', 'shadow-lg', 'transform', 'transition-all', 'duration-300', 'ease-in-out', 'translate-y-0', 'flex', 'items-center', 'gap-2' ); // Style based on notification type if (type === 'error') { notification.classList.add('bg-red-900/90', 'border', 'border-red-700', 'text-red-200'); notification.innerHTML = '' + message; } else if (type === 'warning') { notification.classList.add('bg-yellow-900/90', 'border', 'border-yellow-700', 'text-yellow-200'); notification.innerHTML = '' + message; } else if (type === 'success') { notification.classList.add('bg-green-900/90', 'border', 'border-green-700', 'text-green-200'); notification.innerHTML = '' + message; } else { notification.classList.add('bg-blue-900/90', 'border', 'border-blue-700', 'text-blue-200'); notification.innerHTML = '' + message; } // Add close button const closeBtn = document.createElement('button'); closeBtn.innerHTML = ''; closeBtn.classList.add('ml-auto', 'text-gray-400', 'hover:text-white', 'transition-colors'); closeBtn.onclick = () => { notification.classList.add('opacity-0', 'translate-y-[-20px]'); setTimeout(() => notification.remove(), 300); }; notification.appendChild(closeBtn); // Add to DOM document.body.appendChild(notification); // Animate in setTimeout(() => { notification.classList.add('opacity-0', 'translate-y-[-20px]'); notification.offsetHeight; // Force reflow notification.classList.remove('opacity-0', 'translate-y-[-20px]'); }, 10); // Auto dismiss after 5 seconds setTimeout(() => { if (document.getElementById('notification')) { notification.classList.add('opacity-0', 'translate-y-[-20px]'); setTimeout(() => notification.remove(), 300); } }, 5000); } async function tts(key, input) { // Show loader and prepare UI const loader = document.getElementById("loader"); const inputField = document.getElementById("input"); const resultDiv = document.getElementById("result"); loader.style.display = "block"; inputField.value = ""; inputField.disabled = true; resultDiv.innerHTML = '
${jsonData.error.message || 'An error occurred'}
Network error: Failed to connect to the server