snippet for each zone // 3. Paste zone #1's snippet inside
in the HTML (near the top of ) // 4. Paste zone #2's snippet inside
// That's it - this function handles the 10s timing + switching between them automatically. const LAUNCH_AD_SECONDS = 10; function playLaunchAds(onComplete) { const zone1 = document.getElementById('adZone1'); const zone2 = document.getElementById('adZone2'); const hasAds = (zone1 && zone1.innerHTML.trim()) || (zone2 && zone2.innerHTML.trim()); if (!hasAds) { onComplete(); return; } // no ad codes pasted yet - skip straight into the app const overlay = document.getElementById('launchAdOverlay'); const counterEl = document.getElementById('adCounter'); const countdownEl = document.getElementById('adCountdown'); overlay.classList.remove('hidden'); let step = 1; let remaining = LAUNCH_AD_SECONDS; counterEl.textContent = '1'; countdownEl.textContent = remaining; zone1.style.display = ''; zone2.style.display = 'none'; const timer = setInterval(() => { remaining--; countdownEl.textContent = Math.max(remaining, 0); if (remaining <= 0) { if (step === 1 && zone2 && zone2.innerHTML.trim()) { // move to ad #2 step = 2; remaining = LAUNCH_AD_SECONDS; counterEl.textContent = '2'; countdownEl.textContent = remaining; zone1.style.display = 'none'; zone2.style.display = ''; } else { // done - close overlay and load the app clearInterval(timer); overlay.classList.add('hidden'); onComplete(); } } }, 1000); } // ==================== VOICE ==================== function initVoice() { const btn = document.getElementById('voiceBtn'); const input = document.getElementById('searchInput'); if (!('webkitSpeechRecognition' in window)) { btn.style.opacity = '0.3'; return; } const rec = new webkitSpeechRecognition(); rec.lang = 'en-US'; rec.continuous = false; rec.interimResults = false; btn.onclick = () => { rec.start(); btn.classList.add('active'); }; rec.onresult = (e) => { const text = e.results[0][0].transcript; input.value = text; btn.classList.remove('active'); performSearch(text); }; rec.onerror = () => btn.classList.remove('active'); rec.onend = () => btn.classList.remove('active'); } // ==================== SEARCH ==================== async function performSearch(q) { state.query = q; incrementTopicWeight(q, 3); resetFeedSources([{ q }]); const container = document.getElementById('tab-home'); container.innerHTML = '

Searching...

