import "@/global.css"; import "@/src/i18n"; import { QueryClientProvider } from "@tanstack/react-query"; import { Stack, useRouter } from "expo-router"; import { HeroUINativeProvider } from "heroui-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { KeyboardProvider } from "react-native-keyboard-controller"; import { useEffect } from "react"; import { Linking, Alert } from "react-native"; import { AppThemeProvider } from "@/contexts/app-theme-context"; import { queryClient } from "@/src/lib/query-client"; import { authClient } from "@/src/lib/auth-client"; import { useAuthStore } from "@/src/stores/auth.store"; if (__DEV__) { const originalConsoleError = console.error; console.error = (...args: unknown[]) => { if (typeof args[0] === "string" && args[0].includes("Maximum update depth")) return; originalConsoleError(...args); }; } function DeepLinkHandler() { const router = useRouter(); async function handleUrl(url: string) { // Match haushaltsApp://invite?invitationId=xxx const match = url.match(/haushaltsApp:\/\/invite\?invitationId=([^&]+)/i); if (!match) return; const invitationId = match[1]!; const isLoggedIn = !!useAuthStore.getState().user; if (!isLoggedIn) { // Store invitationId and redirect after login useAuthStore.getState().setPendingInvitationId(invitationId); router.replace("/(auth)/login"); return; } try { const result = await authClient.organization.acceptInvitation({ invitationId }); if (result.error) throw new Error(result.error.message ?? "Fehler"); // Refresh households list const { apiRequest } = await import("@/src/lib/api-client"); const householdsResponse = await apiRequest<{ households: { id: string; name: string; role: string }[] }>("/api/households"); useAuthStore.getState().setHouseholds(householdsResponse.households); await queryClient.invalidateQueries(); Alert.alert("Einladung angenommen", "Du bist jetzt Mitglied des Haushalts."); router.replace("/(app)/haushalt"); } catch (err) { Alert.alert("Fehler", (err as Error).message ?? "Einladung konnte nicht angenommen werden."); } } useEffect(() => { // Handle cold start URL Linking.getInitialURL().then((url) => { if (url) void handleUrl(url); }); // Handle foreground/background URL const sub = Linking.addEventListener("url", ({ url }) => { void handleUrl(url); }); return () => sub.remove(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return null; } export default function Layout() { return ( ); }