WIP
This commit is contained in:
@@ -28,6 +28,10 @@ EXPO_PUBLIC_CHAT_PROXY_DID=
|
||||
#
|
||||
#
|
||||
|
||||
# Growthbook config
|
||||
EXPO_PUBLIC_GROWTHBOOK_API_HOST=
|
||||
EXPO_PUBLIC_GROWTHBOOK_CLIENT_KEY=
|
||||
|
||||
# Sentry DSN for telemetry
|
||||
EXPO_PUBLIC_SENTRY_DSN=
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
"@fortawesome/free-regular-svg-icons": "^6.1.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.1.1",
|
||||
"@fortawesome/react-native-fontawesome": "^0.3.2",
|
||||
"@growthbook/growthbook-react": "^1.6.2",
|
||||
"@haileyok/bluesky-video": "0.3.2",
|
||||
"@ipld/dag-cbor": "^9.2.0",
|
||||
"@lingui/react": "^4.14.1",
|
||||
|
||||
+4
-2
@@ -21,7 +21,7 @@ import {Provider as StatsigProvider, tryFetchGates} from '#/lib/statsig/statsig'
|
||||
import {s} from '#/lib/styles'
|
||||
import {ThemeProvider} from '#/lib/ThemeContext'
|
||||
import I18nProvider from '#/locale/i18nProvider'
|
||||
import {logger} from '#/logger'
|
||||
import {logger, Provider as LoggingProvider} from '#/logger'
|
||||
import {Provider as A11yProvider} from '#/state/a11y'
|
||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||
@@ -238,7 +238,9 @@ function App() {
|
||||
<StarterPackProvider>
|
||||
<SafeAreaProvider
|
||||
initialMetrics={initialWindowMetrics}>
|
||||
<InnerApp />
|
||||
<LoggingProvider>
|
||||
<InnerApp />
|
||||
</LoggingProvider>
|
||||
</SafeAreaProvider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
|
||||
+6
-2
@@ -12,7 +12,8 @@ import {QueryProvider} from '#/lib/react-query'
|
||||
import {Provider as StatsigProvider} from '#/lib/statsig/statsig'
|
||||
import {ThemeProvider} from '#/lib/ThemeContext'
|
||||
import I18nProvider from '#/locale/i18nProvider'
|
||||
import {logger} from '#/logger'
|
||||
import {logger, Provider as LoggingProvider} from '#/logger'
|
||||
import {initializer as growthbookInitializer} from '#/logger/growthbook/context'
|
||||
import {Provider as A11yProvider} from '#/state/a11y'
|
||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||
@@ -85,6 +86,7 @@ function InnerApp() {
|
||||
useEffect(() => {
|
||||
async function onLaunch(account?: SessionAccount) {
|
||||
try {
|
||||
await growthbookInitializer
|
||||
if (account) {
|
||||
await resumeSession(account)
|
||||
}
|
||||
@@ -205,7 +207,9 @@ function App() {
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
<LoggingProvider>
|
||||
<InnerApp />
|
||||
</LoggingProvider>
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
|
||||
Vendored
+11
@@ -84,6 +84,17 @@ export const BLUESKY_PROXY_DID: Did =
|
||||
export const CHAT_PROXY_DID: Did =
|
||||
process.env.EXPO_PUBLIC_CHAT_PROXY_DID || 'did:web:api.bsky.chat'
|
||||
|
||||
/**
|
||||
* Growthbook API host
|
||||
*/
|
||||
export const GROWTHBOOK_API_HOST: string | undefined = process.env.EXPO_PUBLIC_GROWTHBOOK_API_HOST
|
||||
|
||||
/**
|
||||
* Growthbook client key
|
||||
*/
|
||||
export const GROWTHBOOK_CLIENT_KEY: string | undefined = process.env.EXPO_PUBLIC_GROWTHBOOK_CLIENT_KEY
|
||||
|
||||
|
||||
/**
|
||||
* Sentry DSN for telemetry
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import {useMemo, useEffect} from 'react'
|
||||
import {Platform} from 'react-native'
|
||||
import {
|
||||
GrowthBook,
|
||||
GrowthBookProvider,
|
||||
useFeatureIsOn,
|
||||
} from '@growthbook/growthbook-react'
|
||||
|
||||
import * as env from '#/env'
|
||||
import {useSession, SessionAccount} from '#/state/session'
|
||||
import {useGeolocation} from '#/geolocation'
|
||||
import * as persisted from '#/state/persisted'
|
||||
import * as referrer from '#/logger/growthbook/util/referrer'
|
||||
|
||||
type DefaultAttributes = {
|
||||
country: string
|
||||
}
|
||||
type UserAttributes = {
|
||||
id: string
|
||||
pds: string | undefined
|
||||
platform: string
|
||||
appVersion: string
|
||||
bundleIdentifier: string
|
||||
bundleDate: number
|
||||
refSrc: string
|
||||
refUrl: string
|
||||
appLanguage: string
|
||||
contentLanguages: string[]
|
||||
}
|
||||
|
||||
const gb = new GrowthBook({
|
||||
apiHost: env.GROWTHBOOK_API_HOST,
|
||||
clientKey: env.GROWTHBOOK_CLIENT_KEY,
|
||||
trackingCallback: (experiment, result) => {
|
||||
// TODO
|
||||
console.log('Experiment Viewed', {
|
||||
experimentId: experiment.key,
|
||||
variationId: result.key,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
export const initializer = gb.init({
|
||||
timeout: 1e3,
|
||||
})
|
||||
|
||||
export function useGate(gate: string): boolean {
|
||||
return useFeatureIsOn(gate)
|
||||
}
|
||||
|
||||
export function Provider({children}: {children: React.ReactNode}) {
|
||||
const geo = useGeolocation()
|
||||
const {currentAccount} = useSession()
|
||||
const defaultAttributes = useMemo<DefaultAttributes>(
|
||||
() => ({
|
||||
country: geo.countryCode || 'unknown',
|
||||
}),
|
||||
[geo],
|
||||
)
|
||||
|
||||
/**
|
||||
* Decorate existing attributes with any new default attributes
|
||||
*/
|
||||
useEffect(() => {
|
||||
const attr = {
|
||||
...gb.getAttributes(),
|
||||
...defaultAttributes,
|
||||
}
|
||||
gb.setAttributes(attr)
|
||||
console.debug(`update attributes`, {attributes: attr})
|
||||
}, [defaultAttributes])
|
||||
|
||||
/**
|
||||
* Update user attributes on session change, and clear them on logout
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (currentAccount) {
|
||||
const attr = getUserAttributes(currentAccount)
|
||||
gb.setAttributes({
|
||||
...defaultAttributes,
|
||||
...getUserAttributes(currentAccount),
|
||||
})
|
||||
console.debug(`has session, set attributes`, {attributes: attr})
|
||||
} else {
|
||||
gb.setAttributes(defaultAttributes)
|
||||
console.debug(`no session, reset attributes`, {
|
||||
attributes: defaultAttributes,
|
||||
})
|
||||
}
|
||||
}, [defaultAttributes, currentAccount])
|
||||
|
||||
return <GrowthBookProvider growthbook={gb}>{children}</GrowthBookProvider>
|
||||
}
|
||||
|
||||
export function getUserAttributes(account: SessionAccount): UserAttributes
|
||||
export function getUserAttributes(account: undefined): null
|
||||
export function getUserAttributes(
|
||||
account?: SessionAccount,
|
||||
): UserAttributes | null {
|
||||
if (!account) return null
|
||||
const languagePrefs = persisted.get('languagePrefs')
|
||||
return {
|
||||
id: account.did,
|
||||
pds: account.pdsUrl,
|
||||
platform: Platform.OS,
|
||||
appVersion: env.RELEASE_VERSION,
|
||||
bundleIdentifier: env.BUNDLE_IDENTIFIER,
|
||||
bundleDate: env.BUNDLE_DATE,
|
||||
appLanguage: languagePrefs.appLanguage,
|
||||
contentLanguages: languagePrefs.contentLanguages,
|
||||
refSrc: referrer.src,
|
||||
refUrl: referrer.url,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export const src = ''
|
||||
export const url = ''
|
||||
@@ -0,0 +1,3 @@
|
||||
const params = new URLSearchParams(window.location.search)
|
||||
export const src = params.get('ref_src') ?? ''
|
||||
export const url = decodeURIComponent(params.get('ref_url') ?? '')
|
||||
@@ -1,5 +1,6 @@
|
||||
import {nanoid} from 'nanoid/non-secure'
|
||||
|
||||
import {Provider as GrowthbookProvider} from '#/logger/growthbook/context'
|
||||
import {logEvent} from '#/lib/statsig/statsig'
|
||||
import {add} from '#/logger/logDump'
|
||||
import {type MetricEvents} from '#/logger/metrics'
|
||||
@@ -171,3 +172,10 @@ export class Logger {
|
||||
* `logger.error(error[, metadata])`
|
||||
*/
|
||||
export const logger = Logger.create(Logger.Context.Default)
|
||||
|
||||
/**
|
||||
* Logger context provider
|
||||
*/
|
||||
export function Provider({children}: {children: React.ReactNode}) {
|
||||
return <GrowthbookProvider>{children}</GrowthbookProvider>
|
||||
}
|
||||
@@ -4678,6 +4678,20 @@
|
||||
dependencies:
|
||||
nanoid "^3.3.1"
|
||||
|
||||
"@growthbook/growthbook-react@^1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@growthbook/growthbook-react/-/growthbook-react-1.6.2.tgz#847135be0c46b167f980dbe6015e5f4ed010475c"
|
||||
integrity sha512-96Bo2Jwd4NBn/kBLN4ceF299PhTw8fQltRykD32hu2xMW8/LXhB8swxbPshGK+Xfa2gjgt24kpZ5oSvaVLLT7w==
|
||||
dependencies:
|
||||
"@growthbook/growthbook" "^1.6.2"
|
||||
|
||||
"@growthbook/growthbook@^1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@growthbook/growthbook/-/growthbook-1.6.2.tgz#6a25122deac8a09955f6bddeb134af62b209809b"
|
||||
integrity sha512-x3sK6Lff4BVusIzcdBeHZqA3B4kLs3kM/pJ7vvLTJwb6N/+Yn99EF1yc0XU6cfDVqFq6uFkvIFhMwDWUaKD73g==
|
||||
dependencies:
|
||||
dom-mutator "^0.6.0"
|
||||
|
||||
"@grpc/grpc-js@^1.8.20":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.13.3.tgz#6ad08d186c2a8651697085f790c5c68eaca45904"
|
||||
@@ -10522,6 +10536,11 @@ dom-converter@^0.2.0:
|
||||
dependencies:
|
||||
utila "~0.4"
|
||||
|
||||
dom-mutator@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-mutator/-/dom-mutator-0.6.0.tgz#079d7a4b3e8981a562cd777548b99baab51d65c5"
|
||||
integrity sha512-iCt9o0aYfXMUkz/43ZOAUFQYotjGB+GNbYJiJdz4TgXkyToXbbRy5S6FbTp72lRBtfpUMwEc1KmpFEU4CZeoNg==
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
|
||||
|
||||
Reference in New Issue
Block a user