import { useAuth } from '@/profile/auth/context'; import * as Crypto from 'expo-crypto'; import * as SecureStore from 'expo-secure-store'; import { ReactNode, RefObject, createContext, useEffect, useMemo, useRef, useState } from 'react'; import { initTelemetry } from './index'; import { MonitorEvent, StatsigProvider, useStatsigClient } from './statsig'; initTelemetry(); interface MonitorContextType { logEvent: (event: MonitorEvent) => void; } const noopContext: MonitorContextType = { logEvent: () => {} }; const MonitorContext = createContext(noopContext); const ANON_ID_KEY = 'palace_anonymous_id'; function MonitorInner({ children, eventQueueRef, }: { children: ReactNode; eventQueueRef: RefObject; }) { const { client } = useStatsigClient(); const flushed = useRef(false); useEffect(() => { const queue = eventQueueRef.current; if (!flushed.current && queue && queue.length > 0) { flushed.current = true; for (const event of queue) { client.logEvent(event); } queue.splice(0, queue.length); } }, [client, eventQueueRef]); const value = useMemo( () => ({ logEvent: (event: MonitorEvent) => client.logEvent(event), }), [client] ); return {children}; } export function MonitorProvider({ children }: { children: ReactNode }) { const { user } = useAuth(); const [anonId, setAnonId] = useState(null); const eventQueue = useRef([]); useEffect(() => { if (user) return; let mounted = true; (async () => { let id = await SecureStore.getItemAsync(ANON_ID_KEY); if (!id) { id = Crypto.randomUUID(); await SecureStore.setItemAsync(ANON_ID_KEY, id); } if (mounted) setAnonId(id); })(); return () => { mounted = false; }; }, [user]); const monitorUser = useMemo(() => { if (user) return { id: user.id, isAnonymous: false }; if (anonId) return { id: anonId, isAnonymous: true }; return null; }, [user, anonId]); const bufferingContext = useMemo( () => ({ logEvent: (event: MonitorEvent) => eventQueue.current.push(event), }), [] ); if (!monitorUser) { return {children}; } return ( {children} ); }