'; const items = await fetchFeedBatch(); const loadingEl = container.querySelector('.feed-loading'); if (loadingEl) loadingEl.remove(); await renderHome({ items }, false); showTab('home'); document.getElementById('searchInput').value = q; } // ==================== LOGIN MODAL ==================== function openLoginModal() { document.getElementById('modalOverlay').classList.remove('hidden'); document.getElementById('modalEmail').value = ''; document.getElementById('modalPassword').value = ''; document.getElementById('modalName').value = ''; document.getElementById('modalColor').value = '#cc0000'; document.getElementById('emailError').classList.remove('show'); document.getElementById('passError').classList.remove('show'); document.getElementById('modalEmail').classList.remove('error'); document.getElementById('modalPassword').classList.remove('error'); document.getElementById('nameGroup').style.display = 'none'; document.getElementById('colorGroup').style.display = 'none'; document.getElementById('switchMode').style.display = 'block'; document.getElementById('switchMode').textContent = 'Create account'; document.getElementById('modalTitle').textContent = 'Sign in'; document.getElementById('modalSubtitle').textContent = 'to continue to YouTubePC'; document.getElementById('modalSave').textContent = 'Sign In'; state.isSignUp = false; } function validateEmail(email) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } function handleLogin() { const email = document.getElementById('modalEmail').value.trim(); const password = document.getElementById('modalPassword').value.trim(); const name = document.getElementById('modalName').value.trim(); const color = document.getElementById('modalColor').value; let valid = true; if (!email || !validateEmail(email)) { document.getElementById('emailError').classList.add('show'); document.getElementById('modalEmail').classList.add('error'); valid = false; } else { document.getElementById('emailError').classList.remove('show'); document.getElementById('modalEmail').classList.remove('error'); } if (!password || password.length < 6) { document.getElementById('passError').classList.add('show'); document.getElementById('modalPassword').classList.add('error'); valid = false; } else { document.getElementById('passError').classList.remove('show'); document.getElementById('modalPassword').classList.remove('error'); } if (!valid) return; // Save user state.user = { email: email, name: name || email.split('@')[0], color: color, password: password }; saveUser(); document.getElementById('modalOverlay').classList.add('hidden'); updateUI(); openInterestModal(); } function handleSignUp() { const email = document.getElementById('modalEmail').value.trim(); const password = document.getElementById('modalPassword').value.trim(); const name = document.getElementById('modalName').value.trim(); const color = document.getElementById('modalColor').value; let valid = true; if (!email || !validateEmail(email)) { document.getElementById('emailError').classList.add('show'); document.getElementById('modalEmail').classList.add('error'); valid = false; } else { document.getElementById('emailError').classList.remove('show'); document.getElementById('modalEmail').classList.remove('error'); } if (!password || password.length < 6) { document.getElementById('passError').classList.add('show'); document.getElementById('modalPassword').classList.add('error'); valid = false; } else { document.getElementById('passError').classList.remove('show'); document.getElementById('modalPassword').classList.remove('error'); } if (!valid) return; // Save user state.user = { email: email, name: name || email.split('@')[0], color: color, password: password }; saveUser(); document.getElementById('modalOverlay').classList.add('hidden'); updateUI(); openInterestModal(); } // ==================== UI ==================== function updateUI() { const signin = document.getElementById('signinBtn'); const avatar = document.getElementById('avatarBtn'); if (state.user) { signin.style.display = 'none'; avatar.style.display = 'flex'; document.getElementById('avatarText').textContent = state.user.name[0].toUpperCase(); avatar.style.background = state.user.color; } else { signin.style.display = 'flex'; avatar.style.display = 'none'; } if (state.settings.theme === 'light') { document.body.classList.add('light'); } else { document.body.classList.remove('light'); } } // ==================== EVENTS ==================== document.addEventListener('DOMContentLoaded', () => { // Bottom Navigation document.querySelectorAll('.bottom-btn').forEach(el => { el.onclick = () => { const tab = el.dataset.tab; if (tab === 'home') { if (state.query) performSearch(state.query); else buildHomeFeed(); } else if (tab === 'shorts') renderShorts(); else if (tab === 'trending') renderTrending(); else if (tab === 'watchlater') renderWatchLater(); else if (tab === 'history') renderHistory(); else if (tab === 'settings') renderSettings(); showTab(tab); }; }); // Logo document.getElementById('logoLink').onclick = (e) => { e.preventDefault(); state.query = ''; document.getElementById('searchInput').value = ''; buildHomeFeed(); showTab('home'); }; // Search document.getElementById('searchBtn').onclick = () => { const q = document.getElementById('searchInput').value.trim(); if (q) performSearch(q); }; document.getElementById('searchInput').onkeyup = (e) => { if (e.key === 'Enter') { const q = document.getElementById('searchInput').value.trim(); if (q) performSearch(q); } }; // Hamburger - toggle ads document.getElementById('hamburger').onclick = () => { document.querySelectorAll('.ad-left, .ad-right').forEach(el => { el.style.display = el.style.display === 'none' ? '' : 'none'; }); }; // Sign in - Real Gmail style document.getElementById('signinBtn').onclick = openLoginModal; document.getElementById('modalClose').onclick = () => { document.getElementById('modalOverlay').classList.add('hidden'); }; document.getElementById('modalSave').onclick = () => { if (state.isSignUp) { handleSignUp(); } else { handleLogin(); } }; // Switch between Sign In and Sign Up document.getElementById('switchMode').onclick = function() { state.isSignUp = !state.isSignUp; if (state.isSignUp) { this.textContent = 'Sign in instead'; document.getElementById('modalTitle').textContent = 'Create account'; document.getElementById('modalSubtitle').textContent = 'to continue to YouTubePC'; document.getElementById('modalSave').textContent = 'Sign Up'; document.getElementById('nameGroup').style.display = 'block'; document.getElementById('colorGroup').style.display = 'flex'; } else { this.textContent = 'Create account'; document.getElementById('modalTitle').textContent = 'Sign in'; document.getElementById('modalSubtitle').textContent = 'to continue to YouTubePC'; document.getElementById('modalSave').textContent = 'Sign In'; document.getElementById('nameGroup').style.display = 'none'; document.getElementById('colorGroup').style.display = 'none'; } }; // Enter key on modal document.getElementById('modalPassword').onkeyup = (e) => { if (e.key === 'Enter') { if (state.isSignUp) { handleSignUp(); } else { handleLogin(); } } }; // Avatar document.getElementById('avatarBtn').onclick = (e) => { document.getElementById('avatarDropdown').classList.toggle('show'); e.stopPropagation(); }; document.onclick = () => { document.getElementById('avatarDropdown').classList.remove('show'); }; document.querySelectorAll('#avatarDropdown .item').forEach(el => { el.onclick = () => { const action = el.dataset.action; if (action === 'history') renderHistory(); else if (action === 'watchlater') renderWatchLater(); else if (action === 'settings') renderSettings(); else if (action === 'signout') { state.user = null; saveUser(); updateUI(); buildHomeFeed(); } document.getElementById('avatarDropdown').classList.remove('show'); }; }); // Notification document.getElementById('notifBtn').onclick = () => { alert('No new notifications'); }; // Fullscreen document.addEventListener('fullscreenchange', () => { state.fullscreen = !!document.fullscreenElement; toggleAds(state.fullscreen); }); // Mini player document.getElementById('miniClose').onclick = closeMini; // Voice initVoice(); // Load YouTube API const script = document.createElement('script'); script.src = 'https://www.youtube.com/iframe_api'; document.head.appendChild(script); // Infinite scroll - automatically loads more of the home feed as user scrolls down document.getElementById('contentArea').addEventListener('scroll', () => { if (state.currentTab !== 'home') return; const el = document.getElementById('contentArea'); if (el.scrollTop + el.clientHeight >= el.scrollHeight - 600) { loadMoreFeed(); } }); // Initial load - launch ads play first (if configured), then the app loads updateUI(); playLaunchAds(() => { buildHomeFeed(); showTab('home'); }); }); window.onYouTubeIframeAPIReady = function() { console.log('YouTube API ready'); }; console.log('YouTubePC - Real Gmail login, bottom navigation, working buttons');