import * as Device from "expo-device"; import * as Notifications from "expo-notifications"; import { useEffect, useState } from "react"; import { Platform } from "react-native"; type RegisterTokenParams = { apiKey?: string | null; backendUrl: string; appVersion?: string; locale?: string; topics?: string[]; }; export function usePushNotifications({ apiKey, backendUrl, appVersion = "1.0.0", locale, topics }: RegisterTokenParams & { apiKey?: string | null }) { const [expoPushToken, setExpoPushToken] = useState(null); useEffect(() => { if (!apiKey) return; (async () => { const token = await registerForPushNotificationsAsync(); if (token) { setExpoPushToken(token); await registerTokenWithBackend(token); } })(); }, [apiKey]); const registerTokenWithBackend = async (token: string) => { try { await fetch(`${backendUrl}/register_token`, { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": apiKey ?? "", }, body: JSON.stringify({ token, platform: Platform.OS, app_ver: appVersion, locale, topics }) }); console.log("Push token registered with backend ✅"); } catch (error) { console.error("Failed to register token with backend:", error); } }; return expoPushToken; } async function registerForPushNotificationsAsync() { if (!Device.isDevice) { console.log("Must use physical device for Push Notifications"); return null; } const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== "granted") { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== "granted") { console.log("Permission not granted for push notifications."); return null; } const tokenData = await Notifications.getExpoPushTokenAsync(); const token = tokenData.data; console.log("Expo Push Token:", token); // Android-specific setup if (Platform.OS === "android") { await Notifications.setNotificationChannelAsync("default", { name: "default", importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], lightColor: "#FF231F7C" }); } return token; }