diff --git a/bincio/edit/server.py b/bincio/edit/server.py index e603d1f..ec28198 100644 --- a/bincio/edit/server.py +++ b/bincio/edit/server.py @@ -716,8 +716,6 @@ async def strava_callback(code: str = "", error: str = "") -> RedirectResponse: token = exchange_code(strava_client_id, strava_client_secret, code) except StravaError: return RedirectResponse(f"{site_url}?strava=error") - # Stamp last_sync_at at connect time so the first sync only fetches new activities - token.setdefault("last_sync_at", int(time.time())) save_token(dd, token) return RedirectResponse(f"{site_url}?strava=connected") @@ -787,4 +785,50 @@ async def strava_sync() -> JSONResponse: token["last_sync_at"] = int(time.time()) save_token(dd, token) - return JSONResponse({"ok": True, "imported": imported, "skipped": skipped, "errors": errors[:5]}) + return JSONResponse({"ok": True, "imported": imported, "skipped": skipped, "error_count": len(errors), "errors": errors[:5]}) + + +@app.post("/api/strava/reset") +async def strava_reset(request: Request) -> JSONResponse: + """Reset last_sync_at. + + mode=soft — set to the started_at of the most recent activity already on disk + (next sync only fetches activities newer than the last known one) + mode=hard — clear last_sync_at entirely + (next sync re-downloads the full Strava history, skipping existing files) + """ + dd = _get_data_dir() + from bincio.extract.strava_api import load_token, save_token + token = load_token(dd) + if token is None: + raise HTTPException(400, "Not connected to Strava") + + body = await request.json() + mode = body.get("mode", "soft") + + if mode == "hard": + token.pop("last_sync_at", None) + save_token(dd, token) + return JSONResponse({"ok": True, "mode": "hard", "last_sync_at": None}) + + # soft: find the most recent started_at in the current index + from datetime import datetime, timezone + index_path = dd / "index.json" + last_ts: int | None = None + if index_path.exists(): + index_data = json.loads(index_path.read_text(encoding="utf-8")) + started_ats = [ + a.get("started_at") for a in index_data.get("activities", []) + if a.get("started_at") + ] + if started_ats: + latest = max(started_ats) + dt = datetime.fromisoformat(latest.replace("Z", "+00:00")) + last_ts = int(dt.astimezone(timezone.utc).timestamp()) + + if last_ts is None: + token.pop("last_sync_at", None) + else: + token["last_sync_at"] = last_ts + save_token(dd, token) + return JSONResponse({"ok": True, "mode": "soft", "last_sync_at": last_ts}) diff --git a/site/src/layouts/Base.astro b/site/src/layouts/Base.astro index 3d17273..274b48a 100644 --- a/site/src/layouts/Base.astro +++ b/site/src/layouts/Base.astro @@ -204,6 +204,18 @@ const baseUrl = import.meta.env.BASE_URL ?? '/'; id="strava-sync-btn" class="w-full py-2 px-4 rounded-lg font-medium text-sm bg-zinc-700 hover:bg-zinc-600 text-white transition-colors mt-2" >Sync now +