ui: tighten dashboard copy and fix layout issues

This commit is contained in:
k
2026-06-14 21:58:56 +08:00
parent 4c3c8c6f87
commit 8534d90589
19 changed files with 1036 additions and 345 deletions
+16 -5
View File
@@ -18,6 +18,11 @@ interface CacheEntry<T> {
data: T
ts: number
revalidating: boolean
/** onUpdate callbacks of every caller that hit this key while a background
* revalidation was in flight (M9 fix). All are notified when the fetch
* resolves — previously only the caller that STARTED the revalidation got
* fresh data; everyone else silently kept the stale copy. */
subscribers: Array<(fresh: T) => void>
}
const store = new Map<string, CacheEntry<unknown>>()
@@ -37,16 +42,22 @@ export async function swrFetch<T>(
// Still fresh — return immediately.
return hit.data
}
// Stale — return immediately AND revalidate in background.
// Stale — return immediately AND revalidate in background. Every caller's
// onUpdate joins the subscriber list; the in-flight fetch notifies all.
if (onUpdate) hit.subscribers.push(onUpdate)
if (!hit.revalidating) {
hit.revalidating = true
fetcher()
.then(fresh => {
store.set(key, { data: fresh, ts: Date.now(), revalidating: false })
onUpdate?.(fresh)
const subs = hit.subscribers
store.set(key, { data: fresh, ts: Date.now(), revalidating: false, subscribers: [] })
for (const notify of subs) {
try { notify(fresh) } catch { /* one bad subscriber must not starve the rest */ }
}
})
.catch(() => {
if (hit) hit.revalidating = false
hit.revalidating = false
hit.subscribers = []
})
}
return hit.data
@@ -54,7 +65,7 @@ export async function swrFetch<T>(
// Cache miss — must wait for the first fetch.
const data = await fetcher()
store.set(key, { data, ts: Date.now(), revalidating: false })
store.set(key, { data, ts: Date.now(), revalidating: false, subscribers: [] })
return data
}