Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[Statsig] Slightly block the UI on gates (#3608)

authored by

dan and committed by
GitHub
bef7d8a3 6101c32b

+40 -1
+26
src/lib/statsig/statsig.tsx
··· 8 8 import {isWeb} from '#/platform/detection' 9 9 import {IS_TESTFLIGHT} from 'lib/app-info' 10 10 import {useSession} from '../../state/session' 11 + import {timeout} from '../async/timeout' 11 12 import {useNonReactiveCallback} from '../hooks/useNonReactiveCallback' 12 13 import {LogEvents} from './events' 13 14 import {Gate} from './gates' ··· 163 164 }) 164 165 } 165 166 }) 167 + 168 + export async function tryFetchGates( 169 + did: string, 170 + strategy: 'prefer-low-latency' | 'prefer-fresh-gates', 171 + ) { 172 + try { 173 + let timeoutMs = 250 // Don't block the UI if we can't do this fast. 174 + if (strategy === 'prefer-fresh-gates') { 175 + // Use this for less common operations where the user would be OK with a delay. 176 + timeoutMs = 1500 177 + } 178 + // Note: This condition is currently false the very first render because 179 + // Statsig has not initialized yet. In the future, we can fix this by 180 + // doing the initialization ourselves instead of relying on the provider. 181 + if (Statsig.initializeCalled()) { 182 + await Promise.race([ 183 + timeout(timeoutMs), 184 + Statsig.prefetchUsers([toStatsigUser(did)]), 185 + ]) 186 + } 187 + } catch (e) { 188 + // Don't leak errors to the calling code, this is meant to be always safe. 189 + console.error(e) 190 + } 191 + } 166 192 167 193 export function Provider({children}: {children: React.ReactNode}) { 168 194 const {currentAccount, accounts} = useSession()
+14 -1
src/state/session/index.tsx
··· 9 9 import {track} from '#/lib/analytics/analytics' 10 10 import {networkRetry} from '#/lib/async/retry' 11 11 import {IS_TEST_USER} from '#/lib/constants' 12 - import {logEvent, LogEvents} from '#/lib/statsig/statsig' 12 + import {logEvent, LogEvents, tryFetchGates} from '#/lib/statsig/statsig' 13 13 import {hasProp} from '#/lib/type-guards' 14 14 import {logger} from '#/logger' 15 15 import {isWeb} from '#/platform/detection' ··· 243 243 if (!agent.session) { 244 244 throw new Error(`session: createAccount failed to establish a session`) 245 245 } 246 + const fetchingGates = tryFetchGates( 247 + agent.session.did, 248 + 'prefer-fresh-gates', 249 + ) 246 250 247 251 const deactivated = isSessionDeactivated(agent.session.accessJwt) 248 252 if (!deactivated) { ··· 283 287 ) 284 288 285 289 __globalAgent = agent 290 + await fetchingGates 286 291 upsertAccount(account) 287 292 288 293 logger.debug(`session: created account`, {}, logger.DebugContext.session) ··· 303 308 if (!agent.session) { 304 309 throw new Error(`session: login failed to establish a session`) 305 310 } 311 + const fetchingGates = tryFetchGates( 312 + agent.session.did, 313 + 'prefer-fresh-gates', 314 + ) 306 315 307 316 const account: SessionAccount = { 308 317 service: agent.service.toString(), ··· 330 339 __globalAgent = agent 331 340 // @ts-ignore 332 341 if (IS_DEV && isWeb) window.agent = agent 342 + await fetchingGates 333 343 upsertAccount(account) 334 344 335 345 logger.debug(`session: logged in`, {}, logger.DebugContext.session) ··· 362 372 const initSession = React.useCallback<ApiContext['initSession']>( 363 373 async account => { 364 374 logger.debug(`session: initSession`, {}, logger.DebugContext.session) 375 + const fetchingGates = tryFetchGates(account.did, 'prefer-low-latency') 365 376 366 377 const agent = new BskyAgent({ 367 378 service: account.service, ··· 406 417 407 418 agent.session = prevSession 408 419 __globalAgent = agent 420 + await fetchingGates 409 421 upsertAccount(account) 410 422 411 423 if (prevSession.deactivated) { ··· 442 454 try { 443 455 const freshAccount = await resumeSessionWithFreshAccount() 444 456 __globalAgent = agent 457 + await fetchingGates 445 458 upsertAccount(freshAccount) 446 459 } catch (e) { 447 460 /*