fix(mobile): clear technical debt — real SHA-256, feed pagination, search
source_hash: BAS JSON import now computes SHA-256 via crypto.subtle.digest
instead of the '${id}-${length}' stub. No extra package — Hermes supports
Web Crypto API natively.
Feed pagination: useActivities(query, limit) accepts a LIMIT parameter.
The feed screen starts at 50, calls loadMore() via FlatList onEndReached
(threshold 0.3) to increment by 50 each time. useActivityCount(query)
drives the hasMore guard so loadMore is a no-op at the end of the list.
Feed search: compact TextInput below the header filters by title via
SQLite json_extract LIKE. Changing the query resets limit to PAGE_SIZE
so stale paginated results don't linger.
Docs: close the three resolved debt items; keep only the accepted
background-polling limitation as a known gap.
This commit is contained in:
+20
-4
@@ -29,10 +29,11 @@ export type ActivitySummary = {
|
||||
|
||||
// ── Activities ─────────────────────────────────────────────────────────────
|
||||
|
||||
export function useActivities(): ActivitySummary[] {
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
export function useActivities(searchQuery = '', limit = PAGE_SIZE): ActivitySummary[] {
|
||||
const db = useSQLiteContext();
|
||||
// Summaries are derived from the stored detail_json at query time.
|
||||
// JSON extraction via SQLite's json_extract keeps the table schema simple.
|
||||
const like = `%${searchQuery}%`;
|
||||
const rows = db.getAllSync<{
|
||||
id: string;
|
||||
origin: 'local' | 'remote';
|
||||
@@ -53,11 +54,26 @@ export function useActivities(): ActivitySummary[] {
|
||||
json_extract(detail_json, '$.duration_s') AS duration_s,
|
||||
json_extract(detail_json, '$.elevation_gain_m') AS elevation_gain_m
|
||||
FROM activities
|
||||
WHERE (? = '' OR json_extract(detail_json, '$.title') LIKE ?)
|
||||
ORDER BY json_extract(detail_json, '$.started_at') DESC
|
||||
`);
|
||||
LIMIT ?
|
||||
`, [searchQuery, like, limit]);
|
||||
return rows;
|
||||
}
|
||||
|
||||
export function useActivityCount(searchQuery = ''): number {
|
||||
const db = useSQLiteContext();
|
||||
const like = `%${searchQuery}%`;
|
||||
const row = db.getFirstSync<{ n: number }>(
|
||||
`SELECT COUNT(*) as n FROM activities
|
||||
WHERE (? = '' OR json_extract(detail_json, '$.title') LIKE ?)`,
|
||||
[searchQuery, like],
|
||||
);
|
||||
return row?.n ?? 0;
|
||||
}
|
||||
|
||||
export { PAGE_SIZE };
|
||||
|
||||
export function useActivity(id: string): ActivityRow | null {
|
||||
const db = useSQLiteContext();
|
||||
return db.getFirstSync<ActivityRow>(
|
||||
|
||||
Reference in New Issue
Block a user