| |
| const config = { |
| localApiUrl: localStorage.getItem('motif_api_url') || null, |
| }; |
|
|
| |
| const modal = document.getElementById('guide-modal'); |
| const showGuideBtn = document.getElementById('show-guide'); |
| const closeModalBtn = document.querySelector('.close-modal'); |
| const saveConnectionBtn = document.getElementById('save-connection'); |
| const apiUrlInput = document.getElementById('api-url'); |
| const navItems = document.querySelectorAll('.nav-item'); |
| const sections = document.querySelectorAll('main section'); |
|
|
| |
| document.addEventListener('DOMContentLoaded', () => { |
| |
| if (!config.localApiUrl) { |
| openModal(); |
| } else { |
| apiUrlInput.value = config.localApiUrl; |
| } |
| |
| |
| initializeCursorTrail(); |
| }); |
|
|
| |
| navItems.forEach(item => { |
| item.addEventListener('click', (e) => { |
| |
| navItems.forEach(nav => nav.classList.remove('active')); |
| item.classList.add('active'); |
|
|
| |
| const targetSectionId = item.getAttribute('data-target'); |
| sections.forEach(sec => sec.classList.remove('active-section')); |
| document.getElementById(targetSectionId).classList.add('active-section'); |
| }); |
| }); |
|
|
| |
| function openModal() { modal.classList.add('active-modal'); } |
| function closeModal() { modal.classList.remove('active-modal'); } |
|
|
| showGuideBtn.addEventListener('click', openModal); |
| closeModalBtn.addEventListener('click', closeModal); |
| modal.addEventListener('click', (e) => { |
| |
| if (e.target === modal) closeModal(); |
| }); |
|
|
| saveConnectionBtn.addEventListener('click', () => { |
| const enteredUrl = apiUrlInput.value.trim(); |
| if (enteredUrl) { |
| localStorage.setItem('motif_api_url', enteredUrl); |
| config.localApiUrl = enteredUrl; |
| closeModal(); |
| alert(`Setup Complete! 🦄 Portal connected to backend at: ${enteredUrl}`); |
| } else { |
| alert('Please enter your local API address (e.g., http://localhost:7860)'); |
| } |
| }); |
|
|
| |
| function initializeCursorTrail() { |
| const trailContainer = document.getElementById('cursor-trail'); |
| const dots = []; |
| const numDots = 12; |
| |
| |
| for (let i = 0; i < numDots; i++) { |
| const dot = document.createElement('div'); |
| dot.className = 'trail-dot'; |
| dot.style.backgroundColor = getPastelColor(i); |
| trailContainer.appendChild(dot); |
| dots.push({ element: dot, x: 0, y: 0 }); |
| } |
|
|
| let mouseX = 0, mouseY = 0; |
|
|
| window.addEventListener('mousemove', (e) => { |
| mouseX = e.clientX; |
| mouseY = e.clientY; |
| }); |
|
|
| |
| function animateTrail() { |
| let x = mouseX; |
| let y = mouseY; |
| |
| dots.forEach((dot, index) => { |
| const nextDot = dots[index + 1] || dots[0]; |
| |
| dot.x = x; |
| dot.y = y; |
| dot.element.style.left = x + 'px'; |
| dot.element.style.top = y + 'px'; |
| dot.element.style.opacity = 1 - (index / numDots); |
|
|
| |
| x += (nextDot.x - x) * 0.3; |
| y += (nextDot.y - y) * 0.3; |
| }); |
| requestAnimationFrame(animateTrail); |
| } |
| animateTrail(); |
| } |
|
|
| function getPastelColor(index) { |
| const colors = ['#ffe6d9', '#d6eaff', '#fbe0e6', '#e1f7f1']; |
| return colors[index % colors.length]; |
| } |
|
|
| |
| const generateButtons = document.querySelectorAll('.generate-btn'); |
| generateButtons.forEach(btn => { |
| btn.addEventListener('click', handleGeneration); |
| }); |
|
|
| async function handleGeneration(e) { |
| if (!config.localApiUrl) { |
| alert("Wait! 🛑 To keep this portal unlimited and free, you must connect to your own powerful local computer first. Click 'Connection Guide'."); |
| openModal(); |
| return; |
| } |
|
|
| const outputArea = document.getElementById('video-output'); |
| |
| |
| outputArea.innerHTML = '<span class="status-text">Connecting to local GPU...</span><div class="loading-spinner"></div>'; |
| outputArea.closest('.animated-frame').classList.add('generating-active'); |
|
|
| |
| |
| console.log(`Sending generation request to local backend: ${config.localApiUrl}`); |
|
|
| |
| setTimeout(() => { |
| outputArea.innerHTML = ''; |
| |
| |
| const video = document.createElement('video'); |
| video.src = 'https://huggingface.co/Motif-Technologies/Motif-Video-2B/resolve/main/assets/banner.mp4'; |
| video.autoplay = true; |
| video.loop = true; |
| video.controls = true; |
| video.style.width = '100%'; |
| outputArea.appendChild(video); |
| |
| outputArea.closest('.animated-frame').classList.remove('generating-active'); |
| }, 4000); |
| } |