import * as Notifications from "expo-notifications"; import { router } from "expo-router"; import { useEffect, useRef } from "react"; import { AppState, type AppStateStatus } from "react-native"; import { syncInvoiceSendReminders } from "@/lib/invoice-send-reminders"; import { api } from "@/lib/trpc"; function openInvoiceFromNotification(data: Record | undefined) { if (data?.type !== "invoice-send-reminder") return; const invoiceId = data.invoiceId; if (typeof invoiceId !== "string" || !invoiceId) return; router.push(`/(app)/invoices/${invoiceId}`); } /** Schedules local iOS/Android notifications for draft invoice send reminders. */ export function InvoiceReminderSync() { const utils = api.useUtils(); const invoicesQuery = api.invoices.getAll.useQuery( { status: "draft" }, { staleTime: 60_000 }, ); const wasBackgrounded = useRef(false); useEffect(() => { if (!invoicesQuery.data) return; void syncInvoiceSendReminders(invoicesQuery.data); }, [invoicesQuery.data]); useEffect(() => { const subscription = AppState.addEventListener("change", (nextState: AppStateStatus) => { if (nextState === "background" || nextState === "inactive") { wasBackgrounded.current = true; return; } if (nextState !== "active" || !wasBackgrounded.current) return; wasBackgrounded.current = false; void utils.invoices.getAll.invalidate({ status: "draft" }); }); return () => subscription.remove(); }, [utils.invoices.getAll]); useEffect(() => { const responseSubscription = Notifications.addNotificationResponseReceivedListener( (response) => { openInvoiceFromNotification( response.notification.request.content.data as Record, ); }, ); void Notifications.getLastNotificationResponseAsync().then((response) => { if (!response) return; openInvoiceFromNotification( response.notification.request.content.data as Record, ); }); return () => responseSubscription.remove(); }, []); return null; }