1/** 2 * Online Indicator â site-wide tab presence (uses PupwifePresenceClient). 3 * Skips init on chatroom.html (ChatroomPresence owns that page). 4 */ 5 6window.ChatroomOnlineIndicator = (function() { 7 'use strict'; 8 9 function emitDevLog() { 10 if (typeof window !== 'undefined' && typeof window.devLog === 'function') { 11 window.devLog.apply(window, arguments); 12 } 13 } 14 15 let disposeTab = null; 16 let isInitialized = false; 17 18 function isChatroomPage() { 19 try { 20 return /chatroom\.html/i.test(window.location.pathname || ''); 21 } catch (e) { 22 return false; 23 } 24 } 25 26 function waitForPresenceClient(cb, attempts) { 27 attempts = attempts || 0; 28 if (window.PupwifePresenceClient && window.PupwifePresenceClient.startTabPresence) { 29 cb(); 30 return; 31 } 32 if (attempts > 80) return; 33 setTimeout(function() { waitForPresenceClient(cb, attempts + 1); }, 50); 34 } 35 36 function init() { 37 if (isInitialized) return; 38 if (isChatroomPage()) { 39 return; 40 } 41 if (typeof firebase === 'undefined' || !firebase.database) { 42 setTimeout(init, 100); 43 return; 44 } 45 46 waitForPresenceClient(function() { 47 if (isInitialized) return; 48 49 const checkUsername = setInterval(function() { 50 if (window.__sharedUsername) { 51 const u = window.__sharedUsername.get(); 52 if (u) { 53 clearInterval(checkUsername); 54 setupPresence(u); 55 isInitialized = true; 56 } 57 } 58 }, 100); 59 60 setTimeout(function() { 61 clearInterval(checkUsername); 62 if (!isInitialized && window.__sharedUsername) { 63 const u = window.__sharedUsername.get(); 64 if (u) { 65 setupPresence(u); 66 isInitialized = true; 67 } 68 } 69 }, 5000); 70 }); 71 } 72 73 function setupPresence(currentUsername) { 74 if (!currentUsername || !window.PupwifePresenceClient) return; 75 76 if (disposeTab) { 77 try { disposeTab(); } catch (e) {} 78 disposeTab = null; 79 } 80 81 disposeTab = window.PupwifePresenceClient.startTabPresence({ username: currentUsername }); 82 83 window.addEventListener('beforeunload', function() { 84 if (disposeTab) { 85 try { disposeTab(); } catch (e) {} 86 } 87 }); 88 89 emitDevLog('â Online indicator (tab presence) initialized for:', currentUsername); 90 } 91 92 function getUsername() { 93 return window.__sharedUsername ? window.__sharedUsername.get() : null; 94 } 95 96 function delayedInit() { 97 if (typeof firebase === 'undefined' || !firebase.database) { 98 setTimeout(delayedInit, 100); 99 return; 100 } 101 init(); 102 } 103 104 if (document.readyState === 'loading') { 105 document.addEventListener('DOMContentLoaded', function() { 106 setTimeout(delayedInit, 500); 107 }); 108 } else { 109 setTimeout(delayedInit, 500); 110 } 111 112 const publicAPI = { 113 getUsername: getUsername, 114 init: init 115 }; 116 117 window.ChatroomOnlineIndicator = publicAPI; 118 119 return publicAPI; 120})();
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.