Bluesky app fork with some witchin' additions 💫

Enable gating and experimentation on native, send init event (#3149)

* Add the mobile fork

* Add init event

authored by danabra.mov and committed by

GitHub dd86d096 31826633

+74 -6
+4
src/Navigation.tsx
··· 78 78 import {msg} from '@lingui/macro' 79 79 import {i18n, MessageDescriptor} from '@lingui/core' 80 80 import HashtagScreen from '#/screens/Hashtag' 81 + import {logEvent} from './lib/statsig/statsig' 81 82 82 83 const navigationRef = createNavigationContainerRef<AllNavigatorParams>() 83 84 ··· 649 650 return 650 651 } 651 652 didInit = true 653 + 652 654 const initMs = Math.round( 653 655 // @ts-ignore Emitted by Metro in the bundle prelude 654 656 performance.now() - global.__BUNDLE_START_TIME__, 655 657 ) 656 658 console.log(`Time to first paint: ${initMs} ms`) 659 + logEvent('init', initMs) 660 + 657 661 if (__DEV__) { 658 662 // This log is noisy, so keep false committed 659 663 const shouldLog = false
+57 -5
src/lib/statsig/statsig.tsx
··· 1 1 import React from 'react' 2 + import { 3 + Statsig, 4 + StatsigProvider, 5 + useGate as useStatsigGate, 6 + } from 'statsig-react-native-expo' 7 + import {useSession} from '../../state/session' 8 + import {sha256} from 'js-sha256' 2 9 3 - export function useGate(_gateName: string) { 4 - // Not enabled for native yet. 5 - return false 10 + const statsigOptions = { 11 + environment: { 12 + tier: process.env.NODE_ENV === 'development' ? 'development' : 'production', 13 + }, 14 + // Don't block on waiting for network. The fetched config will kick in on next load. 15 + // This ensures the UI is always consistent and doesn't update mid-session. 16 + // Note this makes cold load (no local storage) and private mode return `false` for all gates. 17 + initTimeoutMs: 1, 18 + } 19 + 20 + export function logEvent( 21 + eventName: string, 22 + value?: string | number | null, 23 + metadata?: Record<string, string> | null, 24 + ) { 25 + Statsig.logEvent(eventName, value, metadata) 26 + } 27 + 28 + export function useGate(gateName: string) { 29 + const {isLoading, value} = useStatsigGate(gateName) 30 + if (isLoading) { 31 + // This should not happen because of waitForInitialization={true}. 32 + console.error('Did not expected isLoading to ever be true.') 33 + } 34 + return value 35 + } 36 + 37 + function toStatsigUser(did: string | undefined) { 38 + let userID: string | undefined 39 + if (did) { 40 + userID = sha256(did) 41 + } 42 + return {userID} 6 43 } 7 44 8 45 export function Provider({children}: {children: React.ReactNode}) { 9 - // Not enabled for native yet. 10 - return children 46 + const {currentAccount} = useSession() 47 + const currentStatsigUser = React.useMemo( 48 + () => toStatsigUser(currentAccount?.did), 49 + [currentAccount?.did], 50 + ) 51 + return ( 52 + <StatsigProvider 53 + sdkKey="client-SXJakO39w9vIhl3D44u8UupyzFl4oZ2qPIkjwcvuPsV" 54 + mountKey={currentStatsigUser.userID} 55 + user={currentStatsigUser} 56 + // This isn't really blocking due to short initTimeoutMs above. 57 + // However, it ensures `isLoading` is always `false`. 58 + waitForInitialization={true} 59 + options={statsigOptions}> 60 + {children} 61 + </StatsigProvider> 62 + ) 11 63 }
+13 -1
src/lib/statsig/statsig.web.tsx
··· 1 1 import React from 'react' 2 - import {StatsigProvider, useGate as useStatsigGate} from 'statsig-react' 2 + import { 3 + Statsig, 4 + StatsigProvider, 5 + useGate as useStatsigGate, 6 + } from 'statsig-react' 3 7 import {useSession} from '../../state/session' 4 8 import {sha256} from 'js-sha256' 5 9 ··· 11 15 // This ensures the UI is always consistent and doesn't update mid-session. 12 16 // Note this makes cold load (no local storage) and private mode return `false` for all gates. 13 17 initTimeoutMs: 1, 18 + } 19 + 20 + export function logEvent( 21 + eventName: string, 22 + value?: string | number | null, 23 + metadata?: Record<string, string> | null, 24 + ) { 25 + Statsig.logEvent(eventName, value, metadata) 14 26 } 15 27 16 28 export function useGate(gateName: string) {