import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode, } from 'react'; import { bootstrapSession, clearAuth, ensureSession, getDeviceKey, request, saveSession, type SessionPayload, type UserProfile, } from '../lib/api'; import { touchPromoIfNeeded } from '../lib/promo'; type UserSessionContextValue = { ready: boolean; profile: UserProfile | null; phoneVerified: boolean; applySession: (session: SessionPayload) => void; refreshProfile: () => Promise; resetSession: () => Promise; }; const UserSessionContext = createContext(null); export function UserSessionProvider({ children }: { children: ReactNode }) { const [ready, setReady] = useState(false); const [profile, setProfile] = useState(null); const [phoneVerified, setPhoneVerified] = useState(false); const applySession = useCallback((session: SessionPayload) => { saveSession(session); if (session.user) setProfile(session.user); setPhoneVerified(!!session.phoneVerified || !!session.user?.phoneVerified); }, []); const refreshProfile = useCallback(async () => { const me = await request('USER_H5', '/auth/me'); setProfile(me); setPhoneVerified(!!me.phoneVerified); }, []); const resetSession = useCallback(async () => { clearAuth(); const session = await bootstrapSession(); applySession(session); }, [applySession]); useEffect(() => { let cancelled = false; (async () => { try { const session = await ensureSession(); if (cancelled) return; applySession(session); if (!session.user) { await refreshProfile(); } await touchPromoIfNeeded(); } catch { if (!cancelled) { try { const session = await bootstrapSession(); applySession(session); await refreshProfile(); } catch { /* ignore */ } } } finally { if (!cancelled) setReady(true); } })(); return () => { cancelled = true; }; }, [applySession, refreshProfile]); const value = useMemo( () => ({ ready, profile, phoneVerified, applySession, refreshProfile, resetSession, }), [ready, profile, phoneVerified, applySession, refreshProfile, resetSession], ); if (!ready) { return (

加载中...

); } return {children}; } export function useUserSession() { const ctx = useContext(UserSessionContext); if (!ctx) throw new Error('useUserSession must be used within UserSessionProvider'); return ctx; } export function useOptionalUserSession() { return useContext(UserSessionContext); } /** @deprecated use profile from useUserSession */ export { getDeviceKey };