1(function (root, factory) { 2 if (typeof module === 'object' && module.exports) { 3 module.exports = factory(); 4 } else { 5 root.IntelDeskMobileContinuity = factory(); 6 } 7})(typeof self !== 'undefined' ? self : this, function () { 8 'use strict'; 9 10 var SNAPSHOT_KEY = 'inteldesk_mobile_snapshot_v1'; 11 var RESUME_STATE_KEY = 'inteldesk_resume_state_v1'; 12 var ALLOWED_PANELS = { 13 feeds: true, 14 market: true, 15 alerts: true, 16 portfolio: true, 17 saved: true, 18 osint: true, 19 map: true, 20 polymarket: true, 21 more: true, 22 }; 23 var ALLOWED_FOCUS = { 24 briefing: true, 25 portfolio: true, 26 saved: true, 27 alerts: true, 28 }; 29 30 function toArray(value) { 31 return Array.isArray(value) ? value : []; 32 } 33 34 function toNumber(value, fallback) { 35 var n = Number(value); 36 return Number.isFinite(n) ? n : fallback || 0; 37 } 38 39 function trim(value, maxLen) { 40 var str = String(value || '').trim(); 41 if (!str) return ''; 42 if (str.length <= maxLen) return str; 43 return str.slice(0, maxLen - 1).trimEnd() + 'â¦'; 44 } 45 46 function normalizePanel(value) { 47 var key = String(value || '') 48 .trim() 49 .toLowerCase(); 50 return ALLOWED_PANELS[key] ? key : ''; 51 } 52 53 function normalizeFocus(value) { 54 var key = String(value || '') 55 .trim() 56 .toLowerCase(); 57 return ALLOWED_FOCUS[key] ? key : ''; 58 } 59 60 function normalizeQueueItems(entries) { 61 return toArray(entries) 62 .slice(0, 3) 63 .map(function (entry) { 64 var item = entry && entry.item ? entry.item : entry || {}; 65 var alerts = toArray(item && item.alerts); 66 var level = trim((entry && entry.level) || (item && item.level) || '', 20).toLowerCase(); 67 if (!level) { 68 if ( 69 alerts.some(function (alert) { 70 return alert && alert.level === 'critical'; 71 }) 72 ) 73 level = 'critical'; 74 else if ( 75 alerts.some(function (alert) { 76 return alert && alert.level === 'high'; 77 }) 78 ) 79 level = 'high'; 80 } 81 return { 82 title: trim(item && item.title, 132), 83 source: trim(item && item.source, 40), 84 level: level, 85 timestamp: toNumber(item && item.timestamp, 0), 86 matches: toArray(entry && entry.matches) 87 .slice(0, 3) 88 .map(function (match) { 89 return trim(match, 20).toUpperCase(); 90 }) 91 .filter(Boolean), 92 }; 93 }) 94 .filter(function (entry) { 95 return !!entry.title; 96 }); 97 } 98 99 function normalizeSnapshot(raw) { 100 if (!raw || typeof raw !== 'object') return null; 101 var stats = raw.stats && typeof raw.stats === 'object' ? raw.stats : {}; 102 var band = trim(raw.band || 'DIPLOMATIC', 32).toUpperCase() || 'DIPLOMATIC'; 103 var bandTone = trim(raw.bandTone || 'diplomatic', 24).toLowerCase() || 'diplomatic'; 104 return { 105 snapshotAt: toNumber(raw.snapshotAt, 0), 106 band: band, 107 bandTone: bandTone, 108 primaryTitle: trim(raw.primaryTitle, 180), 109 summaryLine: trim(raw.summaryLine, 220), 110 stats: { 111 pending: Math.max(0, toNumber(stats.pending, 0)), 112 critical: Math.max(0, toNumber(stats.critical, 0)), 113 portfolioHits: Math.max(0, toNumber(stats.portfolioHits, 0)), 114 contested: Math.max(0, toNumber(stats.contested, 0)), 115 }, 116 queueItems: normalizeQueueItems(raw.queueItems), 117 briefingBullets: toArray(raw.briefingBullets) 118 .slice(0, 3) 119 .map(function (line) { 120 return trim(line, 120); 121 }) 122 .filter(Boolean), 123 contradiction: trim(raw.contradiction, 120), 124 actionPath: trim(raw.actionPath, 160), 125 lastMobileTab: normalizePanel(raw.lastMobileTab) || 'feeds', 126 currentFilter: trim(raw.currentFilter || 'all', 32) || 'all', 127 criticalMode: !!raw.criticalMode, 128 reason: trim(raw.reason, 48), 129 }; 130 } 131 132 function normalizeResumeState(raw) { 133 var source = raw && typeof raw === 'object' ? raw : {}; 134 return { 135 savedAt: toNumber(source.savedAt, 0),
136 lastMobileTab: normalizePanel(source.lastMobileTab) || 'feeds', 137 currentFilter: trim(source.currentFilter || 'all', 32) || 'all', 138 criticalMode: !!source.criticalMode, 139 standalone: !!source.standalone, 140 reason: trim(source.reason, 48), 141 }; 142 } 143 144 function buildContinuitySnapshot(input) { 145 var source = input && typeof input === 'object' ? input : {}; 146 var model = source.model && typeof source.model === 'object' ? source.model : {}; 147 return normalizeSnapshot({ 148 snapshotAt: toNumber(source.now, Date.now()), 149 band: model.band, 150 bandTone: model.bandTone, 151 primaryTitle: model.primaryTitle, 152 summaryLine: model.summaryLine, 153 stats: model.stats, 154 queueItems: model.queueItems, 155 briefingBullets: model.briefingBullets, 156 contradiction: model.contradiction, 157 actionPath: model.actionPath, 158 lastMobileTab: source.currentMobileTab, 159 currentFilter: source.currentFilter, 160 criticalMode: source.criticalMode, 161 reason: source.reason, 162 }); 163 } 164 165 function parseLaunchState(inputUrl) { 166 var launch = { 167 panel: '', 168 focus: '', 169 criticalMode: false, 170 }; 171 try { 172 var url = new URL(inputUrl, 'https://www.inteldesk.app/dashboard'); 173 launch.panel = normalizePanel(url.searchParams.get('mobile') || url.searchParams.get('panel')); 174 launch.focus = normalizeFocus(url.searchParams.get('focus')); 175 launch.criticalMode = 176 String(url.searchParams.get('mode') || '') 177 .trim() 178 .toLowerCase() === 'critical' || url.searchParams.get('critical') === '1'; 179 } catch (_e) { 180 return launch; 181 } 182 return launch; 183 } 184 185 var api = { 186 SNAPSHOT_KEY: SNAPSHOT_KEY, 187 RESUME_STATE_KEY: RESUME_STATE_KEY, 188 buildContinuitySnapshot: buildContinuitySnapshot, 189 normalizeResumeState: normalizeResumeState, 190 normalizeSnapshot: normalizeSnapshot, 191 parseLaunchState: parseLaunchState, 192 }; 193 194 if (typeof window === 'undefined' || !window.document) { 195 return api; 196 } 197 198 var lastCaptureAt = 0; 199 200 function lsGetString(key, fallback) { 201 if (typeof lsGet === 'function') return lsGet(key, fallback); 202 try { 203 return window.localStorage.getItem(key); 204 } catch (_e) { 205 return fallback; 206 } 207 } 208 209 function readJson(key, fallback) { 210 if (typeof lsGetJSON === 'function') return lsGetJSON(key, fallback); 211 try { 212 var raw = window.localStorage.getItem(key); 213 return raw ? JSON.parse(raw) : fallback; 214 } catch (_e) { 215 return fallback; 216 } 217 } 218 219 function writeJson(key, value) { 220 if (typeof lsSet === 'function') { 221 lsSet(key, value); 222 return; 223 } 224 try { 225 window.localStorage.setItem(key, JSON.stringify(value)); 226 } catch (_e) { 227 /* ignore */ 228 } 229 } 230 231 function isStandalone() { 232 return ( 233 (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) || 234 window.navigator.standalone === true 235 ); 236 } 237 238 function currentMobileTabValue() { 239 if (typeof currentMobileTab === 'string' && currentMobileTab) return currentMobileTab; 240 return normalizePanel(lsGetString('id:mobileTab', 'feeds')) || 'feeds'; 241 } 242 243 function currentFilterValue() { 244 if (typeof currentFilter === 'string' && currentFilter) return currentFilter; 245 return trim(lsGetString('inteldesk_feedFilter', 'all') || 'all', 32) || 'all'; 246 } 247 248 function readSnapshot() { 249 return normalizeSnapshot(readJson(SNAPSHOT_KEY, null)); 250 } 251 252 function readResumeState() { 253 return normalizeResumeState(readJson(RESUME_STATE_KEY, null)); 254 } 255 256 function saveSnapshot(snapshot) { 257 var normalized = normalizeSnapshot(snapshot); 258 if (!normalized) return null; 259 writeJson(SNAPSHOT_KEY, normalized); 260 return normalized; 261 } 262 263 function saveResumeState(resumeState) { 264 var normalized = normalizeResumeState(resumeState); 265 writeJson(RESUME_STATE_KEY, normalized); 266 return normalized; 267 } 268 269 function buildSnapshotFromGlobals(reason) { 270 if (!window.__intelDeskLastCommandDeckModel) return null; 271 return buildContinuitySnapshot({ 272 model: window.__intelDeskLastCommandDeckModel, 273 currentMobileTab: currentMobileTabValue(), 274 currentFilter: currentFilterValue(), 275 criticalMode: lsGetString('inteldesk_critical_mode') === 'true', 276 reason: reason || '', 277 now: Date.now(), 278 }); 279 } 280 281 function shouldThrottle(reason) { 282 return reason === 'boot' || reason === 'command-deck' || reason === 'briefing'; 283 } 284 285 function captureState(reason) { 286 var now = Date.now();
287 if (shouldThrottle(reason) && now - lastCaptureAt < 30000) { 288 return { 289 snapshot: readSnapshot(), 290 resume: readResumeState(), 291 }; 292 } 293 294 var resume = saveResumeState({ 295 savedAt: now, 296 lastMobileTab: currentMobileTabValue(), 297 currentFilter: currentFilterValue(), 298 criticalMode: lsGetString('inteldesk_critical_mode') === 'true', 299 standalone: isStandalone(), 300 reason: reason || '', 301 }); 302 var snapshot = buildSnapshotFromGlobals(reason); 303 if (snapshot) saveSnapshot(snapshot); 304 lastCaptureAt = now; 305 return { 306 snapshot: snapshot, 307 resume: resume, 308 }; 309 } 310 311 function findMobileTabEl(panel) { 312 return ( 313 document.querySelector('.mobile-nav-tab[data-panel="' + panel + '"]') || 314 document.querySelector('.mobile-nav-tab[data-panel="more"]') 315 ); 316 } 317 318 function applyFocus(focus) { 319 if (!focus) return; 320 if (focus === 'briefing' && typeof openBriefingPanel === 'function') { 321 openBriefingPanel(); 322 return; 323 } 324 if (window.innerWidth > 1023 || typeof switchMobileTab !== 'function') return; 325 if (focus === 'portfolio') { 326 switchMobileTab('portfolio', findMobileTabEl('portfolio')); 327 return; 328 } 329 if (focus === 'saved') { 330 switchMobileTab('saved', findMobileTabEl('saved')); 331 return; 332 } 333 if (focus === 'alerts') { 334 switchMobileTab('alerts', findMobileTabEl('alerts')); 335 } 336 } 337 338 function applyLaunchState() { 339 var launch = parseLaunchState(window.location.href); 340 if (!launch.panel && !launch.focus && !launch.criticalMode) return launch; 341 342 setTimeout(function () { 343 if (launch.criticalMode && typeof toggleCriticalMode === 'function') { 344 toggleCriticalMode(true); 345 } 346 if (launch.panel && window.innerWidth <= 1023 && typeof switchMobileTab === 'function') { 347 switchMobileTab(launch.panel, findMobileTabEl(launch.panel)); 348 } 349 if (launch.focus) applyFocus(launch.focus); 350 }, 450); 351 352 return launch; 353 } 354 355 window.captureMobileContinuityState = captureState; 356 window.readMobileContinuitySnapshot = readSnapshot; 357 window.readMobileResumeState = readResumeState; 358 window.resumeMobileDesk = function () { 359 var resume = readResumeState(); 360 if (resume.criticalMode && typeof toggleCriticalMode === 'function') { 361 toggleCriticalMode(true); 362 } 363 if (window.innerWidth <= 1023 && typeof switchMobileTab === 'function') { 364 switchMobileTab(resume.lastMobileTab, findMobileTabEl(resume.lastMobileTab)); 365 } 366 }; 367 368 api.readSnapshot = readSnapshot; 369 api.readResumeState = readResumeState; 370 api.captureState = captureState; 371 api.applyLaunchState = applyLaunchState; 372 373 document.addEventListener('DOMContentLoaded', function () { 374 setTimeout(applyLaunchState, 200); 375 setTimeout(function () { 376 captureState('boot'); 377 }, 1800); 378 }); 379 380 document.addEventListener('visibilitychange', function () { 381 if (document.hidden) captureState('background'); 382 }); 383 384 window.addEventListener('pagehide', function () { 385 captureState('pagehide'); 386 }); 387 388 document.addEventListener('inteldesk:command-deck-update', function () { 389 captureState('command-deck'); 390 }); 391 392 document.addEventListener('inteldesk:briefing-update', function () { 393 captureState('briefing'); 394 }); 395 396 return api; 397});
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.