Commit Graph

5 Commits

Author SHA1 Message Date
Davide Scaini cbe3e0eeaf feat(mobile): Karoo GPU crash fix, server-side extraction, upload fix, feed redesign
- Skip MapLibre on Android <29 (Karoo): SELinux denies kgsl-3d0 access
  from untrusted_app context, crashing the GPU driver on any OpenGL
  surface. Replace with SvgRouteView — equirectangular SVG route trace
  using react-native-svg, no native GL surface needed.
- Add +/- zoom buttons to full-screen MapLibre map on modern devices
  via Camera ref and onRegionDidChange.
- Skip PyodideWebView on Android <29: same GPU driver conflict; set
  _engineUnavailable at module init via API level gate (< 29).
- Add engine_unavailable fast path in PyodideWebView: post message
  immediately if WebAssembly.Global is absent (Chrome <69) instead of
  attempting 30 MB Pyodide download.
- Add server-side extraction fallback (extractServer.ts): when engine
  unavailable, POST raw file as base64 to /api/upload/raw; server runs
  full Python pipeline and returns extracted data.
- Add /api/upload/raw endpoint in server.py.
- Add pre-flight auth check (checkServerAuth) before batch import so
  an expired token errors immediately rather than after N files.
- Fix uploadLocalActivities in sync.ts: was reading original_path as
  JSON (binary FIT file, always threw), silently skipping every upload.
  Now reads detail_json from DB directly.
- Redesign Feed header: replace single Sync button with Upload /
  Download / Refresh. Pull-to-refresh and Refresh button are local-only.
  Auto-refresh on tab focus via useFocusEffect.
- Replace ActivityIndicator with plain Text everywhere (native animation
  also crashes Karoo GPU driver).
- Raise macOS open-file limit in dev_test.py to prevent EMFILE errors
  from Astro file watcher.
- Document all Karoo hardware constraints in docs/mobile-app.md.
2026-04-26 21:00:12 +02:00
Davide Scaini 1410be7427 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.
2026-04-26 14:59:28 +02:00
Davide Scaini 69571c1306 fix: pass wheel filename through extraction chain to fix micropip install
micropip requires the full PEP 427 wheel filename (name-version-py-abi-plat.whl)
— writing the file as bincio.whl caused InvalidWheelFilename. The wheel URL from
/api/wheel/version now provides the basename; it flows through fetchWheelBase64 →
extractFile → WebView where the file is written with the correct name and
_wheel_path is set as a Pyodide global before PY_INSTALL_WHEEL runs.
2026-04-25 09:29:33 +02:00
Davide Scaini 84e5cead08 fix: pre-fetch bincio wheel via RN networking to avoid ATS blocking HTTP in WKWebView
WKWebView blocks HTTP requests (ATS) even when NSAllowsLocalNetworking is set for
the app's own networking — so fetch(http://192.168.x.x/api/wheel/download) inside
the WebView always fails with 'Load failed' on iOS.

- extractActivity.ts: rename wheelUrl param to wheelBase64; WebView now receives
  the wheel as pre-fetched base64 bytes rather than a URL to fetch itself
- PyodideWebView.tsx: decode wheelBase64 → Uint8Array → Blob → blob URL for
  micropip.install; fix baseUrl '' → 'https://localhost' (null origin blocks fetch
  on iOS)
- import.tsx: add fetchWheelBase64() that resolves the wheel URL via
  /api/wheel/version then fetches with native networking (HTTP works); caches
  result in memory so repeated imports in one session don't re-download
2026-04-24 23:13:24 +02:00
Davide Scaini 966528a0bf feat: Phase 1 — FIT/GPX/TCX extraction via Pyodide in hidden WebView
- extraction/PyodideWebView.tsx: hidden WebView (1×1 px, off-screen) that
  bootstraps Pyodide v0.26.4 from jsDelivr CDN on app startup; loads lxml,
  pyyaml, micropip, fitdecode, gpxpy automatically; installs the bincio wheel
  lazily on the first extraction call via a blob URL (avoids startup delay)
- extraction/extractActivity.ts: typed bridge — extractFile(filename, base64,
  wheelUrl, onStatus) injects JS into the WebView, tracks pending promises by
  request ID, resolves with { id, detail, timeseries, geojson, sourceHash }
- app/_layout.tsx: mounts <PyodideWebView> outside SQLiteProvider at root so
  the runtime warms up as soon as the app opens
- app/(tabs)/import.tsx: replaces the placeholder alert with real extraction;
  reads files as base64, calls extractFile with a progress callback, stores
  detail_json + timeseries_json + geojson + real SHA-256 source_hash; resolves
  wheel URL via GET /api/wheel/version with fallback to /api/wheel/download;
  falls back to bincio.org if no instance is configured
2026-04-24 22:54:59 +02:00