From 9dbd2ef7df1b1d18909266184a5715c65e07304c Mon Sep 17 00:00:00 2001 From: scanash00 Date: Fri, 12 Jun 2026 09:20:28 -0800 Subject: [PATCH] fix: circular import crash (tokens undefined / TRACKING) + profile postsCount - themes.ts imported tokens from the #/alf barrel, which forms a cycle (themes -> #/alf -> alf/themes -> themes); under some load orders tokens was undefined at eval time -> 'Cannot read properties of undefined (TRACKING)'. Import tokens directly from #/alf/tokens (like fontWeight already does). - hydrateProfile now fills postsCount (was always 0) via bounded listRecords; profile header already formats counts compactly (2.5K) via formatCount. --- src/lib/microcosm/hydrate.ts | 17 +++++++++++++---- src/lib/themes.ts | 4 +++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/lib/microcosm/hydrate.ts b/src/lib/microcosm/hydrate.ts index 3fb9151..868563e 100644 --- a/src/lib/microcosm/hydrate.ts +++ b/src/lib/microcosm/hydrate.ts @@ -198,8 +198,10 @@ async function hydrateEmbed( * Hydrate a `ProfileViewDetailed` for a DID or handle from microcosm. * * - `followersCount` comes from Constellation (backlinks of follows -> this DID). - * - `followsCount` comes from counting the DID's own `app.bsky.graph.follow` - * records via listRecords (outgoing follows aren't backlinks). Bounded. + * - `followsCount` / `postsCount` come from counting the DID's own + * `app.bsky.graph.follow` / `app.bsky.feed.post` records via listRecords + * (these aren't backlinks). Bounded by countRecords' page cap, so very busy + * accounts report a floor (e.g. "3000+") rather than an exact total. */ export async function hydrateProfile( identifier: string, @@ -208,7 +210,7 @@ export async function hydrateProfile( const mini = await resolveMiniDoc(identifier, signal) const {did, handle} = mini - const [recordRes, followers, follows] = await Promise.all([ + const [recordRes, followers, follows, posts] = await Promise.all([ getRecordByUri( `at://${did}/app.bsky.actor.profile/self`, undefined, @@ -217,8 +219,14 @@ export async function hydrateProfile( constellation .getBacklinksCount(did, constellation.Sources.followers, signal) .catch(() => undefined), + // Cap pagination so profile loads stay responsive: exact counts in the + // thousands don't matter for display (the AppView caps too). 5 pages = 500. countRecords( - {repo: did, collection: 'app.bsky.graph.follow'}, + {repo: did, collection: 'app.bsky.graph.follow', maxPages: 5}, + signal, + ).catch(() => undefined), + countRecords( + {repo: did, collection: 'app.bsky.feed.post', maxPages: 5}, signal, ).catch(() => undefined), ]) @@ -235,6 +243,7 @@ export async function hydrateProfile( banner: cdnUrl('banner', did, profile?.banner), followersCount: followers?.total, followsCount: follows?.count, + postsCount: posts?.count, labels: extractSelfLabels(did, profile), indexedAt: undefined, createdAt: profile?.createdAt, diff --git a/src/lib/themes.ts b/src/lib/themes.ts index 1df0a55..1b6ba9c 100644 --- a/src/lib/themes.ts +++ b/src/lib/themes.ts @@ -1,8 +1,10 @@ import {Platform} from 'react-native' -import {tokens} from '#/alf' import {darkPalette, dimPalette, lightPalette} from '#/alf/themes' +import * as tokens from '#/alf/tokens' import {fontWeight} from '#/alf/tokens' +// `tokens` is imported directly from #/alf/tokens (not the #/alf barrel) to +// avoid a circular import that left `tokens` undefined at module-eval time. import {colors} from './styles' import {type Theme} from './ThemeContext' -- 2.51.2