feat(mobile/upload): send original FIT file via /api/upload/raw when available
When original_path is set (i.e. the original FIT/GPX/TCX is still on disk),
upload via POST /api/upload/raw { filename, base64 } so the server re-extracts
with DEM elevation correction. Falls back to /api/upload/bas (pre-extracted
BAS JSON) when original_path is null or the file has been deleted.
This commit is contained in:
+37
-14
@@ -1,3 +1,4 @@
|
|||||||
|
import * as FileSystem from 'expo-file-system/legacy';
|
||||||
import type { SQLiteDatabase } from 'expo-sqlite';
|
import type { SQLiteDatabase } from 'expo-sqlite';
|
||||||
import { getSetting, upsertRemoteActivity } from './queries';
|
import { getSetting, upsertRemoteActivity } from './queries';
|
||||||
|
|
||||||
@@ -158,8 +159,14 @@ async function uploadLocalActivities(
|
|||||||
token: string,
|
token: string,
|
||||||
onProgress?: (n: number, total: number) => void,
|
onProgress?: (n: number, total: number) => void,
|
||||||
): Promise<{ uploaded: number; failed: number }> {
|
): Promise<{ uploaded: number; failed: number }> {
|
||||||
const rows = db.getAllSync<{ id: string; detail_json: string; timeseries_json: string | null; geojson: string | null }>(
|
const rows = db.getAllSync<{
|
||||||
`SELECT id, detail_json, timeseries_json, geojson
|
id: string;
|
||||||
|
detail_json: string;
|
||||||
|
timeseries_json: string | null;
|
||||||
|
geojson: string | null;
|
||||||
|
original_path: string | null;
|
||||||
|
}>(
|
||||||
|
`SELECT id, detail_json, timeseries_json, geojson, original_path
|
||||||
FROM activities WHERE origin = 'local' AND synced_at IS NULL`,
|
FROM activities WHERE origin = 'local' AND synced_at IS NULL`,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -173,28 +180,44 @@ async function uploadLocalActivities(
|
|||||||
const row = rows[i];
|
const row = rows[i];
|
||||||
onProgress?.(i + 1, total);
|
onProgress?.(i + 1, total);
|
||||||
try {
|
try {
|
||||||
const detail = JSON.parse(row.detail_json);
|
let resp: Response;
|
||||||
const activity = { id: row.id, ...detail };
|
|
||||||
|
|
||||||
const body: Record<string, unknown> = { activity };
|
// Prefer raw upload when the original FIT/GPX/TCX file is still on disk.
|
||||||
if (row.timeseries_json) body.timeseries = JSON.parse(row.timeseries_json);
|
// The server re-extracts it with DEM elevation correction, producing better data.
|
||||||
if (row.geojson) body.geojson = JSON.parse(row.geojson);
|
const useRaw = row.original_path !== null &&
|
||||||
|
(await FileSystem.getInfoAsync(row.original_path)).exists;
|
||||||
|
|
||||||
const resp = await fetch(`${instanceUrl}/api/upload/bas`, {
|
if (useRaw) {
|
||||||
method: 'POST',
|
const filename = row.original_path!.split('/').pop() ?? 'activity.fit';
|
||||||
headers,
|
const base64 = await FileSystem.readAsStringAsync(row.original_path!, {
|
||||||
body: JSON.stringify(body),
|
encoding: FileSystem.EncodingType.Base64,
|
||||||
});
|
});
|
||||||
|
resp = await fetch(`${instanceUrl}/api/upload/raw`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({ filename, base64 }),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const detail = JSON.parse(row.detail_json);
|
||||||
|
const body: Record<string, unknown> = { activity: { id: row.id, ...detail } };
|
||||||
|
if (row.timeseries_json) body.timeseries = JSON.parse(row.timeseries_json);
|
||||||
|
if (row.geojson) body.geojson = JSON.parse(row.geojson);
|
||||||
|
resp = await fetch(`${instanceUrl}/api/upload/bas`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (resp.ok) {
|
if (resp.ok) {
|
||||||
await db.runAsync(`UPDATE activities SET synced_at = ? WHERE id = ?`, [now, row.id]);
|
await db.runAsync(`UPDATE activities SET synced_at = ? WHERE id = ?`, [now, row.id]);
|
||||||
uploaded++;
|
uploaded++;
|
||||||
} else {
|
} else {
|
||||||
console.warn(`upload/bas ${row.id}: HTTP ${resp.status}`);
|
console.warn(`upload ${row.id}: HTTP ${resp.status}`);
|
||||||
failed++;
|
failed++;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`upload/bas ${row.id}:`, err);
|
console.warn(`upload ${row.id}:`, err);
|
||||||
failed++;
|
failed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user