Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 69 additions & 2 deletions src/scout_sensor_demo_map/templates/index.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,53 @@
#aviation-overview li:hover {
background-color: rgba(255, 255, 255, 0.2);
}

/* Shown (and covering everything else) only when WebGL is unavailable */
#webgl-error {
position: fixed;
inset: 0;
z-index: 10;
background: #1a1a1a;
color: white;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
font-family: sans-serif;
}

#webgl-error[hidden] {
display: none;
}

.webgl-error-box {
max-width: 520px;
background: rgba(0, 0, 0, 0.7);
border-radius: 5px;
padding: 20px 25px;
line-height: 1.5;
}

.webgl-error-box h1 {
margin-top: 0;
font-size: 1.4em;
}
</style>
</head>

<body>

<div id="webgl-error" hidden>
<div class="webgl-error-box">
<h1>WebGL is not available</h1>
<p>This map is drawn with WebGL, but your browser could not create a WebGL
context, so the map and the live targets cannot be displayed.</p>
<p>Please open this page in a browser with WebGL support (a current Firefox,
Chrome, Edge or Safari) and check that hardware acceleration / WebGL is not
disabled in its settings.</p>
</div>
</div>

<div id="map"></div>
<div id="ws-status">
<p class="overview-title"><strong>Configuration</strong></p>
Expand Down Expand Up @@ -182,8 +224,30 @@
// Injected by server from X-Forwarded-Prefix header
const BASE_PATH = {{ prefix | tojson }};

function webglSupported() {
// MapLibre's own probe knows which extensions it actually needs
if (typeof maplibregl !== 'undefined' && typeof maplibregl.supported === 'function') {
return maplibregl.supported();
}
try {
const canvas = document.createElement('canvas');
return !!(window.WebGLRenderingContext &&
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
} catch (e) {
return false;
}
}

// Without WebGL the map cannot be created — show the error instead and keep
// the rest of the page inert (map stays null, nothing connects).
const WEBGL_OK = webglSupported();
if (!WEBGL_OK) {
document.getElementById('webgl-error').hidden = false;
console.error("WebGL is not available — the map cannot be displayed.");
}

// Initialize the map using MapLibre GL JS with OSM road tiles
const map = new maplibregl.Map({
const map = !WEBGL_OK ? null : new maplibregl.Map({
container: 'map',
style: {
"version": 8,
Expand Down Expand Up @@ -663,7 +727,7 @@
}
}

map.on('load', () => {
map?.on('load', () => {
for (const uasid of Object.keys(uasPaths)) {
ensurePathLayer(uasid);
}
Expand Down Expand Up @@ -955,6 +1019,9 @@
}

window.addEventListener('load', () => {
if (!WEBGL_OK) {
return;
}
document.getElementById('connect-button').addEventListener('click', connect);
zoomToLocaleCountry();
document.getElementById('autocenter').checked = centerAutomatically;
Expand Down
34 changes: 33 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
from playwright.sync_api import Page, expect
from playwright.sync_api import Page, WebSocket, expect

# Makes every WebGL context request fail, the way a browser without WebGL support does
NO_WEBGL = """
delete window.WebGLRenderingContext;
delete window.WebGL2RenderingContext;
const realGetContext = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function (type, ...rest) {
if (typeof type === "string" && type.toLowerCase().includes("webgl")) {
return null;
}
return realGetContext.call(this, type, ...rest);
};
"""


def test_page_loads(live_server_url: str, page: Page) -> None:
page.goto(live_server_url)
expect(page.locator("#map")).to_be_visible()
expect(page.locator("#connect-button")).to_be_visible()
expect(page.locator("#receiver-status")).to_be_visible()
expect(page.locator("#webgl-error")).to_be_hidden()


def test_webgl_error_shown_without_webgl(live_server_url: str, page: Page) -> None:
sockets: list[WebSocket] = []
page.on("websocket", lambda ws: sockets.append(ws))
page.add_init_script(NO_WEBGL)

page.goto(live_server_url)

error = page.locator("#webgl-error")
expect(error).to_be_visible()
expect(error).to_contain_text("WebGL")
expect(error).to_contain_text("browser")

# the page stays inert - no connection is attempted (the other tests show that a
# working page connects well within this window)
page.wait_for_timeout(2000)
assert not sockets, f"page opened websockets without WebGL: {[ws.url for ws in sockets]}"


def test_websockets_connect(live_server_url: str, page: Page) -> None:
Expand Down
Loading