import React, { createContext, useCallback, useContext, useEffect, useState } from 'react' import { Alert, Linking } from 'react-native' import { XuqmSDK, ImSDK, UpdateSDK } from '@xuqm/rn-sdk' import { demoApi, type UserProfile } from '../api/demo' import { save, load, clearSession, K } from '../utils/storage' import pluginMeta from '../../plugin.json' const APP_ID = 'ak_demo_chat' const SERVER_URL = 'https://sentry.xuqinmin.com' interface AuthState { ready: boolean userId: string | null profile: UserProfile | null } interface AuthContextValue extends AuthState { login(userId: string, password: string): Promise register(userId: string, password: string, nickname: string): Promise logout(): Promise refreshProfile(): Promise updateProfile(data: Partial>): Promise } const AuthContext = createContext(null) export function AuthProvider({ children }: { children: React.ReactNode }) { const [state, setState] = useState({ ready: false, userId: null, profile: null }) const initSDK = useCallback(async (userId: string, imToken: string, profile: UserProfile) => { await XuqmSDK.initialize({ appId: APP_ID, serverUrl: SERVER_URL }) await ImSDK.loginWithToken(userId, imToken, 'xuqm_im') setState({ ready: true, userId, profile }) UpdateSDK.checkAppUpdate() .then(update => { if (update) { Alert.alert( '发现新版本', `${update.versionName} 是否立即更新?`, [ { text: '稍后', style: 'cancel' }, { text: '立即更新', onPress: () => Linking.openURL(update.downloadUrl) }, ], ) } else { UpdateSDK.checkRnUpdate(pluginMeta.moduleId).catch(() => {}) } }) .catch(() => {}) }, []) useEffect(() => { const restore = async () => { try { const demoToken = await load(K.DEMO_TOKEN) const imToken = await load(K.IM_TOKEN) const profile = await load(K.PROFILE) if (demoToken && imToken && profile) { await initSDK(profile.userId, imToken, profile) return } } catch { await clearSession() } setState(s => ({ ...s, ready: true })) } restore() }, [initSDK]) const handleAuthResult = useCallback(async (result: { demoToken: string; imToken: string; profile: UserProfile }) => { await save(K.DEMO_TOKEN, result.demoToken) await save(K.IM_TOKEN, result.imToken) await save(K.PROFILE, result.profile) await initSDK(result.profile.userId, result.imToken, result.profile) }, [initSDK]) const login = useCallback(async (userId: string, password: string) => { const result = await demoApi.login(userId, password) await handleAuthResult(result) }, [handleAuthResult]) const register = useCallback(async (userId: string, password: string, nickname: string) => { const result = await demoApi.register(userId, password, nickname) await handleAuthResult(result) }, [handleAuthResult]) const logout = useCallback(async () => { ImSDK.disconnect() await clearSession() setState({ ready: true, userId: null, profile: null }) }, []) const refreshProfile = useCallback(async () => { const profile = await demoApi.getProfile() await save(K.PROFILE, profile) setState(s => ({ ...s, profile })) }, []) const updateProfile = useCallback(async (data: Partial>) => { const profile = await demoApi.updateProfile(data) await save(K.PROFILE, profile) setState(s => ({ ...s, profile })) }, []) return ( {children} ) } export function useAuth(): AuthContextValue { const ctx = useContext(AuthContext) if (!ctx) throw new Error('useAuth must be used inside AuthProvider') return ctx }