feat: Phase 4 — MapLibre route map + SVG elevation chart on activity screen

- Add /api/activity/{id}/geojson and /api/activity/{id}/timeseries endpoints
  (bearer-token-gated, falls back from _merged to raw activities dir)
- Rewrite activity detail screen with MapLibreGL v11 API (Map, Camera,
  GeoJSONSource, Layer) and react-native-svg area chart with gradient fill
- On-demand fetch for remote activities that have no local geojson/timeseries
- Add react-native-svg dependency; requires dev build (npx expo run:android)
This commit is contained in:
Davide Scaini
2026-04-24 15:40:10 +02:00
parent 02726034c7
commit 97c7fae9be
5 changed files with 507 additions and 164 deletions
+32
View File
@@ -455,6 +455,38 @@ async def stats() -> JSONResponse:
})
@app.get("/api/activity/{activity_id}/geojson")
async def get_activity_geojson(
activity_id: str,
user: User = Depends(_require_auth),
) -> JSONResponse:
"""Return GeoJSON track for an activity (mobile detail screen)."""
_check_id(activity_id)
dd = _get_data_dir()
user_dir = dd / user.handle
for base in (user_dir / "_merged" / "activities", user_dir / "activities"):
p = base / f"{activity_id}.geojson"
if p.exists():
return JSONResponse(json.loads(p.read_text()))
raise HTTPException(404, "GeoJSON not found")
@app.get("/api/activity/{activity_id}/timeseries")
async def get_activity_timeseries(
activity_id: str,
user: User = Depends(_require_auth),
) -> JSONResponse:
"""Return timeseries for an activity (mobile detail screen)."""
_check_id(activity_id)
dd = _get_data_dir()
user_dir = dd / user.handle
for base in (user_dir / "_merged" / "activities", user_dir / "activities"):
p = base / f"{activity_id}.timeseries.json"
if p.exists():
return JSONResponse(json.loads(p.read_text()))
raise HTTPException(404, "Timeseries not found")
@app.get("/api/wheel/version")
async def wheel_version() -> JSONResponse:
"""Public endpoint: current bincio wheel version for mobile app update checks."""