diff --git a/lib/notifications.ts b/lib/notifications.ts index ae68127..82dcfd6 100644 --- a/lib/notifications.ts +++ b/lib/notifications.ts @@ -1,4 +1,4 @@ -import * as Notifications from "expo-notifications"; +import type * as NotificationsType from "expo-notifications"; import { loadNotifSettings, loadNotifThresholdLastFired, @@ -7,22 +7,32 @@ import { import type { ClaudeUsageResponse } from "@/types/claude"; import type { CodexUsageResponse } from "@/types/codex"; -Notifications.setNotificationHandler({ - handleNotification: async () => ({ - shouldShowAlert: true, - shouldShowBanner: true, - shouldShowList: true, - shouldPlaySound: false, - shouldSetBadge: false, - }), -}); +// expo-notifications push notifications were removed from Expo Go in SDK 53. +// Use require() so the initialization error is caught gracefully in Expo Go. +let Notifications: typeof NotificationsType | null = null; +try { + Notifications = require("expo-notifications") as typeof NotificationsType; + Notifications.setNotificationHandler({ + handleNotification: async () => ({ + shouldShowAlert: true, + shouldShowBanner: true, + shouldShowList: true, + shouldPlaySound: false, + shouldSetBadge: false, + }), + }); +} catch { + // Running in Expo Go or native module unavailable — notifications disabled. +} export async function requestPermissions(): Promise { + if (!Notifications) return false; const { status } = await Notifications.requestPermissionsAsync(); return status === "granted"; } export async function getPermissionStatus(): Promise { + if (!Notifications) return "undetermined"; const { status } = await Notifications.getPermissionsAsync(); return status; } @@ -35,6 +45,7 @@ export async function scheduleDailyDigest( claudeUsage: ClaudeUsageResponse | null, codexUsage: CodexUsageResponse | null ): Promise { + if (!Notifications) return; try { await Notifications.cancelScheduledNotificationAsync(DAILY_ID); } catch {} @@ -68,6 +79,7 @@ export async function scheduleDailyDigest( } export async function cancelDailyDigest(): Promise { + if (!Notifications) return; try { await Notifications.cancelScheduledNotificationAsync(DAILY_ID); } catch {} @@ -128,7 +140,7 @@ export async function onUsageDataLoaded( claudeUsage, codexUsage ); - if (alerts.length > 0) { + if (alerts.length > 0 && Notifications) { await Notifications.scheduleNotificationAsync({ content: { title: "Low quota warning",