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) => { // Update all theme toggle icons 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'; } }); // Update all theme status texts 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'; // Update UI html.setAttribute('data-theme', newTheme); // Update All Icons and Labels updateIcons(newTheme); // Save preference document.cookie = `theme=${newTheme}; path=/; max-age=${365 * 24 * 60 * 60}`; localStorage.setItem('theme', newTheme); }); }; // AJAX Category Filtering const initCategoryAjax = () => { const filters = document.querySelectorAll('.category-filter'); const gridContainer = document.getElementById('apk-grid-container'); const dropdownBtn = document.getElementById('category-dropdown-btn'); const latestTitle = document.getElementById('latest-title'); if (!gridContainer || filters.length === 0) return; filters.forEach(filter => { filter.addEventListener('click', (e) => { e.preventDefault(); const category = filter.getAttribute('data-category'); const url = filter.getAttribute('href'); const categoryName = filter.textContent; // Update UI state gridContainer.style.opacity = '0.5'; gridContainer.style.pointerEvents = 'none'; // Fetch data fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(response => response.text()) .then(data => { gridContainer.innerHTML = data; gridContainer.style.opacity = '1'; gridContainer.style.pointerEvents = 'all'; // Update dropdown button text if (dropdownBtn) { dropdownBtn.innerHTML = `${categoryName} `; } // Update title if not searching if (latestTitle && !url.includes('search=')) { // We could use translations here but for simplicity we'll just use the category name // if it's All Categories, we'll reset to original (usually "Latest APKs") // However, we'll just keep it simple for now. } // Update URL without refreshing window.history.pushState({ category: category }, '', url); }) .catch(err => { console.error('Fetch error:', err); gridContainer.style.opacity = '1'; gridContainer.style.pointerEvents = 'all'; }); }); }); // Handle browser back/forward window.addEventListener('popstate', (e) => { window.location.reload(); // Simple solution for now }); }; // Initial Sync const currentTheme = html.getAttribute('data-theme') || 'light'; updateIcons(currentTheme); // Sync theme from localStorage if cookie is missing but localStorage has it const savedTheme = localStorage.getItem('theme'); const currentCookie = document.cookie.split('; ').find(row => row.startsWith('theme='))?.split('=')[1]; if (savedTheme && !currentCookie) { html.setAttribute('data-theme', savedTheme); updateIcons(savedTheme); document.cookie = `theme=${savedTheme}; path=/; max-age=${365 * 24 * 60 * 60}`; } initThemeToggle('theme-toggle'); initThemeToggle('theme-toggle-mobile'); initCategoryAjax(); console.log('ApkNusa ready.'); });