From 01a022813a3bf6f2063d1b7fcdd263ff6a562cc1 Mon Sep 17 00:00:00 2001 From: Lalit Sharma Date: Tue, 24 Feb 2026 01:00:27 +0000 Subject: [PATCH] Skip notification permission prompt when env flag is set --- apps/mobile/src/services/notifications.ts | 7 +++++++ apps/mobile/src/utils/env.ts | 10 ++++++++++ .../tests/notifications-permission.test.ts | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 apps/mobile/src/utils/env.ts create mode 100644 apps/mobile/tests/notifications-permission.test.ts diff --git a/apps/mobile/src/services/notifications.ts b/apps/mobile/src/services/notifications.ts index d783c40..179543c 100644 --- a/apps/mobile/src/services/notifications.ts +++ b/apps/mobile/src/services/notifications.ts @@ -15,6 +15,7 @@ import { setNotificationHandler } from "expo-notifications/build/NotificationsHa import scheduleNotificationAsync from "expo-notifications/build/scheduleNotificationAsync"; import setNotificationChannelAsync from "expo-notifications/build/setNotificationChannelAsync"; import { Platform } from "react-native"; +import { readEnvFlag } from "../utils/env"; import { buildReminderScheduleRequests, enabledReminderMinutes, @@ -25,9 +26,14 @@ import { const MANAGED_NOTIFICATION_SOURCE = "eclipse-timer"; const ANDROID_CHANNEL_ID = "eclipse-alerts"; const MAX_SCHEDULED_NOTIFICATIONS_PER_SYNC = 60; +const SKIP_PERMISSION_PROMPT_FLAG = "EXPO_PUBLIC_SKIP_NOTIFICATION_PERMISSION_PROMPT"; let hasConfiguredHandler = false; +export function shouldSkipNotificationPermissionPrompt() { + return readEnvFlag(SKIP_PERMISSION_PROMPT_FLAG); +} + export type NotificationSchedulingSettings = { vibrationEnabled: boolean; soundEnabled: boolean; @@ -130,6 +136,7 @@ export function configureNotificationPresentationHandler() { export async function ensureNotificationPermissionAsync() { const current = await getPermissionsAsync(); if (current.granted || current.status === "granted") return true; + if (shouldSkipNotificationPermissionPrompt()) return false; const requested = await requestPermissionsAsync({ ios: { diff --git a/apps/mobile/src/utils/env.ts b/apps/mobile/src/utils/env.ts new file mode 100644 index 0000000..923f90b --- /dev/null +++ b/apps/mobile/src/utils/env.ts @@ -0,0 +1,10 @@ +export function envFlagEnabled(value: string | undefined) { + if (typeof value !== "string") return false; + + const normalized = value.trim().toLowerCase(); + return normalized === "1" || normalized === "true" || normalized === "yes"; +} + +export function readEnvFlag(name: string) { + return envFlagEnabled(process.env[name]); +} diff --git a/apps/mobile/tests/notifications-permission.test.ts b/apps/mobile/tests/notifications-permission.test.ts new file mode 100644 index 0000000..65bcecf --- /dev/null +++ b/apps/mobile/tests/notifications-permission.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from "vitest"; + +import { envFlagEnabled } from "../src/utils/env"; + +describe("envFlagEnabled", () => { + it("returns true for true-like values", () => { + expect(envFlagEnabled("true")).toBe(true); + expect(envFlagEnabled("1")).toBe(true); + expect(envFlagEnabled("yes")).toBe(true); + }); + + it("returns false for false-like values", () => { + expect(envFlagEnabled(undefined)).toBe(false); + expect(envFlagEnabled("false")).toBe(false); + expect(envFlagEnabled("0")).toBe(false); + }); +});