85 lines
2.8 KiB
TypeScript
85 lines
2.8 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,
|
|
setBackgroundMessageHandler,
|
|
} from '@react-native-firebase/messaging';
|
|
import { registerDeviceToken, listenForTokenRefresh, displayLocalNotification } 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';
|
|
|
|
// Registered at module scope so it's installed as soon as this entry file
|
|
// loads, which is required for it to fire while the app is backgrounded/killed.
|
|
setBackgroundMessageHandler(getMessaging(), async (remoteMessage) => {
|
|
const title = remoteMessage.data?.title as string | undefined;
|
|
const body = remoteMessage.data?.body as string | undefined;
|
|
await displayLocalNotification(title, body);
|
|
});
|
|
|
|
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>
|
|
);
|
|
} |