diff --git a/src/App.native.tsx b/src/App.native.tsx
index 5ffbb6a8..442d7fe5 100644
--- a/src/App.native.tsx
+++ b/src/App.native.tsx
@@ -16,7 +16,7 @@ import {ThemeProvider} from 'lib/ThemeContext'
import {s} from 'lib/styles'
import {Shell} from 'view/shell'
import * as notifications from 'lib/notifications/notifications'
-import * as analytics from 'lib/analytics/analytics'
+import {Provider as AnalyticsProvider} from 'lib/analytics/analytics'
import * as Toast from 'view/com/util/Toast'
import {queryClient} from 'lib/react-query'
import {TestCtrls} from 'view/com/testing/TestCtrls'
@@ -45,7 +45,6 @@ function InnerApp() {
// init
useEffect(() => {
- analytics.init()
notifications.init(queryClient)
listenSessionDropped(() => {
Toast.show('Sorry! Your session expired. Please log in again.')
@@ -72,7 +71,7 @@ function InnerApp() {
-
+
{/* All components should be within this provider */}
@@ -80,7 +79,7 @@ function InnerApp() {
-
+
diff --git a/src/App.web.tsx b/src/App.web.tsx
index 74702dca..37115320 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -9,7 +9,7 @@ import 'view/icons'
import {init as initPersistedState} from '#/state/persisted'
import {useColorMode} from 'state/shell'
-import * as analytics from 'lib/analytics/analytics'
+import {Provider as AnalyticsProvider} from 'lib/analytics/analytics'
import {Shell} from 'view/shell/index'
import {ToastContainer} from 'view/com/util/Toast.web'
import {ThemeProvider} from 'lib/ThemeContext'
@@ -37,7 +37,6 @@ function InnerApp() {
// init
useEffect(() => {
- analytics.init()
const account = persisted.get('session').currentAccount
resumeSession(account)
}, [resumeSession])
@@ -59,7 +58,7 @@ function InnerApp() {
-
+
{/* All components should be within this provider */}
@@ -67,7 +66,7 @@ function InnerApp() {
-
+
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index a26f3693..3f6b5ba2 100644
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -41,6 +41,7 @@ import {
shouldRequestEmailConfirmation,
setEmailConfirmationRequested,
} from './state/shell/reminders'
+import {init as initAnalytics} from './lib/analytics/analytics'
import {HomeScreen} from './view/screens/Home'
import {SearchScreen} from './view/screens/Search'
@@ -474,6 +475,8 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
const {openModal} = useModalControls()
function onReady() {
+ initAnalytics(currentAccount)
+
if (currentAccount && shouldRequestEmailConfirmation(currentAccount)) {
openModal({name: 'verify-email', showReminder: true})
setEmailConfirmationRequested()
diff --git a/src/lib/analytics/analytics.tsx b/src/lib/analytics/analytics.tsx
index 3a8254eb..1650dfd3 100644
--- a/src/lib/analytics/analytics.tsx
+++ b/src/lib/analytics/analytics.tsx
@@ -7,20 +7,17 @@ import {
useAnalytics as useAnalyticsOrig,
ClientMethods,
} from '@segment/analytics-react-native'
-import {z} from 'zod'
-import {useSession} from '#/state/session'
+import {useSession, SessionAccount} from '#/state/session'
import {sha256} from 'js-sha256'
import {ScreenEvent, TrackEvent} from './types'
import {logger} from '#/logger'
-import {listenSessionLoaded} from '#/state/events'
-export const appInfo = z.object({
- build: z.string().optional(),
- name: z.string().optional(),
- namespace: z.string().optional(),
- version: z.string().optional(),
-})
-export type AppInfo = z.infer
+type AppInfo = {
+ build?: string | undefined
+ name?: string | undefined
+ namespace?: string | undefined
+ version?: string | undefined
+}
const segmentClient = createClient({
writeKey: '8I6DsgfiSLuoONyaunGoiQM7A6y2ybdI',
@@ -58,8 +55,10 @@ export function useAnalytics() {
}, [hasSession, methods])
}
-export function init() {
- listenSessionLoaded(account => {
+export function init(account: SessionAccount | undefined) {
+ setupListenersOnce()
+
+ if (account) {
if (account.did) {
const did_hashed = sha256(account.did)
segmentClient.identify(did_hashed, {did_hashed})
@@ -68,8 +67,15 @@ export function init() {
logger.debug('Ping w/o hash')
segmentClient.identify()
}
- })
+ }
+}
+let didSetupListeners = false
+function setupListenersOnce() {
+ if (didSetupListeners) {
+ return
+ }
+ didSetupListeners = true
// NOTE
// this is a copy of segment's own lifecycle event tracking
// we handle it manually to ensure that it never fires while the app is backgrounded
diff --git a/src/lib/analytics/analytics.web.tsx b/src/lib/analytics/analytics.web.tsx
index 0a5d5d68..df03ee13 100644
--- a/src/lib/analytics/analytics.web.tsx
+++ b/src/lib/analytics/analytics.web.tsx
@@ -6,9 +6,8 @@ import {
} from '@segment/analytics-react'
import {sha256} from 'js-sha256'
-import {useSession} from '#/state/session'
+import {useSession, SessionAccount} from '#/state/session'
import {logger} from '#/logger'
-import {listenSessionLoaded} from '#/state/events'
const segmentClient = createClient(
{
@@ -44,8 +43,8 @@ export function useAnalytics() {
}, [hasSession, methods])
}
-export function init() {
- listenSessionLoaded(account => {
+export function init(account: SessionAccount | undefined) {
+ if (account) {
if (account.did) {
if (account.did) {
const did_hashed = sha256(account.did)
@@ -56,7 +55,7 @@ export function init() {
segmentClient.identify()
}
}
- })
+ }
}
export function Provider({children}: React.PropsWithChildren<{}>) {
diff --git a/src/state/events.ts b/src/state/events.ts
index f8586082..1384abde 100644
--- a/src/state/events.ts
+++ b/src/state/events.ts
@@ -1,6 +1,4 @@
import EventEmitter from 'eventemitter3'
-import {BskyAgent} from '@atproto/api'
-import {SessionAccount} from './session'
type UnlistenFn = () => void
@@ -16,19 +14,6 @@ export function listenSoftReset(fn: () => void): UnlistenFn {
return () => emitter.off('soft-reset', fn)
}
-export function emitSessionLoaded(
- sessionAccount: SessionAccount,
- agent: BskyAgent,
-) {
- emitter.emit('session-loaded', sessionAccount, agent)
-}
-export function listenSessionLoaded(
- fn: (sessionAccount: SessionAccount, agent: BskyAgent) => void,
-): UnlistenFn {
- emitter.on('session-loaded', fn)
- return () => emitter.off('session-loaded', fn)
-}
-
export function emitSessionDropped() {
emitter.emit('session-dropped')
}
diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx
index 49c1326d..76b77a08 100644
--- a/src/state/session/index.tsx
+++ b/src/state/session/index.tsx
@@ -8,7 +8,7 @@ import {logger} from '#/logger'
import * as persisted from '#/state/persisted'
import {PUBLIC_BSKY_AGENT} from '#/state/queries'
import {IS_PROD} from '#/lib/constants'
-import {emitSessionLoaded, emitSessionDropped} from '../events'
+import {emitSessionDropped} from '../events'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useCloseAllActiveElements} from '#/state/util'
import {track} from '#/lib/analytics/analytics'
@@ -210,7 +210,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
__globalAgent = agent
queryClient.clear()
upsertAccount(account)
- emitSessionLoaded(account, agent)
logger.debug(
`session: created account`,
@@ -262,7 +261,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
__globalAgent = agent
queryClient.clear()
upsertAccount(account)
- emitSessionLoaded(account, agent)
logger.debug(
`session: logged in`,
@@ -355,12 +353,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
__globalAgent = agent
queryClient.clear()
upsertAccount(account)
- emitSessionLoaded(account, agent)
+
// Intentionally not awaited to unblock the UI:
- resumeSessionWithFreshAccount().then(async freshAccount => {
+ resumeSessionWithFreshAccount().then(freshAccount => {
if (JSON.stringify(account) !== JSON.stringify(freshAccount)) {
upsertAccount(freshAccount)
- emitSessionLoaded(freshAccount, agent)
}
})
} else {
@@ -368,7 +365,6 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
__globalAgent = agent
queryClient.clear()
upsertAccount(freshAccount)
- emitSessionLoaded(freshAccount, agent)
}
async function resumeSessionWithFreshAccount(): Promise {