mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
fix(modes): deep-linked mode scripts fail when body not yet parsed
ensureModeScript() used document.body.appendChild() to load lazy mode scripts, but the preload for ?mode= query params runs in <head> before <body> exists, causing all deep-linked modes to silently fail. Also fix cross-mode handoffs (BT→BT Locate, WiFi→WiFi Locate, Spy Stations→Waterfall) that assumed target module was already loaded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,31 +4,44 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>VESSEL RADAR // INTERCEPT - See the Invisible</title>
|
||||
<!-- Preconnect hints -->
|
||||
{% if offline_settings.assets_source != 'local' %}
|
||||
<link rel="preconnect" href="https://unpkg.com" crossorigin>
|
||||
{% endif %}
|
||||
{% if offline_settings.fonts_source != 'local' %}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
{% endif %}
|
||||
<link rel="preconnect" href="https://cartodb-basemaps-a.global.ssl.fastly.net" crossorigin>
|
||||
<!-- Fonts - Conditional CDN/Local loading -->
|
||||
{% if offline_settings.fonts_source == 'local' %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/fonts-local.css') }}">
|
||||
{% else %}
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
{% endif %}
|
||||
<!-- Leaflet.js - Conditional CDN/Local loading -->
|
||||
<!-- Leaflet CSS -->
|
||||
{% if offline_settings.assets_source == 'local' %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='vendor/leaflet/leaflet.css') }}">
|
||||
<script src="{{ url_for('static', filename='vendor/leaflet/leaflet.js') }}"></script>
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
{% endif %}
|
||||
<!-- Core CSS variables -->
|
||||
<!-- Core CSS -->
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/core/variables.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/ais_dashboard.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/responsive.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/core/layout.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/settings.css') }}?v={{ version }}&r=maptheme17">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/help-modal.css') }}">
|
||||
<!-- Deferred scripts -->
|
||||
<script>
|
||||
window.INTERCEPT_SHARED_OBSERVER_LOCATION = {{ shared_observer_location | tojson }};
|
||||
</script>
|
||||
<script src="{{ url_for('static', filename='js/core/observer-location.js') }}"></script>
|
||||
{% if offline_settings.assets_source == 'local' %}
|
||||
<script defer src="{{ url_for('static', filename='vendor/leaflet/leaflet.js') }}"></script>
|
||||
{% else %}
|
||||
<script defer src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
{% endif %}
|
||||
<script defer src="{{ url_for('static', filename='js/core/observer-location.js') }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Radar background effects -->
|
||||
@@ -393,6 +406,10 @@
|
||||
|
||||
// Initialize map
|
||||
async function initMap() {
|
||||
// Guard against double initialization (e.g. bfcache restore)
|
||||
const container = document.getElementById('vesselMap');
|
||||
if (!container || container._leaflet_id) return;
|
||||
|
||||
if (observerLocation) {
|
||||
document.getElementById('obsLat').value = observerLocation.lat;
|
||||
document.getElementById('obsLon').value = observerLocation.lon;
|
||||
@@ -406,18 +423,29 @@
|
||||
|
||||
// Use settings manager for tile layer (allows runtime changes)
|
||||
window.vesselMap = vesselMap;
|
||||
|
||||
// Add fallback tile layer immediately so the map is never blank
|
||||
const fallbackTiles = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OSM</a> © <a href="https://carto.com/">CARTO</a>',
|
||||
maxZoom: 19,
|
||||
subdomains: 'abcd',
|
||||
className: 'tile-layer-cyan'
|
||||
}).addTo(vesselMap);
|
||||
|
||||
// Then try to upgrade tiles via Settings (non-blocking)
|
||||
if (typeof Settings !== 'undefined') {
|
||||
// Wait for settings to load from server before applying tiles
|
||||
await Settings.init();
|
||||
Settings.createTileLayer().addTo(vesselMap);
|
||||
Settings.registerMap(vesselMap);
|
||||
} else {
|
||||
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OSM</a> © <a href="https://carto.com/">CARTO</a>',
|
||||
maxZoom: 19,
|
||||
subdomains: 'abcd',
|
||||
className: 'tile-layer-cyan'
|
||||
}).addTo(vesselMap);
|
||||
try {
|
||||
await Promise.race([
|
||||
Settings.init(),
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error('Settings timeout')), 5000))
|
||||
]);
|
||||
vesselMap.removeLayer(fallbackTiles);
|
||||
Settings.createTileLayer().addTo(vesselMap);
|
||||
Settings.registerMap(vesselMap);
|
||||
} catch (e) {
|
||||
console.warn('Settings init failed/timed out, using fallback tiles:', e);
|
||||
// fallback tiles already added above
|
||||
}
|
||||
}
|
||||
|
||||
// Add observer marker
|
||||
@@ -547,7 +575,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function startTracking() {
|
||||
async function startTracking() {
|
||||
const device = document.getElementById('aisDeviceSelect').value;
|
||||
const gain = document.getElementById('aisGain').value;
|
||||
|
||||
@@ -1502,6 +1530,13 @@
|
||||
// Auto-connect to gpsd if available
|
||||
autoConnectGps();
|
||||
});
|
||||
|
||||
// Clean up SSE connections on page unload to prevent orphaned streams
|
||||
window.addEventListener('pagehide', function() {
|
||||
if (eventSource) { eventSource.close(); eventSource = null; }
|
||||
if (dscEventSource) { dscEventSource.close(); dscEventSource = null; }
|
||||
if (gpsEventSource) { gpsEventSource.close(); gpsEventSource = null; }
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Agent styles -->
|
||||
|
||||
Reference in New Issue
Block a user