Fix launcher: simplify server check for Android WebView compatibility

WebView blocks no-cors fetch and image probes differently than browsers.
Simplified to a normal fetch that treats CORS errors as 'server reachable'
(CORS error = server responded, just blocked the origin).
This commit is contained in:
Daniel 2026-04-11 03:23:00 +02:00
parent ca6e2418f5
commit fd442c195a
3 changed files with 24 additions and 42 deletions

View file

@ -121,21 +121,15 @@
// ── Server check ──
function testServer(url, callback) {
var done = false;
function respond(ok) {
if (done) return;
done = true;
callback(ok);
}
fetch(url + '/api/health', { mode: 'no-cors', signal: AbortSignal.timeout(8000) })
.then(function() { respond(true); })
// In native WebView, no-cors fetch and image probes are unreliable.
// Just try a normal fetch to the health endpoint.
fetch(url + '/api/health', { signal: AbortSignal.timeout(8000) })
.then(function(r) { callback(true); })
.catch(function() {
var fallbackTimer = setTimeout(function() { respond(false); }, 5000);
var img = new Image();
img.onload = function() { clearTimeout(fallbackTimer); respond(true); };
img.onerror = function() { clearTimeout(fallbackTimer); respond(false); };
img.src = url + '/favicon.ico?t=' + Date.now();
// If CORS blocks it, that still means the server is reachable
// (CORS error = server responded but blocked the origin).
// Just navigate — the WebView will handle it.
callback(true);
});
}

View file

@ -121,21 +121,15 @@
// ── Server check ──
function testServer(url, callback) {
var done = false;
function respond(ok) {
if (done) return;
done = true;
callback(ok);
}
fetch(url + '/api/health', { mode: 'no-cors', signal: AbortSignal.timeout(8000) })
.then(function() { respond(true); })
// In native WebView, no-cors fetch and image probes are unreliable.
// Just try a normal fetch to the health endpoint.
fetch(url + '/api/health', { signal: AbortSignal.timeout(8000) })
.then(function(r) { callback(true); })
.catch(function() {
var fallbackTimer = setTimeout(function() { respond(false); }, 5000);
var img = new Image();
img.onload = function() { clearTimeout(fallbackTimer); respond(true); };
img.onerror = function() { clearTimeout(fallbackTimer); respond(false); };
img.src = url + '/favicon.ico?t=' + Date.now();
// If CORS blocks it, that still means the server is reachable
// (CORS error = server responded but blocked the origin).
// Just navigate — the WebView will handle it.
callback(true);
});
}

View file

@ -121,21 +121,15 @@
// ── Server check ──
function testServer(url, callback) {
var done = false;
function respond(ok) {
if (done) return;
done = true;
callback(ok);
}
fetch(url + '/api/health', { mode: 'no-cors', signal: AbortSignal.timeout(8000) })
.then(function() { respond(true); })
// In native WebView, no-cors fetch and image probes are unreliable.
// Just try a normal fetch to the health endpoint.
fetch(url + '/api/health', { signal: AbortSignal.timeout(8000) })
.then(function(r) { callback(true); })
.catch(function() {
var fallbackTimer = setTimeout(function() { respond(false); }, 5000);
var img = new Image();
img.onload = function() { clearTimeout(fallbackTimer); respond(true); };
img.onerror = function() { clearTimeout(fallbackTimer); respond(false); };
img.src = url + '/favicon.ico?t=' + Date.now();
// If CORS blocks it, that still means the server is reachable
// (CORS error = server responded but blocked the origin).
// Just navigate — the WebView will handle it.
callback(true);
});
}