This commit is contained in:
eric
2026-03-26 01:59:04 -05:00
parent aba40c8cb7
commit 3bc1599763
12 changed files with 629 additions and 72 deletions

View File

@@ -0,0 +1,135 @@
import { useState } from 'react'
import {
ActivityIndicator,
KeyboardAvoidingView,
Linking,
Modal,
Platform,
Pressable,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native'
import { useAuth } from '@/context/AuthContext'
import { theme } from '@/constants/theme'
const VIP_URL = 'https://vip.hackrobot.cn/'
export function PocketBaseAuthModal() {
const { loginVisible, closeLogin, login } = useAuth()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [busy, setBusy] = useState(false)
const [err, setErr] = useState<string | null>(null)
const onSubmit = async () => {
setErr(null)
setBusy(true)
try {
await login(email.trim(), password)
setPassword('')
} catch (e) {
setErr(e instanceof Error ? e.message : String(e))
} finally {
setBusy(false)
}
}
return (
<Modal visible={loginVisible} animationType="fade" transparent onRequestClose={closeLogin}>
<KeyboardAvoidingView
style={styles.backdrop}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
>
<Pressable style={styles.scrim} onPress={closeLogin} />
<View style={styles.sheet}>
<Text style={styles.title}></Text>
<Text style={styles.sub}>
使退
</Text>
{err ? <Text style={styles.err}>{err}</Text> : null}
<Text style={styles.lbl}></Text>
<TextInput
style={styles.input}
value={email}
onChangeText={setEmail}
placeholder="you@example.com"
placeholderTextColor={theme.muted}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
/>
<Text style={styles.lbl}></Text>
<TextInput
style={styles.input}
value={password}
onChangeText={setPassword}
placeholder="••••••••"
placeholderTextColor={theme.muted}
secureTextEntry
/>
<Pressable
style={[styles.btn, busy && styles.btnDisabled]}
disabled={busy}
onPress={() => void onSubmit()}
>
{busy ? (
<ActivityIndicator color="#fff" />
) : (
<Text style={styles.btnText}></Text>
)}
</Pressable>
<View style={styles.row}>
<Pressable onPress={() => void Linking.openURL(VIP_URL)}>
<Text style={styles.link}></Text>
</Pressable>
<Text style={styles.sep}>·</Text>
<Pressable onPress={closeLogin}>
<Text style={styles.linkMuted}></Text>
</Pressable>
</View>
</View>
</KeyboardAvoidingView>
</Modal>
)
}
const styles = StyleSheet.create({
backdrop: { flex: 1, justifyContent: 'center', padding: 20 },
scrim: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(0,0,0,0.55)' },
sheet: {
borderRadius: 16,
padding: 20,
backgroundColor: theme.bgCard,
borderWidth: 1,
borderColor: theme.border,
},
title: { fontSize: 18, fontWeight: '700', color: theme.text, marginBottom: 8 },
sub: { fontSize: 13, color: theme.muted, lineHeight: 20, marginBottom: 14 },
err: { color: theme.danger, fontSize: 13, marginBottom: 10 },
lbl: { fontSize: 12, fontWeight: '600', color: theme.muted, marginBottom: 6 },
input: {
borderWidth: 1,
borderColor: theme.border,
borderRadius: 10,
padding: 12,
color: theme.text,
marginBottom: 12,
backgroundColor: theme.bg,
},
btn: {
backgroundColor: theme.accent,
paddingVertical: 14,
borderRadius: 12,
alignItems: 'center',
marginTop: 4,
},
btnDisabled: { opacity: 0.6 },
btnText: { color: '#fff', fontWeight: '700', fontSize: 15 },
row: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', marginTop: 16, gap: 8 },
link: { color: theme.accent, fontWeight: '600', fontSize: 14 },
linkMuted: { color: theme.muted, fontSize: 14 },
sep: { color: theme.muted },
})