diff --git a/src/api/demo.ts b/src/api/demo.ts index f60bf8c..85d9fc9 100644 --- a/src/api/demo.ts +++ b/src/api/demo.ts @@ -43,7 +43,9 @@ export interface UserProfile { export interface AuthResult { demoToken: string + demoTokenExpiresAt?: number | null imToken: string + imTokenExpiresAt?: number | null profile: UserProfile } @@ -64,6 +66,14 @@ export const demoApi = { }) }, + refreshImToken(appId: string = APP_ID): Promise<{ imToken: string; imTokenExpiresAt?: number | null }> { + return request('/auth/refresh-im', { + method: 'POST', + skipAuth: false, + params: { appId }, + }) + }, + getProfile(): Promise { return request('/user/profile') }, diff --git a/src/context/AuthContext.tsx b/src/context/AuthContext.tsx index ab954d3..4167be0 100644 --- a/src/context/AuthContext.tsx +++ b/src/context/AuthContext.tsx @@ -1,16 +1,12 @@ import React, { createContext, useCallback, useContext, useEffect, useState } from 'react' import { Alert, Linking } from 'react-native' -import { XuqmSDK, ImSDK, UpdateSDK } from '@xuqm/rn-sdk' +import { XuqmSDK, 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' -function buildImDbName(appId: string, userId: string): string { - return `xuqm_im_${appId}_${userId}` -} - interface AuthState { ready: boolean userId: string | null @@ -30,11 +26,21 @@ 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 (profile: UserProfile, imToken: string) => { + const initSDK = useCallback(async (profile: UserProfile, imToken: string, imTokenExpiresAt?: number | null) => { const appKey = profile.appId || APP_ID await XuqmSDK.initialize({ appKey }) - const appId = appKey - await ImSDK.loginWithToken(profile.userId, imToken, buildImDbName(appId, profile.userId)) + await XuqmSDK.login({ + userId: profile.userId, + userSig: imToken, + expiresAt: imTokenExpiresAt ?? undefined, + profile, + refreshUserSig: async () => { + const refreshed = await demoApi.refreshImToken(appKey) + await save(K.IM_TOKEN, refreshed.imToken) + await save(K.IM_TOKEN_EXPIRES_AT, refreshed.imTokenExpiresAt ?? null) + return { userSig: refreshed.imToken, expiresAt: refreshed.imTokenExpiresAt ?? undefined } + }, + }) setState({ ready: true, userId: profile.userId, profile }) UpdateSDK.checkAppUpdate() @@ -60,9 +66,10 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { try { const demoToken = await load(K.DEMO_TOKEN) const imToken = await load(K.IM_TOKEN) + const imTokenExpiresAt = await load(K.IM_TOKEN_EXPIRES_AT) const profile = await load(K.PROFILE) if (demoToken && imToken && profile) { - await initSDK(profile, imToken) + await initSDK(profile, imToken, imTokenExpiresAt ?? undefined) return } } catch { @@ -73,11 +80,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { restore() }, [initSDK]) - const handleAuthResult = useCallback(async (result: { demoToken: string; imToken: string; profile: UserProfile }) => { + const handleAuthResult = useCallback(async (result: { demoToken: string; demoTokenExpiresAt?: number | null; imToken: string; imTokenExpiresAt?: number | null; profile: UserProfile }) => { await save(K.DEMO_TOKEN, result.demoToken) await save(K.IM_TOKEN, result.imToken) + await save(K.IM_TOKEN_EXPIRES_AT, result.imTokenExpiresAt ?? null) await save(K.PROFILE, result.profile) - await initSDK(result.profile, result.imToken) + await initSDK(result.profile, result.imToken, result.imTokenExpiresAt ?? undefined) }, [initSDK]) const login = useCallback(async (userId: string, password: string) => { @@ -91,7 +99,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { }, [handleAuthResult]) const logout = useCallback(async () => { - ImSDK.disconnect() + await XuqmSDK.logout() await clearSession() setState({ ready: true, userId: null, profile: null }) }, []) diff --git a/src/utils/storage.ts b/src/utils/storage.ts index 827e775..356fa63 100644 --- a/src/utils/storage.ts +++ b/src/utils/storage.ts @@ -3,6 +3,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage' export const K = { DEMO_TOKEN: '@xuqm:demoToken', IM_TOKEN: '@xuqm:imToken', + IM_TOKEN_EXPIRES_AT: '@xuqm:imTokenExpiresAt', PROFILE: '@xuqm:profile', CONTACTS: '@xuqm:contacts', } as const @@ -22,5 +23,5 @@ export async function remove(key: string): Promise { } export async function clearSession(): Promise { - await Promise.all([K.DEMO_TOKEN, K.IM_TOKEN, K.PROFILE].map(k => AsyncStorage.removeItem(k))) + await Promise.all([K.DEMO_TOKEN, K.IM_TOKEN, K.IM_TOKEN_EXPIRES_AT, K.PROFILE].map(k => AsyncStorage.removeItem(k))) }