fix: guard expo-notifications against Expo Go crash on import
SDK 53+ removed push notification support from Expo Go, causing the module to throw at require-time. The static import in notifications.ts propagated the error to _layout.tsx and both tab screens, making expo- router report missing default exports and crash the app. Switch to a try/catch require() so the module initialises safely in Expo Go (Notifications stays null, all functions become no-ops) while still working correctly in EAS / development builds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+14
-2
@@ -1,4 +1,4 @@
|
||||
import * as Notifications from "expo-notifications";
|
||||
import type * as NotificationsType from "expo-notifications";
|
||||
import {
|
||||
loadNotifSettings,
|
||||
loadNotifThresholdLastFired,
|
||||
@@ -7,6 +7,11 @@ import {
|
||||
import type { ClaudeUsageResponse } from "@/types/claude";
|
||||
import type { CodexUsageResponse } from "@/types/codex";
|
||||
|
||||
// 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,
|
||||
@@ -16,13 +21,18 @@ Notifications.setNotificationHandler({
|
||||
shouldSetBadge: false,
|
||||
}),
|
||||
});
|
||||
} catch {
|
||||
// Running in Expo Go or native module unavailable — notifications disabled.
|
||||
}
|
||||
|
||||
export async function requestPermissions(): Promise<boolean> {
|
||||
if (!Notifications) return false;
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
return status === "granted";
|
||||
}
|
||||
|
||||
export async function getPermissionStatus(): Promise<string> {
|
||||
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<void> {
|
||||
if (!Notifications) return;
|
||||
try {
|
||||
await Notifications.cancelScheduledNotificationAsync(DAILY_ID);
|
||||
} catch {}
|
||||
@@ -68,6 +79,7 @@ export async function scheduleDailyDigest(
|
||||
}
|
||||
|
||||
export async function cancelDailyDigest(): Promise<void> {
|
||||
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",
|
||||
|
||||
Reference in New Issue
Block a user