// State management let currentMode = 'template'; let isRecording = false; let isPlaying = false; let uploadedImage = null; let recordingInterval = null; let recordingTime = 0; let generationQueue = []; let currentGeneration = null; let selectedTemplate = null; let selectedMusic = null; let audioContext = null; // Initialize document.addEventListener('DOMContentLoaded', () => { lucide.createIcons(); initializeDragDrop(); initializeSliders(); initializeCheckboxes(); initializeGenerations(); }); // Drag and Drop Setup function initializeDragDrop() { const uploadZone = document.getElementById('uploadZone'); if (!uploadZone) return; ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { uploadZone.addEventListener(eventName, preventDefaults, false); }); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } uploadZone.addEventListener('dragenter', () => { uploadZone.classList.add('dragover'); }); uploadZone.addEventListener('dragleave', () => { uploadZone.classList.remove('dragover'); }); uploadZone.addEventListener('drop', (e) => { uploadZone.classList.remove('dragover'); const dt = e.dataTransfer; const files = dt.files; if (files.length > 0) { handleFile(files[0]); } }); } // Initialize range sliders with value display function initializeSliders() { const sliders = document.querySelectorAll('.slider-thumb'); sliders.forEach(slider => { const updateValue = () => { const valueDisplay = slider.parentElement.querySelector('span:last-child'); if (valueDisplay) { let suffix = '%'; if (slider.parentElement.textContent.includes('Blink')) suffix = ''; valueDisplay.textContent = slider.value + suffix; } }; slider.addEventListener('input', updateValue); }); } // Initialize checkboxes with visual feedback function initializeCheckboxes() { const checkboxes = document.querySelectorAll('input[type="checkbox"]'); checkboxes.forEach(checkbox => { checkbox.addEventListener('change', (e) => { const label = e.target.closest('label'); if (label) { if (e.target.checked) { label.classList.add('bg-violet-50'); } else { label.classList.remove('bg-violet-50'); } } }); }); } // Initialize generations with demo data function initializeGenerations() { // Simulate real-time progress updates setInterval(() => { updateProcessingItems(); }, 3000); } // Mode selection function selectMode(mode, element) { currentMode = mode; // Update UI document.querySelectorAll('.mode-card').forEach(card => { card.classList.remove('active'); }); element.classList.add('active'); // Show/hide sections with animation const sections = { template: document.getElementById('templateSection'), music: document.getElementById('musicSection'), voice: document.getElementById('voiceSection') }; Object.values(sections).forEach(section => { if (section) { section.classList.add('hidden'); section.style.opacity = '0'; } }); if (sections[mode]) { sections[mode].classList.remove('hidden'); setTimeout(() => { sections[mode].style.transition = 'opacity 0.2s ease'; sections[mode].style.opacity = '1'; }, 10); } lucide.createIcons(); } // Image upload handling function handleImageUpload(event) { const file = event.target.files[0]; if (file) { handleFile(file); } } function handleFile(file) { if (!file.type.startsWith('image/')) { showNotification('Please upload an image file (JPG, PNG, WEBP)', 'error'); return; } if (file.size > 10 * 1024 * 1024) { showNotification('File size must be less than 10MB', 'error'); return; } const reader = new FileReader(); reader.onload = (e) => { uploadedImage = e.target.result; updateUploadUI(file.name); showNotification('Image uploaded successfully!', 'success'); }; reader.readAsDataURL(file); } function updateUploadUI(filename) { const placeholder = document.getElementById('uploadPlaceholder'); const preview = document.getElementById('imagePreview'); const previewImg = document.getElementById('previewImage'); const activePreview = document.getElementById('activePreview'); const previewPlaceholder = document.getElementById('previewPlaceholder'); const summaryInput = document.getElementById('summaryInput'); if (placeholder) placeholder.classList.add('hidden'); if (preview) { preview.classList.remove('hidden'); const img = preview.querySelector('img'); if (img) img.src = uploadedImage; } if (previewPlaceholder) previewPlaceholder.classList.add('hidden'); if (activePreview) { activePreview.classList.remove('hidden'); if (previewImg) previewImg.src = uploadedImage; } if (summaryInput) summaryInput.textContent = filename; } function removeImage() { uploadedImage = null; document.getElementById('uploadPlaceholder').classList.remove('hidden'); document.getElementById('imagePreview').classList.add('hidden'); document.getElementById('fileInput').value = ''; document.getElementById('previewPlaceholder').classList.remove('hidden'); document.getElementById('activePreview').classList.add('hidden'); document.getElementById('summaryInput').textContent = 'No image'; showNotification('Image removed', 'info'); } // Template selection in sidebar function selectTemplate(element, templateName) { selectedTemplate = templateName; document.querySelectorAll('.template-option').forEach(opt => { opt.classList.remove('bg-violet-50', 'border-violet-300'); opt.classList.add('border-gray-200'); }); element.classList.remove('border-gray-200'); element.classList.add('bg-violet-50', 'border-violet-300'); // Update preview if image is uploaded if (uploadedImage) { showNotification(`Template "${templateName}" selected`, 'success'); } } // Template selection in grid function selectTemplateCard(element) { document.querySelectorAll('.template-card').forEach(card => { card.classList.remove('selected'); }); element.classList.add('selected'); // Extract template name const nameEl = element.querySelector('h4'); if (nameEl) selectedTemplate = nameEl.textContent; // Switch to preview tab with animation setTimeout(() => { const previewBtn = document.querySelector('button[onclick*="preview"]'); if (previewBtn) switchTab('preview', previewBtn); }, 200); showNotification('Template selected', 'success'); } // Tab switching function switchTab(tabName, element) { const tabs = ['previewTab', 'templatesTab', 'audioTab', 'captionsTab']; tabs.forEach(tab => { const el = document.getElementById(tab); if (el) { el.classList.add('hidden'); el.style.opacity = '0'; } }); const selectedTab = document.getElementById(tabName + 'Tab'); if (selectedTab) { selectedTab.classList.remove('hidden'); setTimeout(() => { selectedTab.style.transition = 'opacity 0.3s ease'; selectedTab.style.opacity = '1'; }, 10); } document.querySelectorAll('.tab-active').forEach(btn => { btn.classList.remove('tab-active'); btn.classList.add('text-gray-500'); }); if (element) { element.classList.remove('text-gray-500'); element.classList.add('tab-active'); } lucide.createIcons(); } // Aspect ratio selection function setAspect(btn) { document.querySelectorAll('.aspect-btn').forEach(b => { b.classList.remove('border-violet-500', 'bg-violet-50', 'text-violet-700'); b.classList.add('border-gray-200', 'text-gray-600'); }); btn.classList.remove('border-gray-200', 'text-gray-600'); btn.classList.add('border-violet-500', 'bg-violet-50', 'text-violet-700'); // Update preview aspect ratio const activePreview = document.getElementById('activePreview'); if (activePreview) { const ratio = btn.textContent.trim(); if (ratio === '1:1') activePreview.style.aspectRatio = '1/1'; else if (ratio === '4:5') activePreview.style.aspectRatio = '4/5'; else if (ratio === '9:16') activePreview.style.aspectRatio = '9/16'; else if (ratio === '16:9') activePreview.style.aspectRatio = '16/9'; } } // Recording functionality function toggleRecording() { const btn = document.getElementById('recordBtn'); const icon = document.getElementById('recordIcon'); const text = document.getElementById('recordText'); if (!isRecording) { // Start recording isRecording = true; recordingTime = 0; if (icon) { icon.classList.add('recording-pulse'); icon.classList.remove('rounded-full'); icon.classList.add('rounded-sm'); } if (text) text.textContent = 'Stop Recording (0:00)'; if (btn) { btn.classList.remove('bg-red-50', 'border-red-200'); btn.classList.add('bg-red-100', 'border-red-300'); } // Simulate recording timer recordingInterval = setInterval(() => { recordingTime++; const mins = Math.floor(recordingTime / 60); const secs = recordingTime % 60; if (text) { text.textContent = `Stop Recording (${mins}:${secs.toString().padStart(2, '0')})`; } }, 1000); showNotification('Recording started...', 'info'); // Simulate recording limit setTimeout(() => { if (isRecording) toggleRecording(); }, 60000); // Auto stop after 60 seconds } else { // Stop recording isRecording = false; clearInterval(recordingInterval); if (icon) { icon.classList.remove('recording-pulse'); icon.classList.add('rounded-full'); icon.classList.remove('rounded-sm'); } if (text) text.textContent = 'Record Voice'; if (btn) { btn.classList.add('bg-red-50', 'border-red-200'); btn.classList.remove('bg-red-100', 'border-red-300'); } showNotification(`Recording saved (${recordingTime}s)`, 'success'); // Add to generations addGenerationToQueue({ name: `Voice Recording (${recordingTime}s)`, type: 'Voice', status: 'completed', duration: `${recordingTime}s`, resolution: '1080p' }); } } // Play/Pause toggle for preview function togglePlay() { const playIcon = document.getElementById('playIcon'); const progressBar = document.getElementById('progressBar'); isPlaying = !isPlaying; if (isPlaying) { if (playIcon) { playIcon.setAttribute('data-lucide', 'pause'); lucide.createIcons(); } // Simulate progress if (progressBar) { progressBar.style.width = '0%'; setTimeout(() => { progressBar.style.transition = 'width 15s linear'; progressBar.style.width = '100%'; }, 100); } showNotification('Playing preview...', 'info'); setTimeout(() => { isPlaying = false; if (playIcon) { playIcon.setAttribute('data-lucide', 'play'); lucide.createIcons(); } if (progressBar) { progressBar.style.transition = 'none'; progressBar.style.width = '0%'; } }, 15000); } else { if (playIcon) { playIcon.setAttribute('data-lucide', 'play'); lucide.createIcons(); } if (progressBar) { progressBar.style.transition = 'none'; } } } // Generate Lip Sync function generateLipSync() { if (!uploadedImage) { showNotification('Please upload a cat photo first', 'error'); document.getElementById('uploadZone').scrollIntoView({ behavior: 'smooth' }); return; } if (!selectedTemplate && currentMode === 'template') { showNotification('Please select a template', 'error'); return; } // Deduct credits const creditsBadge = document.querySelector('.text-violet-900'); if (creditsBadge) { let credits = parseInt(creditsBadge.textContent.replace(/,/g, '')); credits -= 45; creditsBadge.textContent = credits.toLocaleString() + ' credits'; } // Add to generations const generationId = Date.now(); const newGeneration = { id: generationId, name: selectedTemplate || 'Custom Generation', type: currentMode === 'template' ? 'Template' : currentMode === 'music' ? 'Music' : 'Voice', status: 'processing', progress: 0, timestamp: new Date(), duration: '0:15', resolution: '1080p' }; addGenerationToQueue(newGeneration); showNotification('Generation started! Check the Generations panel.', 'success'); // Simulate generation progress simulateGenerationProgress(generationId); } // Add generation to queue and UI function addGenerationToQueue(generation) { generationQueue.push(generation); renderGenerationCard(generation); } // Render generation card function renderGenerationCard(generation) { const container = document.querySelector('.overflow-y-auto.custom-scrollbar'); if (!container) return; const card = document.createElement('div'); card.className = 'generation-card bg-white border border-gray-200 rounded-xl p-3 shadow-sm mb-3'; card.id = `gen-${generation.id}`; const statusColor = generation.status === 'completed' ? 'green' : generation.status === 'failed' ? 'red' : 'amber'; card.innerHTML = `
${generation.name}
${generation.type} • Just now
${generation.status === 'processing' ? `Ready to download
0:15 • 1080p