Global feed: switch from sequential pages to month-based BAS shards
feed.json is now a BAS shard index pointing to feed-YYYY-MM.json files (~150 activities / ~25 KB gzip each) instead of 400+ sequential feed-N.json pages. The frontend can now jump directly to a specific month when filtering by year or date range, without loading all newer data first. - merge.py: write_combined_feed groups by YYYY-MM and emits a shard index - dataloader.ts: isYearShardUrl matches feed-YYYY-MM.json; loadCombinedFeed returns pendingShards; FeedPage interface and loadCombinedFeedPage removed - ActivityFeed.svelte: _yearFromShard handles both index-YYYY and feed-YYYY-MM; feedNextPage/feedTotalPages/loadingAllFeedPages removed; infinite-loop bug fixed (toLoad.length guard before setting loadingAllShards); onMount uses pendingShards from loadCombinedFeed
This commit is contained in:
+10
-32
@@ -58,7 +58,7 @@ function emptyIndex(): BASIndex {
|
||||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
function isYearShardUrl(url: string): boolean {
|
||||
return /(?:^|\/)index-\d{4}\.json$/.test(url);
|
||||
return /(?:^|\/)(?:index-\d{4}|feed-\d{4}-\d{2})\.json$/.test(url);
|
||||
}
|
||||
|
||||
function rewriteActivityUrls(a: ActivitySummary, shardBase: string): ActivitySummary {
|
||||
@@ -253,50 +253,28 @@ export async function loadShardActivities(shardUrl: string): Promise<ActivitySum
|
||||
}
|
||||
}
|
||||
|
||||
interface FeedPage {
|
||||
page: number;
|
||||
total_pages: number;
|
||||
total_activities: number;
|
||||
activities: ActivitySummary[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the combined feed (multi-user global feed). Returns the first page of
|
||||
* activities pre-sorted across all users, plus remaining page count.
|
||||
* Load the combined feed (multi-user global feed).
|
||||
*
|
||||
* Falls back to the full shard-resolution path if feed.json doesn't exist
|
||||
* (single-user installs, older data).
|
||||
* feed.json is now a BAS shard index: the most-recent year shard is fetched
|
||||
* immediately; older shards are returned as pendingShards for lazy loading.
|
||||
* Returns null if feed.json doesn't exist (single-user installs).
|
||||
*/
|
||||
export async function loadCombinedFeed(
|
||||
baseUrl: string,
|
||||
): Promise<{ activities: ActivitySummary[]; remainingPages: number; totalActivities: number } | null> {
|
||||
): Promise<{ activities: ActivitySummary[]; pendingShards: string[]; totalActivities: number } | null> {
|
||||
try {
|
||||
const feed = await fetchJSON<FeedPage>(`${baseUrl}data/feed.json`);
|
||||
const { index, pendingShards } = await loadIndexPaged(baseUrl, `${baseUrl}data/feed.json`);
|
||||
return {
|
||||
activities: feed.activities ?? [],
|
||||
remainingPages: (feed.total_pages ?? 1) - 1,
|
||||
totalActivities: feed.total_activities ?? 0,
|
||||
activities: index.activities,
|
||||
pendingShards,
|
||||
totalActivities: (index as any).total_activities ?? index.activities.length,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a subsequent page of the combined feed (feed-2.json, feed-3.json, etc.).
|
||||
*/
|
||||
export async function loadCombinedFeedPage(
|
||||
baseUrl: string,
|
||||
page: number,
|
||||
): Promise<ActivitySummary[]> {
|
||||
try {
|
||||
const feed = await fetchJSON<FeedPage>(`${baseUrl}data/feed-${page}.json`);
|
||||
return feed.activities ?? [];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a single activity detail, checking IndexedDB first so locally-converted
|
||||
* activities are available offline.
|
||||
|
||||
Reference in New Issue
Block a user