expo-popcore-old/components/auth/auth-guard.tsx

111 lines
2.4 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 from 'react';
import { View, StyleSheet } from 'react-native';
import { useAuth } from '@/hooks/use-auth';
import { useAuthGuard } from '@/hooks/use-auth-guard';
import { ThemedText } from '@/components/themed-text';
interface AuthGuardProps {
children: React.ReactNode;
fallback?: React.ReactNode;
showLoginPrompt?: boolean;
title?: string;
subtitle?: string;
}
/**
* 认证守卫组件
* 用于包装需要登录才能访问的内容
*
* @param children - 需要保护的内容
* @param fallback - 未登录时显示的自定义内容(可选)
* @param showLoginPrompt - 是否显示默认的登录提示默认true
* @param title - 自定义提示标题
* @param subtitle - 自定义提示副标题
*
* @example
* ```typescript
* <AuthGuard>
* <ProtectedComponent />
* </AuthGuard>
*
* // 自定义提示
* <AuthGuard
* title="需要登录"
* subtitle="登录后即可使用此功能"
* >
* <ProtectedComponent />
* </AuthGuard>
* ```
*/
export function AuthGuard({
children,
fallback,
showLoginPrompt = true,
title = '需要登录',
subtitle = '请先登录以继续使用',
}: AuthGuardProps) {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) {
return <View style={styles.loadingContainer} />;
}
if (!isAuthenticated) {
if (fallback) {
return <>{fallback}</>;
}
if (showLoginPrompt) {
return (
<View style={styles.promptContainer}>
<View style={styles.iconContainer}>
<ThemedText style={styles.lockIcon}>🔒</ThemedText>
</View>
<ThemedText style={styles.title}>{title}</ThemedText>
<ThemedText style={styles.subtitle}>{subtitle}</ThemedText>
</View>
);
}
return null;
}
return <>{children}</>;
}
const styles = StyleSheet.create({
loadingContainer: {
flex: 1,
},
promptContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 32,
},
iconContainer: {
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: 'rgba(0, 122, 255, 0.1)',
alignItems: 'center',
justifyContent: 'center',
marginBottom: 24,
},
lockIcon: {
fontSize: 40,
},
title: {
fontSize: 24,
fontWeight: '700',
marginBottom: 12,
textAlign: 'center',
},
subtitle: {
fontSize: 16,
opacity: 0.7,
textAlign: 'center',
lineHeight: 24,
},
});