Files
bw-expo-app/components/auth/auth-provider.tsx
imeepos 668caaa91f 🔐 feat: 认证系统升级 - 从重定向到底部Modal的完整改造
## 核心功能

### 1. 全局认证架构
- 新增 AuthProvider:全局认证上下文,管理登录状态和Modal
- 新增 useAuthGuard Hook:提供 requireAuth 认证拦截功能
- 新增 AuthGuard 组件:包装需要认证的组件
- 新增 AuthPrompt 组件:多种样式的登录引导组件

### 2. 登录体验优化
- LoginModal 已优化为底部抽屉式设计
- 登录成功后自动关闭Modal并恢复用户操作
- 支持队列机制,多个认证检查依次执行

### 3. 页面架构调整
- 根布局集成 AuthProvider
- 移除 Tabs 布局的重定向逻辑
- Explore 页面添加认证保护,显示登录提示

### 4. API安全增强
- 新增 TokenManager:完整的Token生命周期管理
- 新增 SecureClient:安全API客户端,自动处理认证
- 更新 API 客户端:支持认证头和自动Token刷新

### 5. 文档完善
- AUTH_SYSTEM.md:完整的认证系统使用指南
- AUTH_UPGRADE_SUMMARY.md:升级总结文档

## 技术亮点

 TypeScript 完整支持,编译时类型检查
 React 最佳实践,合理使用 Hooks 和 Context
 优雅的错误处理,友好的用户提示
 流畅的动画效果,原生级用户体验

## 核心优势

- 流畅:无需页面跳转,Modal即用即走
- 智能:自动检测登录需求,无需手动判断
- 安全:完整Token管理和自动刷新机制
- 灵活:多种认证组件满足不同场景
- 易用:详细文档和示例,快速上手

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 11:18:20 +08:00

82 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { createContext, useContext, useEffect, useState, useCallback } from 'react';
import { useAuth } from '@/hooks/use-auth';
import { LoginModal } from './login-modal';
export interface AuthContextType {
requireAuth: (callback?: () => void) => boolean;
showLoginModal: boolean;
setShowLoginModal: (show: boolean) => void;
pendingCallback: (() => void) | null;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export { AuthContext };
export function AuthProvider({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading } = useAuth();
const [showLoginModal, setShowLoginModal] = useState(false);
const [pendingCallback, setPendingCallback] = useState<(() => void) | null>(null);
// 认证拦截函数
const requireAuth = useCallback((callback?: () => void): boolean => {
if (isLoading) {
// 如果认证状态还在加载中,不执行任何操作
return false;
}
if (!isAuthenticated) {
// 未登录保存回调并显示登录Modal
setPendingCallback(() => callback || null);
setShowLoginModal(true);
return false;
}
// 已登录,执行回调
if (callback) {
callback();
}
return true;
}, [isAuthenticated, isLoading]);
// 监听登录状态变化
useEffect(() => {
if (isAuthenticated && showLoginModal) {
// 登录成功自动关闭Modal并执行回调
if (pendingCallback) {
pendingCallback();
setPendingCallback(null);
}
setShowLoginModal(false);
}
}, [isAuthenticated, showLoginModal, pendingCallback]);
const value = {
requireAuth,
showLoginModal,
setShowLoginModal,
pendingCallback,
};
return (
<AuthContext.Provider value={value}>
{children}
<LoginModal
visible={showLoginModal}
onClose={() => {
setShowLoginModal(false);
setPendingCallback(null);
}}
/>
</AuthContext.Provider>
);
}
export function useAuthGuard() {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuthGuard must be used within an AuthProvider');
}
return context;
}