import Constants from 'expo-constants'; import * as Device from 'expo-device'; import * as Notifications from 'expo-notifications'; import { httpsCallable } from 'firebase/functions'; import { arrayUnion, serverTimestamp, setDoc, } from 'firebase/firestore'; import { Platform } from 'react-native'; import { functions } from '@/lib/firebase'; import { userDocRef } from '@/lib/firestore'; Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldPlaySound: true, shouldSetBadge: true, shouldShowBanner: true, shouldShowList: true, }), }); type NotificationSettingsPayload = { expoPushToken: string | null; pushEnabled: boolean; platform: 'android' | 'ios' | null; }; type SendTestPushNotificationResult = { success: boolean; }; function isExpoPushToken(token: string) { return ( token.startsWith('ExponentPushToken[') || token.startsWith('ExpoPushToken[') ); } async function saveExpoPushToken( uid: string, expoPushToken: string ) { if (!isExpoPushToken(expoPushToken)) { return; } await setDoc( userDocRef(uid), { expoPushTokens: arrayUnion(expoPushToken), updatedAt: serverTimestamp(), }, { merge: true } ); } function getProjectId() { const projectId = Constants.expoConfig?.extra?.eas?.projectId ?? Constants.easConfig?.projectId; if (!projectId) { throw new Error('EAS projectId introuvable pour Expo Notifications.'); } return projectId; } export async function registerForPushNotifications(uid: string) { if (Platform.OS === 'web') { return null; } if (!Device.isDevice) { return null; } const existingPermissions = await Notifications.getPermissionsAsync(); let finalStatus = existingPermissions.status; if (finalStatus !== 'granted') { const requestedPermissions = await Notifications.requestPermissionsAsync(); finalStatus = requestedPermissions.status; } if (finalStatus !== 'granted') { return null; } const expoPushToken = ( await Notifications.getExpoPushTokenAsync({ projectId: getProjectId(), }) ).data; await saveExpoPushToken(uid, expoPushToken); return expoPushToken; } export function subscribeToPushTokenRefresh(uid: string) { if (Platform.OS === 'web') { return () => undefined; } const subscription = Notifications.addPushTokenListener((token) => { if (!isExpoPushToken(token.data)) { return; } void saveExpoPushToken(uid, token.data); }); return () => { subscription.remove(); }; } export async function sendTestPushNotification() { const callable = httpsCallable( functions, 'sendTestPushNotification' ); await callable(); }