// Deep-Link Bridge für OAuth-Callback (Google/Apple). // // Hintergrund: nach erfolgreichem OAuth-Login redirected Supabase zu // `rebreak://auth/callback#access_token=...`. Auf iOS schluckt // `WebBrowser.openAuthSessionAsync` den Deep-Link bevor expo-router ihn sieht. // Auf Android öffnet das System die App via Deep-Link → expo-router routet // `/auth/callback` BEVOR openAuthSessionAsync's Listener feuert → 404. // // Diese Bridge-Page fängt das ab: zeigt einen Loader, extrahiert Tokens als // Fallback (falls openAuthSessionAsync den Hash nicht selbst parst), und // navigiert nach (app). signin.tsx macht zusätzlich router.replace('/(app)') // nach openAuthSessionAsync resolve — diese Bridge ist nur für den Android- // 404-Flash da. import { useEffect } from 'react'; import { View, ActivityIndicator } from 'react-native'; import { useRouter, useLocalSearchParams } from 'expo-router'; import { supabase } from '../../lib/supabase'; import { useColors } from '../../lib/theme'; export default function AuthCallback() { const router = useRouter(); const colors = useColors(); const params = useLocalSearchParams<{ access_token?: string; refresh_token?: string }>(); useEffect(() => { let cancelled = false; (async () => { const accessToken = typeof params.access_token === 'string' ? params.access_token : undefined; const refreshToken = typeof params.refresh_token === 'string' ? params.refresh_token : undefined; if (accessToken && refreshToken) { try { await supabase.auth.setSession({ access_token: accessToken, refresh_token: refreshToken, }); } catch (err) { console.warn('[auth-callback] setSession failed:', err); } } // Kurzer Delay → onAuthStateChange propagiert die Session in den Store. if (!cancelled) { setTimeout(() => { router.replace('/(app)' as never); }, 60); } })(); return () => { cancelled = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( ); }