Feed: eager-load only the year shards needed for the active date filter
This commit is contained in:
@@ -132,57 +132,83 @@
|
||||
|
||||
$: if (sport || datePre || query || customFrom || customTo) shown = PAGE_SIZE; // reset pagination on filter change
|
||||
|
||||
// When a search query or any date filter is active, eagerly load all
|
||||
// remaining shards so results aren't limited to the initially-loaded year.
|
||||
// Use only primary let-variables here — Svelte 5 doesn't reliably track
|
||||
// derived $: variables as dependencies of side-effect $: blocks.
|
||||
let loadingAllShards = false;
|
||||
// Eager-load shards / feed-pages when a filter needs data not yet in memory.
|
||||
let loadingAllShards = false;
|
||||
let loadingAllFeedPages = false;
|
||||
|
||||
$: if ((query.trim() || customFrom || customTo || datePre !== 'all') && pendingShards.length > 0 && !loadingAllShards) {
|
||||
loadingAllShards = true;
|
||||
(async () => {
|
||||
while (pendingShards.length > 0) {
|
||||
const url = pendingShards[0];
|
||||
pendingShards = pendingShards.slice(1);
|
||||
try {
|
||||
const fresh = await loadShardActivities(url);
|
||||
const existing = new Map(all.map(a => [a.id, a]));
|
||||
for (const a of fresh) if (!existing.has(a.id)) existing.set(a.id, a);
|
||||
all = [...existing.values()].sort((a, b) =>
|
||||
(b.started_at ?? '').localeCompare(a.started_at ?? ''),
|
||||
);
|
||||
} catch { /* ignore — partial results still useful */ }
|
||||
}
|
||||
loadingAllShards = false;
|
||||
})();
|
||||
function _yearFromShard(url: string): number | null {
|
||||
const m = url.match(/index-(\d{4})\.json$/);
|
||||
return m ? parseInt(m[1], 10) : null;
|
||||
}
|
||||
|
||||
$: if ((query.trim() || customFrom || customTo || datePre !== 'all') && feedNextPage > 0 && !loadingAllFeedPages) {
|
||||
loadingAllFeedPages = true;
|
||||
(async () => {
|
||||
// Snapshot at loop start — customFrom may change while we're fetching.
|
||||
const fromFilter = customFrom;
|
||||
while (feedNextPage > 0) {
|
||||
const page = feedNextPage;
|
||||
feedNextPage = page < feedTotalPages ? page + 1 : 0;
|
||||
try {
|
||||
const fresh = await loadCombinedFeedPage(base, page);
|
||||
const existing = new Map(all.map(a => [a.id, a]));
|
||||
for (const a of fresh) if (!existing.has(a.id)) existing.set(a.id, a);
|
||||
all = [...existing.values()].sort((a, b) =>
|
||||
(b.started_at ?? '').localeCompare(a.started_at ?? ''),
|
||||
);
|
||||
// Feed is sorted newest-first. Once the oldest activity in this page
|
||||
// predates our from-filter, everything needed is already loaded.
|
||||
if (fromFilter && fresh.length > 0) {
|
||||
const oldest = fresh.reduce((m, a) => (a.started_at ?? '') < (m.started_at ?? '') ? a : m);
|
||||
if ((oldest.started_at ?? '') < fromFilter) { feedNextPage = 0; break; }
|
||||
}
|
||||
} catch { /* ignore — partial results still useful */ }
|
||||
}
|
||||
loadingAllFeedPages = false;
|
||||
})();
|
||||
// Returns [minYear, maxYear] for year-specific filters (year preset or custom
|
||||
// date range). Returns null for open-ended filters (all, 7d, 30d, 6mo).
|
||||
function _neededYearRange(pre: string, from: string, to: string): [number, number] | null {
|
||||
if (from || to) {
|
||||
const fy = from ? parseInt(from.slice(0, 4), 10) : 0;
|
||||
const ty = to ? parseInt(to.slice(0, 4), 10) : 9999;
|
||||
return [fy, ty];
|
||||
}
|
||||
if (/^\d{4}$/.test(pre)) { const y = parseInt(pre, 10); return [y, y]; }
|
||||
return null;
|
||||
}
|
||||
|
||||
$: {
|
||||
const yr = _neededYearRange(datePre, customFrom, customTo);
|
||||
const needEager = !!query.trim() || yr !== null;
|
||||
if (needEager && pendingShards.length > 0 && !loadingAllShards) {
|
||||
loadingAllShards = true;
|
||||
// When year-specific filter (no search), load only shards that cover
|
||||
// the needed range; unneeded shards stay in pendingShards for "Load more".
|
||||
// When search is active, load everything so full-text search works.
|
||||
const toLoad = (yr && !query.trim())
|
||||
? pendingShards.filter(url => { const y = _yearFromShard(url); return y !== null && y >= yr[0] && y <= yr[1]; })
|
||||
: [...pendingShards];
|
||||
(async () => {
|
||||
for (const url of toLoad) {
|
||||
pendingShards = pendingShards.filter(u => u !== url);
|
||||
try {
|
||||
const fresh = await loadShardActivities(url);
|
||||
const existing = new Map(all.map(a => [a.id, a]));
|
||||
for (const a of fresh) if (!existing.has(a.id)) existing.set(a.id, a);
|
||||
all = [...existing.values()].sort((a, b) =>
|
||||
(b.started_at ?? '').localeCompare(a.started_at ?? ''),
|
||||
);
|
||||
} catch { /* ignore — partial results still useful */ }
|
||||
}
|
||||
loadingAllShards = false;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
const yr = _neededYearRange(datePre, customFrom, customTo);
|
||||
if ((!!query.trim() || yr !== null) && feedNextPage > 0 && !loadingAllFeedPages) {
|
||||
loadingAllFeedPages = true;
|
||||
// Capture at loop start — dateFrom is reactive and may change mid-fetch.
|
||||
const effectiveFrom = dateFrom;
|
||||
(async () => {
|
||||
while (feedNextPage > 0) {
|
||||
const page = feedNextPage;
|
||||
feedNextPage = page < feedTotalPages ? page + 1 : 0;
|
||||
try {
|
||||
const fresh = await loadCombinedFeedPage(base, page);
|
||||
const existing = new Map(all.map(a => [a.id, a]));
|
||||
for (const a of fresh) if (!existing.has(a.id)) existing.set(a.id, a);
|
||||
all = [...existing.values()].sort((a, b) =>
|
||||
(b.started_at ?? '').localeCompare(a.started_at ?? ''),
|
||||
);
|
||||
// Feed is sorted newest-first. Once the oldest activity in this page
|
||||
// predates our from-filter, everything needed is already loaded.
|
||||
if (effectiveFrom && fresh.length > 0) {
|
||||
const oldest = fresh.reduce((m, a) => (a.started_at ?? '') < (m.started_at ?? '') ? a : m);
|
||||
if ((oldest.started_at ?? '') < effectiveFrom) { feedNextPage = 0; break; }
|
||||
}
|
||||
} catch { /* ignore — partial results still useful */ }
|
||||
}
|
||||
loadingAllFeedPages = false;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
$: if (mounted) {
|
||||
|
||||
Reference in New Issue
Block a user