用户静默注册
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
import {
|
||||
bootstrapSession,
|
||||
clearAuth,
|
||||
ensureSession,
|
||||
getDeviceKey,
|
||||
request,
|
||||
type SessionPayload,
|
||||
type UserProfile,
|
||||
} from '../lib/api';
|
||||
|
||||
type UserSessionContextValue = {
|
||||
ready: boolean;
|
||||
profile: UserProfile | null;
|
||||
phoneVerified: boolean;
|
||||
refreshProfile: () => Promise<void>;
|
||||
resetSession: () => Promise<void>;
|
||||
};
|
||||
|
||||
const UserSessionContext = createContext<UserSessionContextValue | null>(null);
|
||||
|
||||
export function UserSessionProvider({ children }: { children: ReactNode }) {
|
||||
const [ready, setReady] = useState(false);
|
||||
const [profile, setProfile] = useState<UserProfile | null>(null);
|
||||
const [phoneVerified, setPhoneVerified] = useState(false);
|
||||
|
||||
const applySession = useCallback((session: SessionPayload) => {
|
||||
if (session.user) setProfile(session.user);
|
||||
setPhoneVerified(!!session.phoneVerified || !!session.user?.phoneVerified);
|
||||
}, []);
|
||||
|
||||
const refreshProfile = useCallback(async () => {
|
||||
const me = await request<UserProfile>('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();
|
||||
}
|
||||
} 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,
|
||||
refreshProfile,
|
||||
resetSession,
|
||||
}),
|
||||
[ready, profile, phoneVerified, refreshProfile, resetSession],
|
||||
);
|
||||
|
||||
if (!ready) {
|
||||
return (
|
||||
<div className="session-boot">
|
||||
<p className="session-boot-text">加载中...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <UserSessionContext.Provider value={value}>{children}</UserSessionContext.Provider>;
|
||||
}
|
||||
|
||||
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 };
|
||||
Reference in New Issue
Block a user