1const ReconnectOverlay = (() => { 2 'use strict'; 3 4 let _el = null; 5 let _wasOpen = false; 6 let _attemptEl = null; 7 let _titleEl = null; 8 let _subEl = null; 9 let _btnEl = null; 10 11 /** Ensure el â writes innerHTML, so anything user-supplied must be escaped first. */ 12 function _ensureEl() { 13 if (_el) return _el; 14 _el = document.createElement('div'); 15 _el.id = 'reconnect-overlay'; 16 _el.setAttribute('aria-live', 'polite'); 17 _el.setAttribute('role', 'status'); 18 _el.style.display = 'none'; 19 _el.innerHTML = ` 20 <div class="reconnect-card"> 21 <div class="reconnect-spinner" aria-hidden="true"></div> 22 <h3 class="reconnect-title"></h3> 23 <p class="reconnect-sub"></p> 24 <p class="reconnect-attempt" id="reconnect-attempt"></p> 25 <button class="btn btn-warning" onclick="returnToBattlefieldFromDisconnect()"></button> 26 </div>`; 27 document.body.appendChild(_el); 28 _attemptEl = _el.querySelector('#reconnect-attempt'); 29 _titleEl = _el.querySelector('.reconnect-title'); 30 _subEl = _el.querySelector('.reconnect-sub'); 31 _btnEl = _el.querySelector('.btn-warning'); 32 return _el; 33 } 34 35 function _hide() { 36 const el = _ensureEl(); 37 el.style.display = 'none'; 38 } 39 40 /** Refresh static text every show so locale swaps + late bundles get the right translation 41 * (innerHTML cached at first build). */ 42 function _show() { 43 const el = _ensureEl(); 44 if (_titleEl) _titleEl.textContent = t('reconnect.title'); 45 if (_subEl) _subEl.textContent = t('reconnect.body'); 46 if (_btnEl) _btnEl.textContent = t('reconnect.returnToBattlefield'); 47 el.style.display = 'flex'; 48 } 49 50 /** Active online match only â outside this set the corner NetworkStatus dot suffices. */ 51 function _isInOnlineMatch() { 52 if (typeof game === 'undefined' || typeof Phase === 'undefined') return false; 53 if (game.onlineMatchContext) return true; 54 const p = game.phase; 55 return p === Phase.ONLINE_COIN_FLIP 56 || p === Phase.ONLINE_MAP_SELECT 57 || p === Phase.ONLINE_RECRUIT 58 || p === Phase.ONLINE_DEPLOY 59 || p === Phase.ONLINE_REVEAL 60 || (p === Phase.PLAY && !!game.onlineMatchContext); 61 } 62 63 function _update() { 64 if (typeof Net === 'undefined') return; 65 const state = Net.getState(); 66 const attempt = (typeof Net.getReconnectAttempt === 'function') ? Net.getReconnectAttempt() : 0; 67 68 // Sign-out resets `_wasOpen` so the next sign-in doesn't flash the overlay during 'connecting'. 69 if (typeof game !== 'undefined' && typeof Phase !== 'undefined' && game.phase === Phase.AUTH) { 70 _wasOpen = false; 71 _hide(); 72 return; 73 } 74 75 if (state === 'open') { 76 _wasOpen = true; 77 _hide(); 78 return; 79 } 80 81 if (!_wasOpen) { _hide(); return; } 82 83 if (!_isInOnlineMatch()) { _hide(); return; } 84 85 // 'idle' happens briefly between login and the first connect â treat as hidden. 86 if (state === 'connecting' || state === 'reconnecting' || state === 'closed') { 87 _show(); 88 if (_attemptEl) { 89 _attemptEl.textContent = attempt > 1 90 ? t('reconnect.attempt', { n: attempt }) 91 : state === 'closed' ? t('reconnect.waitingToRetry') : t('reconnect.connecting'); 92 } 93 } else { 94 _hide(); 95 } 96 } 97 98 function _attach() { 99 if (typeof Net === 'undefined' || typeof Net.onStateChange !== 'function') { 100 // socket.js may not be loaded yet. 101 setTimeout(_attach, 50); 102 return; 103 } 104 Net.onStateChange(_update); 105 // Poll so the "Attempt N" counter ticks during backoff. 106 setInterval(_update, 1_000); 107 } 108 109 _attach(); 110 111 return { 112 _update, 113 _isShown: () => _el && _el.style.display !== 'none', 114 }; 115})(); 116 117window.ReconnectOverlay = ReconnectOverlay; 118 119/** 120 * Return to battlefield from disconnect â triggers a full re-render; navigates, so it pushes a 121 * history entry. 122 */ 123function returnToBattlefieldFromDisconnect() { 124 if (typeof game !== 'undefined') game.onlineMatchContext = null; 125 // User-initiated, so it goes through the choke point and pushes history. 126 if (typeof navigateTo === 'function' && typeof Phase !== 'undefined') { 127 navigateTo(Phase.BATTLEFIELD); 128 } else if (typeof render === 'function') { 129 render(); 130 } 131 // Hide eagerly so the button feels snappy. 132 const el = document.getElementById('reconnect-overlay'); 133 if (el) el.style.display = 'none'; 134}
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.