import type { SQLiteDatabase } from 'expo-sqlite'; import { getSetting, upsertRemoteActivity } from './queries'; export type SyncResult = { synced: number; total: number; error?: string }; export async function syncFeed(db: SQLiteDatabase): Promise { const instanceUrl = (await getSetting(db, 'instance_url'))?.replace(/\/$/, ''); const token = await getSetting(db, 'api_token'); if (!instanceUrl || !token) { return { synced: 0, total: 0, error: 'No instance configured — add one in Settings.' }; } let resp: Response; try { resp = await fetch(`${instanceUrl}/api/feed`, { headers: { Authorization: `Bearer ${token}` }, }); } catch { return { synced: 0, total: 0, error: 'Could not reach instance — check your connection.' }; } if (resp.status === 401) { return { synced: 0, total: 0, error: 'Session expired — reconnect in Settings.' }; } if (!resp.ok) { return { synced: 0, total: 0, error: `Server error (${resp.status})` }; } const data: { activities?: RemoteSummary[] } = await resp.json(); const activities = data.activities ?? []; let synced = 0; for (const a of activities) { const detailJson = JSON.stringify({ id: a.id, title: a.title ?? a.id, sport: a.sport ?? null, started_at: a.started_at ?? null, distance_m: a.distance_m ?? null, moving_time_s: a.moving_time_s ?? null, elevation_gain_m: a.elevation_gain_m ?? null, avg_speed_kmh: a.avg_speed_kmh ?? null, avg_hr_bpm: a.avg_hr_bpm ?? null, avg_power_w: a.avg_power_w ?? null, }); const changed = await upsertRemoteActivity(db, a.id, detailJson); if (changed) synced++; } return { synced, total: activities.length }; } type RemoteSummary = { id: string; title?: string; sport?: string; started_at?: string; distance_m?: number | null; moving_time_s?: number | null; elevation_gain_m?: number | null; avg_speed_kmh?: number | null; avg_hr_bpm?: number | null; avg_power_w?: number | null; };