Files
etf-oglasi/frontend/app/_layout.tsx
T
ksan 45e57181a9
CI/CD / Backend Unit Tests (push) Successful in 2m16s
CI/CD / Deploy (push) Successful in 2m6s
CI/CD / Mobile Release (push) Successful in 22m0s
fix push notification delivery on android
2026-07-30 15:28:12 +02:00

79 lines
2.4 KiB
TypeScript

import "../globals.css";
import { useEffect, useState } from 'react';
import { Stack } from 'expo-router';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import {
getMessaging,
onMessage,
onNotificationOpenedApp,
getInitialNotification,
} from '@react-native-firebase/messaging';
import { registerDeviceToken, listenForTokenRefresh } from '@/services/notifications';
import { AuthProvider, useAuth } from "@/context/AuthContext";
import { useUpdatecheck } from '@/hooks/useUpdatecheck';
import { UpdatePrompt } from '@/components/UpdatePrompt';
import Toast from 'react-native-toast-message';
// The FCM background handler now lives in index.js (registered before this
// module loads) so it fires reliably while the app is backgrounded/killed.
function NotificationSetup() {
const { user, loading } = useAuth();
useEffect(() => {
if (loading || !user) return;
registerDeviceToken(user.token);
const messaging = getMessaging();
const unsubRefresh = listenForTokenRefresh(user.token);
const unsubForeground = onMessage(messaging, async (msg) => {
console.log('Foreground notification:', msg);
Toast.show({
type: 'info',
text1: (msg.data?.title as string | undefined) ?? 'New Notification',
text2: msg.data?.body as string | undefined,
position: 'top',
visibilityTime: 4000,
});
});
onNotificationOpenedApp(messaging, (msg) => {
console.log('Opened from background:', msg);
});
getInitialNotification(messaging).then((msg) => {
if (msg) console.log('Opened from quit state:', msg);
});
return () => {
unsubRefresh();
unsubForeground();
};
}, [user, loading]);
return null;
}
function UpdateCheck() {
const { updateInfo } = useUpdatecheck();
const [dismissed, setDismissed] = useState(false);
if (!updateInfo || dismissed) return null;
return <UpdatePrompt updateInfo={updateInfo} onDismiss={() => setDismissed(true)} />;
}
export default function RootLayout() {
return (
<AuthProvider>
<SafeAreaProvider>
<NotificationSetup />
<Stack screenOptions={{ headerShown: false }} />
<UpdateCheck />
<Toast />
</SafeAreaProvider>
</AuthProvider>
);
}