feat(mobile): batch import + Karoo auto-import from watch folder
- Import tab now accepts multiple files at once (DocumentPicker multiple:true), processes them sequentially through Pyodide, and shows a summary with per-file errors on completion. - DB migration v2 adds source_path column (original filesystem path before copy) and an index on it, enabling O(1) deduplication for watch-folder imports. - On Android, if auto_import_path is set, the Import tab scans the directory on mount and on AppState 'active' (app foreground), then automatically imports any FIT files not yet in the DB. Designed for Karoo: finish a ride, open the app, new files import without any manual steps. - insertActivity now accepts optional source_path; both importBasJson and importNativeFile pass it through (null for files picked via DocumentPicker, real path for watch-folder files).
This commit is contained in:
+17
-3
@@ -9,6 +9,7 @@ export type ActivityRow = {
|
||||
timeseries_json: string | null;
|
||||
geojson: string | null;
|
||||
original_path: string | null;
|
||||
source_path: string | null;
|
||||
synced_at: number | null;
|
||||
origin: 'local' | 'remote';
|
||||
created_at: number;
|
||||
@@ -67,12 +68,13 @@ export function useActivity(id: string): ActivityRow | null {
|
||||
|
||||
export async function insertActivity(
|
||||
db: ReturnType<typeof useSQLiteContext>,
|
||||
row: Pick<ActivityRow, 'id' | 'source_hash' | 'detail_json' | 'timeseries_json' | 'geojson' | 'original_path' | 'origin'>,
|
||||
row: Pick<ActivityRow, 'id' | 'source_hash' | 'detail_json' | 'timeseries_json' | 'geojson' | 'original_path' | 'origin'>
|
||||
& { source_path?: string | null },
|
||||
): Promise<void> {
|
||||
await db.runAsync(
|
||||
`INSERT OR IGNORE INTO activities
|
||||
(id, source_hash, detail_json, timeseries_json, geojson, original_path, origin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
||||
(id, source_hash, detail_json, timeseries_json, geojson, original_path, source_path, origin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[
|
||||
row.id,
|
||||
row.source_hash,
|
||||
@@ -80,11 +82,23 @@ export async function insertActivity(
|
||||
row.timeseries_json ?? null,
|
||||
row.geojson ?? null,
|
||||
row.original_path ?? null,
|
||||
row.source_path ?? null,
|
||||
row.origin,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
export function isSourcePathImported(
|
||||
db: ReturnType<typeof useSQLiteContext>,
|
||||
sourcePath: string,
|
||||
): boolean {
|
||||
const row = db.getFirstSync<{ id: string }>(
|
||||
'SELECT id FROM activities WHERE source_path = ?',
|
||||
[sourcePath],
|
||||
);
|
||||
return row != null;
|
||||
}
|
||||
|
||||
export async function upsertRemoteActivity(
|
||||
db: ReturnType<typeof useSQLiteContext>,
|
||||
id: string,
|
||||
|
||||
Reference in New Issue
Block a user