From 16965a7645c3f2506398447031768e13cff4368f Mon Sep 17 00:00:00 2001 From: Davide Scaini Date: Thu, 14 May 2026 18:22:05 +0200 Subject: [PATCH] ActivityDetail: fetch timeseries in parallel with detail JSON to cut load time --- site/src/components/ActivityDetail.svelte | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/site/src/components/ActivityDetail.svelte b/site/src/components/ActivityDetail.svelte index 66f1105..36bedcb 100644 --- a/site/src/components/ActivityDetail.svelte +++ b/site/src/components/ActivityDetail.svelte @@ -52,15 +52,27 @@ .then(d => { segmentEfforts = d; }) .catch(() => {}); + // Start timeseries fetch immediately in parallel with detail — the URL is + // predictable from detail_url, saving a full sequential round-trip. + const detailUrl = activity.detail_url ?? ''; + const earlyTsPromise: Promise = detailUrl && !detailUrl.startsWith('idb:') + ? loadTimeseries( + detailUrl.replace(/\.json$/, '.timeseries.json').replace(/^.*activities\//, 'activities/'), + detailUrl, + base, + ).catch(() => null) + : Promise.resolve(null); + try { - detail = await loadActivity(activity.id, activity.detail_url ?? '', base); + detail = await loadActivity(activity.id, detailUrl, base); if (!detail) throw new Error('Activity not found'); - // Use embedded timeseries (IDB activities) or lazy-fetch from URL + // Use embedded timeseries (IDB activities) or the already-in-flight fetch if (detail.timeseries) { timeseries = detail.timeseries; } else if (detail.timeseries_url) { timeseriesLoading = true; - timeseries = await loadTimeseries(detail.timeseries_url, activity.detail_url ?? '', base); + timeseries = await earlyTsPromise ?? + await loadTimeseries(detail.timeseries_url, detailUrl, base); timeseriesLoading = false; } } catch (e: any) {