import { useLocalSearchParams, useRouter } from 'expo-router'; import { useEffect, useState } from 'react'; import { ActivityIndicator, StyleSheet, Text, View } from 'react-native'; import { supabase } from '../../lib/supabase'; import { colors } from '../../theme/colors'; // Supabase magic-link emails redirect to netralax://auth/callback with // the tokens in either the URL fragment (#access_token=...&refresh_token=...) // or the query string depending on the provider. Expo Router parses the // query string into useLocalSearchParams. The hash portion would require // expo-linking; we accept both shapes for safety. export default function AuthCallback() { const params = useLocalSearchParams<{ access_token?: string; refresh_token?: string; error?: string; error_description?: string; }>(); const router = useRouter(); const [status, setStatus] = useState<'working' | 'error'>('working'); const [message, setMessage] = useState(''); useEffect(() => { void (async () => { if (params.error) { setStatus('error'); setMessage(params.error_description ?? params.error); return; } if (!params.access_token || !params.refresh_token) { setStatus('error'); setMessage('Magic-Link-URL enthielt keine Tokens.'); return; } const { error } = await supabase.auth.setSession({ access_token: params.access_token, refresh_token: params.refresh_token, }); if (error) { setStatus('error'); setMessage(error.message); return; } router.replace('/(app)/chats'); })(); }, [params, router]); return ( {status === 'working' ? ( <> Du wirst angemeldet… ) : ( <> Anmeldung fehlgeschlagen {message} )} ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.bg, padding: 24, gap: 16, }, text: { color: colors.textMuted, fontSize: 14, textAlign: 'center' }, errorTitle: { color: colors.danger, fontSize: 18, fontWeight: '600' }, });