129 lines
2.7 KiB
TypeScript
129 lines
2.7 KiB
TypeScript
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<undefined, SendTestPushNotificationResult>(
|
|
functions,
|
|
'sendTestPushNotification'
|
|
);
|
|
|
|
await callable();
|
|
}
|