Feature Requests

With Expo, you can write iOS and Android experiences in JavaScript using React Native.
[expo-notifications] `threadIdentifier` is parsed from local notification input but never applied to `UNMutableNotificationContent` (iOS)
## Summary NotificationContentRecord (the native Swift record backing scheduleNotificationAsync 's content ) declares threadIdentifier as a @Field , so it's correctly parsed out of the JS-supplied object and even read back out when serializing a received notification. But toUNMutableNotificationContent() — the method that builds the actual outgoing UNMutableNotificationContent for a scheduled local notification — never assigns it. Every other field on that record ( title , body , categoryIdentifier , sound , attachments , interruptionLevel , ...) is copied over; threadIdentifier is the one silent exception. Net effect: passing threadIdentifier when scheduling a local notification compiles, is accepted by the native module, and does... nothing. iOS falls back to its own default "Automatic" notification grouping instead of the app-authored one that was requested. _Posted here, it's kind of a bug, but not an error. But I can't, neither I will, create an full application to trigger the issue_ ## Where packages/expo-notifications/ios/ExpoNotifications/Notifications/NotificationRecords.swift ```swift @Field public var categoryIdentifier: String? @Field var threadIdentifier: String? // <- declared, parsed from input, read back on output... ... func toUNMutableNotificationContent() -> UNMutableNotificationContent { let content = UNMutableNotificationContent() ... if let categoryIdentifier = categoryIdentifier { content.categoryIdentifier = categoryIdentifier } // ...threadIdentifier is never assigned to content anywhere in this function. if let sound = sound { ... ## Fix ```swift if let threadIdentifier = threadIdentifier { content.threadIdentifier = threadIdentifier } placed alongside the categoryIdentifier assignment. One-line native fix. The public NotificationContentInput TS type should also expose threadIdentifier as an input field — right now it's only documented on NotificationContentIos , the read/output-only type ( For the input type, see NotificationContentInput ), so even a caller who wanted to use this had no typed way to do it. ```ts /** * iOS notification-thread identifier, used to group related notifications together in * Notification Center / on the Lock Screen. * @platform ios */ threadIdentifier?: string; ## Reference implementation I already have a working `patch-package` fix for both changes above, build but not tested against `expo-notifications@57.0.7` (don't have iOS dev license yet). Happy to open this as a PR if useful — let me know. ## How I found this I was investigating explicit notification grouping on Android (see Support explicit Android notification grouping (`setGroup`/`setGroupSummary`) for local `scheduleNotificationAsync`) and, before assuming iOS was fine by default, went looking for the iOS equivalent of Android's `setGroup`/`setGroupSummary`. `threadIdentifier` is the iOS mechanism for that, and tracing it through the native module is how I found it's a no-op today. To be clear, this is **not** the same failure mode as the Android issue: iOS doesn't need an app-authored group summary to keep each notification's actions reachable (grouped notifications stay individually addressable via long-press regardless of `threadIdentifier`), so nothing is *broken* by this bug today for apps that don't rely on `threadIdentifier`. It's a silently-dead input, not a crash or a regression — but anyone trying to use it will see it fail with no error or explanation. ## Environment expo: ~57.0.8 expo-notifications: ~57.0.7 react-native: 0.86.0 Platform: iOS ``` ## Related issues #28580 — grouping for push notifications ( android.group / threadId in the FCM/APNs payload). Different code path (remote push, not local scheduleNotificationAsync ); the reporter there also tried threadId on iOS without success, which is consistent with what I found, but that issue is scoped to push and doesn't diagnose the local-notification root cause. Searched the repo for existing issues about threadIdentifier being dropped/ignored before filing — didn't find one covering this specific gap.
0
[expo-notifications] Support explicit Android notification grouping (`setGroup`/`setGroupSummary`) for local `scheduleNotificationAsync`
## Summary expo-notifications has no way to opt local ( scheduleNotificationAsync ) Android notifications into an explicit, app-authored notification group ( NotificationCompat.Builder.setGroup() / setGroupSummary() ). Neither NotificationContentInput nor the native Android builder ( ExpoNotificationBuilder.kt / BaseNotificationBuilder.kt ) call setGroup / setGroupSummary anywhere — this capability just doesn't exist yet. ## Problem Any app that schedules 4+ local notifications into the same channel (a common pattern for reminder/recall-style apps) falls into Android's implicit auto-bundling fallback instead of a real, app-authored group. Per Android's own docs: > If your app sends four or more notifications and doesn't specify a group, the system automatically groups them on Android 7.0 and higher. [...] Automatic grouping behavior might vary on some device types. > — https://developer.android.com/develop/ui/views/notifications/group#automatic-grouping In practice, on several OEM skins this auto-bundled stack renders an expand chevron that doesn't reliably surface each notification's action buttons ( categoryIdentifier actions) once expanded — the chevron is there, but expanding it doesn't visibly do anything, and the per-notification action buttons are gone. That's the documented risk of relying on Android's fallback instead of defining the group explicitly, and today there's no way in expo-notifications to do the latter: NotificationContentInput has no groupKey / isGroupSummary /equivalent field. The remote-push payload does support a group key, but that's the FCM path — it doesn't touch local scheduled notifications at all. The native builder path ( ArgumentsNotificationContentBuilder → NotificationContent → ExpoNotificationBuilder.build() ) never calls setGroup() / setGroupSummary() . ## Proposed solution Add two optional, Android-only fields to NotificationContentInput : ```ts type NotificationContentInput = { // ...existing fields /** * Android notification group key. Notifications sharing the same groupKey are bundled * together by the system under one app-authored group. Pair with a single * isGroupSummary: true notification per groupKey. * @platform android */ groupKey?: string; /** * Marks this notification as the group summary for groupKey . * @platform android */ isGroupSummary?: boolean; }; ``` Wired straight through to NotificationCompat.Builder.setGroup(groupKey) / .setGroupSummary(true) in ExpoNotificationBuilder.build() . Ideally, the module would also take care of posting/refreshing the group-summary notification itself at delivery/dismissal time (in ExpoPresentationDelegate.presentNotification() / dismissNotifications() ), reusing each sibling notification's own already-authored title/text for the summary's InboxStyle lines. That avoids apps having to keep a JS-side summary in sync with what's actually in the tray, which is fragile — notifications can be delivered by an OS alarm while the app is killed, so there's no reliable JS-side hook to recompute a summary from. ## Why this matters Grouping isn't cosmetic here — without it, apps that legitimately schedule several local notifications (reminders, recalls, chat-style updates) have no supported way to keep each one individually actionable once Android's own notification count threshold kicks in. Right now the only way to fix that is a native patch to expo-notifications itself. ## Reference implementation I already have a working patch-package fix implementing the above (JS type + native builder wiring + delivery-time summary management in ExpoPresentationDelegate.kt ), tested against expo-notifications@57.0.7 — verified end-to-end against a fresh install. Happy to turn this into a PR if that's useful — let me know. ## Related #28580 — grouping for push notifications ( android.group in the FCM payload). Different code path; doesn't cover local scheduleNotificationAsync , which is what this request is about. #10962 , #31710 , #36282 — Android action buttons missing in other contexts (background/killed state, remote push). Related symptom, different root cause. Searched Canny and GitHub for existing setGroup / setGroupSummary /grouping requests before posting — didn't find one covering this specific gap.
0
Load More