t3-code-android-nightly/patches/expo-notifications@57.0.15.patch

119 lines
4.2 KiB
Diff

diff --git a/ios/ExpoNotifications/Notifications/NotificationCenterManager.swift b/ios/ExpoNotifications/Notifications/NotificationCenterManager.swift
--- a/ios/ExpoNotifications/Notifications/NotificationCenterManager.swift
+++ b/ios/ExpoNotifications/Notifications/NotificationCenterManager.swift
@@ -42,8 +42,10 @@
@objc
public static let shared = NotificationCenterManager()
- var delegates: [NotificationDelegate] = []
- var pendingResponses: [UNNotificationResponse] = []
+ // Module creation and destruction can overlap across React runtimes.
+ private let stateLock = NSLock()
+ private var delegates: [NotificationDelegate] = []
+ private var pendingResponses: [UNNotificationResponse] = []
let userNotificationCenter: UNUserNotificationCenter = UNUserNotificationCenter.current()
private override init() {
@@ -62,32 +64,49 @@
}
public func addDelegate(_ delegate: NotificationDelegate) {
- delegates.append(delegate)
+ let responses = stateLock.withLock {
+ delegates.append(delegate)
+ return pendingResponses
+ }
var handled = false
- for pendingResponse in pendingResponses {
+ for pendingResponse in responses {
handled = delegate.didReceive(pendingResponse, completionHandler: {}) || handled
}
if handled {
- pendingResponses.removeAll()
+ removePendingResponses(responses)
}
}
public func removeDelegate(_ delegate: AnyObject) {
- if let index = delegates.firstIndex(where: { $0 === delegate }) {
- delegates.remove(at: index)
+ stateLock.withLock {
+ if let index = delegates.firstIndex(where: { $0 === delegate }) {
+ delegates.remove(at: index)
+ }
+ }
+ }
+
+ private func snapshotDelegates() -> [NotificationDelegate] {
+ stateLock.withLock { delegates }
+ }
+
+ private func removePendingResponses(_ responses: [UNNotificationResponse]) {
+ let identifiers = Set(responses.map(ObjectIdentifier.init))
+ stateLock.withLock {
+ // Keep responses received while delegate callbacks were running.
+ pendingResponses.removeAll { identifiers.contains(ObjectIdentifier($0)) }
}
}
// MARK: - Called by PushTokenAppDelegateSubscriber
public func didFailRegistration(_ error: any Error) {
- for delegate in delegates {
+ for delegate in snapshotDelegates() {
delegate.didFailRegistration(error)
}
}
public func didRegister(_ deviceToken: String) {
- for delegate in delegates {
+ for delegate in snapshotDelegates() {
delegate.didRegister(deviceToken)
}
}
@@ -100,7 +119,7 @@
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
var handled = false
- for delegate in delegates {
+ for delegate in snapshotDelegates() {
handled = delegate.willPresent(notification, completionHandler: completionHandler) || handled
}
if !handled {
@@ -113,18 +132,23 @@
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
+ let currentDelegates = stateLock.withLock {
+ // A delegate registering during delivery must see this response too.
+ pendingResponses.append(response)
+ return delegates
+ }
var handled = false
- for delegate in delegates {
+ for delegate in currentDelegates {
handled = delegate.didReceive(response, completionHandler: completionHandler) || handled
}
- if !handled {
- pendingResponses.append(response)
+ if handled {
+ removePendingResponses([response])
}
completionHandler()
}
public func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) {
- for delegate in delegates {
+ for delegate in snapshotDelegates() {
delegate.openSettings(notification)
}
}
@@ -132,7 +156,7 @@
// MARK: - Called from NotificationsAppDelegateSubscriber
public func didReceive(_ userInfo: [AnyHashable: Any], completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
var handled = false
- for delegate in delegates {
+ for delegate in snapshotDelegates() {
handled = delegate.didReceive(userInfo, completionHandler: completionHandler) || handled
}
if !handled {