fix(mobile): patch pyodide.js at runtime to bypass Chrome 61 import() syntax

Chrome 61 (Karoo WebView) cannot parse dynamic import() — a SyntaxError at
parse time prevents loadPyodide from ever being defined.

Fix: fetch pyodide.js as text, replace every import( with a __loadScript(
shim that uses <script> tag injection, then inject via Blob URL. The Blob
script is never pre-scanned for module syntax so the patch is invisible to
the parser.

Also: expose waitForEngine() from extractActivity so callers can await
engine readiness before batching files — manual scan now shows "Preparing
extraction engine…" instead of flooding with N individual failures.
This commit is contained in:
Davide Scaini
2026-04-26 14:59:28 +02:00
parent a5c2810568
commit 1410be7427
3 changed files with 73 additions and 5 deletions
+13 -2
View File
@@ -6,7 +6,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { AppState, PermissionsAndroid, Platform, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
import { insertActivity, isSourcePathImported, getSetting } from '@/db/queries';
import { PyodideWebView } from '@/extraction/PyodideWebView';
import { extractFile } from '@/extraction/extractActivity';
import { extractFile, waitForEngine } from '@/extraction/extractActivity';
import { useTheme } from '@/ThemeContext';
const FIT_EXTENSIONS = ['.fit', '.fit.gz'];
@@ -54,7 +54,10 @@ export default function ImportScreen() {
const path = await getSetting(db, 'auto_import_path');
if (!path) return;
const instanceUrl = await getSetting(db, 'instance_url');
if (!instanceUrl) return; // silently skip — engine can't be downloaded without an instance
if (!instanceUrl) return;
// Wait for the extraction engine — but don't block forever on auto-scan.
try { await waitForEngine(120_000); } catch { return; }
const newFiles = await discoverNewFiles(db, path);
if (newFiles.length === 0) return;
@@ -77,6 +80,14 @@ export default function ImportScreen() {
return;
}
setState({ status: 'loading', msg: 'Preparing extraction engine…', current: 0, total: 0 });
try {
await waitForEngine();
} catch (e: unknown) {
setState({ status: 'error', message: e instanceof Error ? e.message : String(e) });
return;
}
setState({ status: 'loading', msg: 'Scanning…', current: 0, total: 0 });
const newFiles = await discoverNewFiles(db, path);
if (newFiles.length === 0) {