Some comments and cleanup
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
import {useEffect, useRef} from 'react'
|
||||||
|
|
||||||
|
import {getCurrentState, onAppStateChange} from '#/lib/appState'
|
||||||
|
import {useAnalytics} from '#/analytics'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks passive analytics like app foreground/background time.
|
||||||
|
*/
|
||||||
|
export function PassiveAnalytics() {
|
||||||
|
const ax = useAnalytics()
|
||||||
|
const lastActive = useRef(
|
||||||
|
getCurrentState() === 'active' ? performance.now() : null,
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = onAppStateChange(state => {
|
||||||
|
if (state === 'active') {
|
||||||
|
lastActive.current = performance.now()
|
||||||
|
ax.metric('state:foreground', {})
|
||||||
|
} else if (lastActive.current !== null) {
|
||||||
|
ax.metric('state:background', {
|
||||||
|
secondsActive: Math.round(
|
||||||
|
(performance.now() - lastActive.current) / 1e3,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return () => sub.remove()
|
||||||
|
}, [ax])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -61,8 +61,17 @@ const Context = createContext<AnalyticsBaseContextType>({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that deviceId is set and migrated from legacy storage. Handled on
|
||||||
|
* startup in `App.<platform>.tsx`. This must be awaited prior to the app
|
||||||
|
* booting up.
|
||||||
|
*/
|
||||||
export const setupDeviceId = getAndMigrateDeviceId()
|
export const setupDeviceId = getAndMigrateDeviceId()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analytics context provider. Decorates the parent analytics context with
|
||||||
|
* additional metadata. Nesting should be done carefully and sparingly.
|
||||||
|
*/
|
||||||
export function AnalyticsContext({
|
export function AnalyticsContext({
|
||||||
children,
|
children,
|
||||||
metadata,
|
metadata,
|
||||||
@@ -102,6 +111,11 @@ export function AnalyticsContext({
|
|||||||
return <Context.Provider value={childContext}>{children}</Context.Provider>
|
return <Context.Provider value={childContext}>{children}</Context.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feature gates provider. Decorates the parent analytics context with
|
||||||
|
* feature gate capabilities. Should be mounted within `AnalyticsContext`,
|
||||||
|
* and below the `<Fragment key={did} />` breaker in `App.<platform>.tsx`.
|
||||||
|
*/
|
||||||
export function AnalyticsFeaturesContext({
|
export function AnalyticsFeaturesContext({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
@@ -133,10 +147,18 @@ export function AnalyticsFeaturesContext({
|
|||||||
return <Context.Provider value={childContext}>{children}</Context.Provider>
|
return <Context.Provider value={childContext}>{children}</Context.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic analytics context without feature gates. Should really only be used
|
||||||
|
* above the `AnalyticsFeaturesContext` provider.
|
||||||
|
*/
|
||||||
export function useAnalyticsBase() {
|
export function useAnalyticsBase() {
|
||||||
return useContext(Context)
|
return useContext(Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main analytics context, including feature gates. Use this everywhere you
|
||||||
|
* need metrics, features, or logging within the React tree.
|
||||||
|
*/
|
||||||
export function useAnalytics() {
|
export function useAnalytics() {
|
||||||
const ctx = useContext(Context)
|
const ctx = useContext(Context)
|
||||||
if (!('feature' in ctx) || !('Features' in ctx)) {
|
if (!('feature' in ctx) || !('Features' in ctx)) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {isNetworkError} from '#/lib/strings/errors'
|
|||||||
import {Sentry} from '#/logger/sentry/lib'
|
import {Sentry} from '#/logger/sentry/lib'
|
||||||
import * as env from '#/env'
|
import * as env from '#/env'
|
||||||
|
|
||||||
// TODO just fucken use logger in here
|
// TODO debug logging
|
||||||
|
|
||||||
type Event<M extends Record<string, any>> = {
|
type Event<M extends Record<string, any>> = {
|
||||||
time: number
|
time: number
|
||||||
|
|||||||
@@ -3,18 +3,3 @@ import {type Events} from '#/analytics/metrics/types'
|
|||||||
|
|
||||||
export type {Events as Metrics} from '#/analytics/metrics/types'
|
export type {Events as Metrics} from '#/analytics/metrics/types'
|
||||||
export const metrics = new MetricsClient<Events>()
|
export const metrics = new MetricsClient<Events>()
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO
|
|
||||||
let lastActive = getCurrentState() === 'active' ? performance.now() : null
|
|
||||||
onAppStateChange(state => {
|
|
||||||
if (state === 'active') {
|
|
||||||
lastActive = performance.now()
|
|
||||||
metrics.track('state:foreground', {})
|
|
||||||
} else if (lastActive !== null) {
|
|
||||||
metrics.track('state:background', {
|
|
||||||
secondsActive: Math.round((performance.now() - lastActive) / 1e3),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Do not import runtime code into this file
|
||||||
|
*/
|
||||||
|
|
||||||
import {type NotificationReason} from '#/lib/hooks/useNotificationHandler'
|
import {type NotificationReason} from '#/lib/hooks/useNotificationHandler'
|
||||||
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
import {type FeedDescriptor} from '#/state/queries/post-feed'
|
||||||
import {type LiveEventFeedMetricContext} from '#/features/liveEvents/types'
|
import {type LiveEventFeedMetricContext} from '#/features/liveEvents/types'
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import {BSKY_SERVICE} from '#/lib/constants'
|
|||||||
import {type SessionAccount} from '#/state/session'
|
import {type SessionAccount} from '#/state/session'
|
||||||
import {type MergeableMetadata, type SessionMetadata} from '#/analytics/types'
|
import {type MergeableMetadata, type SessionMetadata} from '#/analytics/types'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thin `useMemo` wrapper that marks the metadata as memoized and provides a
|
||||||
|
* type guard.
|
||||||
|
*/
|
||||||
export function useMeta(metadata: MergeableMetadata) {
|
export function useMeta(metadata: MergeableMetadata) {
|
||||||
const m = useMemo(() => metadata, [metadata])
|
const m = useMemo(() => metadata, [metadata])
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import {Outlet as PortalOutlet} from '#/components/Portal'
|
|||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
import {NoAccessScreen} from '#/ageAssurance/components/NoAccessScreen'
|
import {NoAccessScreen} from '#/ageAssurance/components/NoAccessScreen'
|
||||||
import {RedirectOverlay} from '#/ageAssurance/components/RedirectOverlay'
|
import {RedirectOverlay} from '#/ageAssurance/components/RedirectOverlay'
|
||||||
|
import {PassiveAnalytics} from '#/analytics/PassiveAnalytics'
|
||||||
import {IS_ANDROID, IS_IOS} from '#/env'
|
import {IS_ANDROID, IS_IOS} from '#/env'
|
||||||
import {RoutesContainer, TabsNavigator} from '#/Navigation'
|
import {RoutesContainer, TabsNavigator} from '#/Navigation'
|
||||||
import {BottomSheetOutlet} from '../../../modules/bottom-sheet'
|
import {BottomSheetOutlet} from '../../../modules/bottom-sheet'
|
||||||
@@ -245,6 +246,8 @@ export function Shell() {
|
|||||||
<RedirectOverlay />
|
<RedirectOverlay />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<PassiveAnalytics />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {WelcomeModal} from '#/components/WelcomeModal'
|
|||||||
import {useAgeAssurance} from '#/ageAssurance'
|
import {useAgeAssurance} from '#/ageAssurance'
|
||||||
import {NoAccessScreen} from '#/ageAssurance/components/NoAccessScreen'
|
import {NoAccessScreen} from '#/ageAssurance/components/NoAccessScreen'
|
||||||
import {RedirectOverlay} from '#/ageAssurance/components/RedirectOverlay'
|
import {RedirectOverlay} from '#/ageAssurance/components/RedirectOverlay'
|
||||||
|
import {PassiveAnalytics} from '#/analytics/PassiveAnalytics'
|
||||||
import {FlatNavigator, RoutesContainer} from '#/Navigation'
|
import {FlatNavigator, RoutesContainer} from '#/Navigation'
|
||||||
import {Composer} from './Composer.web'
|
import {Composer} from './Composer.web'
|
||||||
import {DrawerContent} from './Drawer'
|
import {DrawerContent} from './Drawer'
|
||||||
@@ -181,6 +182,8 @@ export function Shell() {
|
|||||||
<RedirectOverlay />
|
<RedirectOverlay />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<PassiveAnalytics />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user