From 5d9da3527406ae0a2004f2869befab2260459e5e Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Sat, 20 Jun 2026 07:47:39 -0700 Subject: [PATCH 1/3] Structure notification permission failures Co-authored-by: codex --- .../notificationPermissions.ts | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/apps/mobile/src/features/agent-awareness/notificationPermissions.ts b/apps/mobile/src/features/agent-awareness/notificationPermissions.ts index ce8dfddf3d2..2b449928bad 100644 --- a/apps/mobile/src/features/agent-awareness/notificationPermissions.ts +++ b/apps/mobile/src/features/agent-awareness/notificationPermissions.ts @@ -1,5 +1,6 @@ import * as Notifications from "expo-notifications"; import * as Effect from "effect/Effect"; +import * as Schema from "effect/Schema"; import { Platform } from "react-native"; export type NotificationPermissionResult = @@ -7,9 +8,33 @@ export type NotificationPermissionResult = | { readonly type: "granted" } | { readonly type: "denied"; readonly canAskAgain: boolean }; +export class NotificationPermissionReadError extends Schema.TaggedErrorClass()( + "NotificationPermissionReadError", + { + platform: Schema.Literal("ios"), + cause: Schema.Defect(), + }, +) { + override get message(): string { + return `Failed to read notification permissions on ${this.platform}.`; + } +} + +export class NotificationPermissionRequestError extends Schema.TaggedErrorClass()( + "NotificationPermissionRequestError", + { + platform: Schema.Literal("ios"), + cause: Schema.Defect(), + }, +) { + override get message(): string { + return `Failed to request notification permissions on ${this.platform}.`; + } +} + export const requestAgentNotificationPermission: Effect.Effect< NotificationPermissionResult, - unknown + NotificationPermissionReadError | NotificationPermissionRequestError > = Effect.gen(function* () { if (Platform.OS !== "ios") { return { type: "unsupported" }; @@ -17,7 +42,7 @@ export const requestAgentNotificationPermission: Effect.Effect< const existing = yield* Effect.tryPromise({ try: () => Notifications.getPermissionsAsync(), - catch: (error) => error, + catch: (cause) => new NotificationPermissionReadError({ platform: "ios", cause }), }); if (existing.granted) { return { type: "granted" }; @@ -36,7 +61,7 @@ export const requestAgentNotificationPermission: Effect.Effect< allowSound: true, }, }), - catch: (error) => error, + catch: (cause) => new NotificationPermissionRequestError({ platform: "ios", cause }), }); return requested.granted ? { type: "granted" } From 436cf127d8bfb464677694589fad51ef36126135 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Sat, 20 Jun 2026 07:49:19 -0700 Subject: [PATCH 2/3] Preserve Live Activity preference causes Co-authored-by: codex --- .../agent-awareness/liveActivityPreferences.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/mobile/src/features/agent-awareness/liveActivityPreferences.ts b/apps/mobile/src/features/agent-awareness/liveActivityPreferences.ts index 8f73ffdf65e..932376e8bce 100644 --- a/apps/mobile/src/features/agent-awareness/liveActivityPreferences.ts +++ b/apps/mobile/src/features/agent-awareness/liveActivityPreferences.ts @@ -1,4 +1,5 @@ import * as Effect from "effect/Effect"; +import * as Schema from "effect/Schema"; import { HttpClient } from "effect/unstable/http"; import { ManagedRelay } from "@t3tools/client-runtime/relay"; @@ -7,6 +8,18 @@ import { savePreferencesPatch } from "../../lib/storage"; import { linkEnvironmentToCloud } from "../cloud/linkEnvironment"; import { refreshAgentAwarenessRegistration } from "./remoteRegistration"; +export class LiveActivityPreferenceSaveError extends Schema.TaggedErrorClass()( + "LiveActivityPreferenceSaveError", + { + enabled: Schema.Boolean, + cause: Schema.Defect(), + }, +) { + override get message(): string { + return `Failed to save the Live Activity updates setting (enabled: ${this.enabled}).`; + } +} + export function setLiveActivityUpdatesEnabled(input: { readonly enabled: boolean; readonly clerkToken: string | null; @@ -15,7 +28,7 @@ export function setLiveActivityUpdatesEnabled(input: { return Effect.gen(function* () { yield* Effect.tryPromise({ try: () => savePreferencesPatch({ liveActivitiesEnabled: input.enabled }), - catch: (error) => error, + catch: (cause) => new LiveActivityPreferenceSaveError({ enabled: input.enabled, cause }), }); yield* refreshAgentAwarenessRegistration(); From 0f03667eb25279589516d86cc7f0804e272c267b Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Sat, 20 Jun 2026 07:55:24 -0700 Subject: [PATCH 3/3] Remove redundant permission platform fields Co-authored-by: codex --- .../agent-awareness/notificationPermissions.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/mobile/src/features/agent-awareness/notificationPermissions.ts b/apps/mobile/src/features/agent-awareness/notificationPermissions.ts index 2b449928bad..dc275774a50 100644 --- a/apps/mobile/src/features/agent-awareness/notificationPermissions.ts +++ b/apps/mobile/src/features/agent-awareness/notificationPermissions.ts @@ -11,24 +11,22 @@ export type NotificationPermissionResult = export class NotificationPermissionReadError extends Schema.TaggedErrorClass()( "NotificationPermissionReadError", { - platform: Schema.Literal("ios"), cause: Schema.Defect(), }, ) { override get message(): string { - return `Failed to read notification permissions on ${this.platform}.`; + return "Failed to read notification permissions on iOS."; } } export class NotificationPermissionRequestError extends Schema.TaggedErrorClass()( "NotificationPermissionRequestError", { - platform: Schema.Literal("ios"), cause: Schema.Defect(), }, ) { override get message(): string { - return `Failed to request notification permissions on ${this.platform}.`; + return "Failed to request notification permissions on iOS."; } } @@ -42,7 +40,7 @@ export const requestAgentNotificationPermission: Effect.Effect< const existing = yield* Effect.tryPromise({ try: () => Notifications.getPermissionsAsync(), - catch: (cause) => new NotificationPermissionReadError({ platform: "ios", cause }), + catch: (cause) => new NotificationPermissionReadError({ cause }), }); if (existing.granted) { return { type: "granted" }; @@ -61,7 +59,7 @@ export const requestAgentNotificationPermission: Effect.Effect< allowSound: true, }, }), - catch: (cause) => new NotificationPermissionRequestError({ platform: "ios", cause }), + catch: (cause) => new NotificationPermissionRequestError({ cause }), }); return requested.granted ? { type: "granted" }