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