document.addEventListener('DOMContentLoaded', () => { // Basic interaction for toasts try { const toasts = document.querySelectorAll('.toast'); toasts.forEach(toastEl => { if (window.bootstrap && bootstrap.Toast) { const toast = new bootstrap.Toast(toastEl, { delay: 5000 }); toast.show(); } }); } catch (e) { console.error('Toast error:', e); } const html = document.documentElement; const updateIcons = (theme) => { const icons = document.querySelectorAll('#theme-toggle i, #theme-toggle-mobile i'); icons.forEach(icon => { if (theme === 'dark') { icon.className = 'fa-solid fa-sun'; } else { icon.className = 'fa-solid fa-moon'; } }); const textLabels = document.querySelectorAll('.theme-status-text'); textLabels.forEach(label => { label.textContent = theme === 'dark' ? 'Dark Mode' : 'Light Mode'; }); }; // Theme Toggle Logic const initThemeToggle = (btnId) => { const themeToggle = document.getElementById(btnId); if (!themeToggle) return; themeToggle.addEventListener('click', () => { const currentTheme = html.getAttribute('data-theme') || 'light'; const newTheme = currentTheme === 'dark' ? 'light' : 'dark'; html.setAttribute('data-theme', newTheme); updateIcons(newTheme); document.cookie = `theme=${newTheme}; path=/; max-age=${365 * 24 * 60 * 60}`; localStorage.setItem('theme', newTheme); }); }; // Unified AJAX Content Loader const loadContent = (url, updateUrl = true) => { const gridContainer = document.getElementById('apk-grid-container'); if (!gridContainer) return; gridContainer.style.opacity = '0.5'; gridContainer.style.pointerEvents = 'none'; fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(response => response.text()) .then(data => { gridContainer.innerHTML = data; gridContainer.style.opacity = '1'; gridContainer.style.pointerEvents = 'all'; if (updateUrl) { window.history.pushState({}, '', url); } // Scroll to grid top on mobile if needed if (window.innerWidth < 992) { const latestSection = document.getElementById('latest'); if (latestSection) { window.scrollTo({ top: latestSection.offsetTop - 100, behavior: 'smooth' }); } } }) .catch(err => { console.error('Fetch error:', err); gridContainer.style.opacity = '1'; gridContainer.style.pointerEvents = 'all'; }); }; // AJAX Category Filtering const initCategoryAjax = () => { document.addEventListener('click', (e) => { const filter = e.target.closest('.category-filter, .ajax-cat-link'); if (!filter) return; e.preventDefault(); const url = filter.getAttribute('href'); const categoryName = filter.textContent.trim(); const dropdownBtn = document.getElementById('category-dropdown-btn'); if (dropdownBtn && filter.classList.contains('category-filter')) { dropdownBtn.innerHTML = `${categoryName} `; } // Update active state for chips if they are chips if (filter.classList.contains('ajax-cat-link')) { document.querySelectorAll('.ajax-cat-link').forEach(btn => { btn.classList.remove('btn-success'); btn.classList.add('btn-light'); }); filter.classList.remove('btn-light'); filter.classList.add('btn-success'); } loadContent(url); // Close search overlay if open const searchOverlay = document.getElementById('search-overlay'); if (searchOverlay) searchOverlay.classList.remove('active'); }); }; // AJAX Search const initSearchAjax = () => { const searchForm = document.getElementById('ajax-search-form'); if (!searchForm) return; searchForm.addEventListener('submit', (e) => { e.preventDefault(); const formData = new FormData(searchForm); const query = formData.get('search'); const url = `/?search=${encodeURIComponent(query)}`; loadContent(url); const searchOverlay = document.getElementById('search-overlay'); if (searchOverlay) searchOverlay.classList.remove('active'); }); }; // Newsletter AJAX const initNewsletterAjax = () => { document.addEventListener('click', (e) => { const btn = e.target.closest('.newsletter-submit-btn'); if (!btn) return; const form = btn.closest('.newsletter-form') || btn.parentElement; const emailInput = form.querySelector('.newsletter-email'); const msg = form.querySelector('.newsletter-msg') || form.nextElementSibling; if (!emailInput) return; const email = emailInput.value; if (!email || !email.includes('@')) return; btn.disabled = true; const originalText = btn.innerHTML; btn.innerHTML = ''; fetch('/api/newsletter/subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email }) }) .then(res => res.json()) .then(data => { btn.disabled = false; btn.innerHTML = originalText; if (data.success) { if (msg) msg.innerHTML = `${data.success}`; else alert(data.success); emailInput.value = ''; } else { if (msg) msg.innerHTML = `${data.error}`; else alert(data.error); } }) .catch(err => { btn.disabled = false; btn.innerHTML = originalText; if (msg) msg.innerHTML = 'An error occurred.'; }); }); // Also handle form submit for the one in home.php document.addEventListener('submit', (e) => { if (e.target.classList.contains('newsletter-form')) { e.preventDefault(); const btn = e.target.querySelector('.newsletter-submit-btn'); if (btn) btn.click(); } }); }; // AI Chat Assistant Logic const initAIChat = () => { const toggleBtn = document.getElementById('toggle-ai-chat'); const closeBtn = document.getElementById('close-ai-chat'); const chatWindow = document.getElementById('ai-chat-window'); const chatInput = document.getElementById('ai-chat-input'); const sendBtn = document.getElementById('send-ai-chat'); const messagesContainer = document.getElementById('ai-chat-messages'); if (!toggleBtn || !chatWindow) return; toggleBtn.addEventListener('click', () => { chatWindow.classList.toggle('d-none'); if (!chatWindow.classList.contains('d-none')) { chatInput.focus(); } }); closeBtn.addEventListener('click', () => { chatWindow.classList.add('d-none'); }); const appendMessage = (message, isUser = false) => { const div = document.createElement('div'); div.className = 'mb-3 d-flex ' + (isUser ? 'justify-content-end' : ''); const content = document.createElement('div'); content.className = (isUser ? 'bg-success text-white' : 'bg-white') + ' p-3 rounded-4 shadow-sm small'; content.style.maxWidth = '85%'; content.style.borderBottomRightRadius = isUser ? '0' : 'inherit'; content.style.borderBottomLeftRadius = isUser ? 'inherit' : '0'; content.textContent = message; div.appendChild(content); messagesContainer.appendChild(div); messagesContainer.scrollTop = messagesContainer.scrollHeight; }; const sendMessage = () => { const message = chatInput.value.trim(); if (!message) return; appendMessage(message, true); chatInput.value = ''; const loadingDiv = document.createElement('div'); loadingDiv.className = 'mb-3 d-flex'; loadingDiv.innerHTML = '