1export const initScrollDepthBanner = ({ 2 scrollDepth = 50, 3 showAgainAfterPageLoad = true, 4 hideDurationDays = 1 5} = {}) => { 6 console.log('[scrollDepthBanner] Initializing with options:', { scrollDepth, showAgainAfterPageLoad, hideDurationDays }); 7 8 const STORAGE_KEY = 'intel-snooze'; 9 const COOKIE_KEY = 'intel_snooze'; 10 11 const setCookie = (name, value, expiresAtMs) => { 12 const expires = new Date(expiresAtMs).toUTCString(); 13 document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/; SameSite=Lax`; 14 }; 15 16 const getCookie = (name) => { 17 const key = `${name}=`; 18 const cookie = document.cookie 19 .split(';') 20 .map((part) => part.trim()) 21 .find((part) => part.startsWith(key)); 22 23 if (!cookie) return null; 24 return decodeURIComponent(cookie.slice(key.length)); 25 }; 26 27 const setDismissUntil = (expiresAtMs) => { 28 const value = expiresAtMs.toString(); 29 30 try { 31 localStorage.setItem(STORAGE_KEY, value); 32 } catch (err) { 33 // Ignore storage quota/privacy mode errors and fall back to cookies. 34 } 35 36 setCookie(COOKIE_KEY, value, expiresAtMs); 37 }; 38 39 const getDismissUntil = () => { 40 try { 41 const stored = localStorage.getItem(STORAGE_KEY); 42 if (stored) return parseInt(stored, 10); 43 } catch (err) { 44 // Ignore storage access errors and fall back to cookies. 45 } 46 47 const cookieValue = getCookie(COOKIE_KEY); 48 return cookieValue ? parseInt(cookieValue, 10) : null; 49 }; 50 51 const el = document.querySelector('.scroll-depth-banner'); 52 const tag = document.querySelector('main .article-header .premium-intelligence-tag'); 53 const wall = document.querySelector('.paywall-block'); 54 55 const isLocalDev = window.location.href.includes('http://127.0.0.1'); 56 const isPermHidden = localStorage.getItem('intel-perm'); 57 58 // Check snooze expiry 59 const snoozeUntil = getDismissUntil(); 60 const isSnoozed = snoozeUntil && Date.now() < snoozeUntil; 61 62 // Check session 63 const isSessionHidden = !showAgainAfterPageLoad && sessionStorage.getItem('intel-sess'); 64 65 const isHidden = isLocalDev ? false : (isPermHidden || isSnoozed || isSessionHidden); 66 67 console.log('[scrollDepthBanner] el:', el); 68 console.log('[scrollDepthBanner] tag:', tag); 69 console.log('[scrollDepthBanner] wall:', wall); 70 console.log('[scrollDepthBanner] isLocalDev:', isLocalDev); 71 console.log('[scrollDepthBanner] isHidden:', isHidden); 72 73 if (!el || !tag || (wall && wall.offsetParent !== null) || isHidden) { 74 console.log('[scrollDepthBanner] Early exit - missing requirements or hidden'); 75 return; 76 } 77 78 console.log('[scrollDepthBanner] Setup complete, listening for scroll...'); 79 80 const handleScroll = () => { 81 const progress = (window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100; 82 // console.log('[scrollDepthBanner] Scroll progress:', progress.toFixed(2) + '%'); 83 if (progress >= scrollDepth) { 84 console.log('[scrollDepthBanner] Adding is-visible class...'); 85 el.classList.add('is-visible'); 86 console.log('[scrollDepthBanner] Banner should now be visible'); 87 window.removeEventListener('scroll', handleScroll); 88 } 89 }; 90 91 const dismiss = () => { 92 el.classList.remove('is-visible'); 93 94 if (hideDurationDays > 0) { 95 const expiry = Date.now() + (hideDurationDays * 24 * 60 * 60 * 1000); 96 setDismissUntil(expiry); 97 } else if (!showAgainAfterPageLoad) { 98 sessionStorage.setItem('intel-sess', '1'); 99 } 100 }; 101 102 103 const closeBtn = el.querySelector('.scroll-depth-banner-close'); 104 const hideBtn = el.querySelector('.scroll-depth-banner-hide'); 105 106 if (closeBtn) closeBtn.onclick = () => dismiss(); 107 if (hideBtn) hideBtn.onclick = () => dismiss(); 108 109 window.addEventListener('scroll', handleScroll); 110};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.