From 39194655b4a952383c25aff97926482a4c290be7 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Wed, 14 Oct 2026 11:56:04 +0200 Subject: [PATCH] Remove PushNotificationIOS --- packages/eslint-plugin-react-native/utils.js | 4 - .../jest-preset/jest/mocks/NativeModules.js | 43 -- .../src/configs/lazy-imports.js | 1 - .../NativePushNotificationManagerIOS.js | 14 - .../PushNotificationIOS.js | 692 ------------------ .../RCTPushNotificationManager.h | 48 -- .../RCTPushNotificationManager.mm | 621 ---------------- .../RCTPushNotificationPlugins.h | 40 - .../RCTPushNotificationPlugins.mm | 30 - .../React-RCTPushNotification.podspec | 56 -- packages/react-native/React-Core.podspec | 1 - packages/react-native/React/Base/RCTBridge.mm | 1 - packages/react-native/ReactNativeApi.d.ts | 98 +-- packages/react-native/__typetests__/index.tsx | 25 - packages/react-native/index.js | 26 +- packages/react-native/index.js.flow | 6 - .../react-native/scripts/cocoapods/utils.rb | 1 - .../scripts/ios-prebuild/headers-config.js | 7 - .../scripts/ios-prebuild/setup.js | 3 - .../NativePushNotificationManagerIOS.js | 108 --- .../PushNotificationIOS.d.ts | 286 -------- .../react-native/types_DEPRECATED/index.d.ts | 1 - packages/rn-tester/Podfile | 2 - packages/rn-tester/Podfile.lock | 38 +- packages/rn-tester/RNTester/AppDelegate.mm | 59 -- .../RNTesterPods.xcodeproj/project.pbxproj | 2 - .../PushNotificationIOSExample.js | 97 --- .../rn-tester/js/utils/RNTesterList.ios.js | 5 - packages/rn-tester/package.json | 7 - .../api-snapshots/ReactAppleDebugCxx.api | 113 --- .../api-snapshots/ReactAppleFrameworksCxx.api | 101 --- .../api-snapshots/ReactAppleNewarchCxx.api | 101 --- .../api-snapshots/ReactAppleReleaseCxx.api | 101 --- 33 files changed, 18 insertions(+), 2720 deletions(-) delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm delete mode 100644 packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec delete mode 100644 packages/react-native/src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS.js delete mode 100644 packages/react-native/types_DEPRECATED/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts delete mode 100644 packages/rn-tester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js diff --git a/packages/eslint-plugin-react-native/utils.js b/packages/eslint-plugin-react-native/utils.js index 12f0f3c2c417..99d21aecd387 100644 --- a/packages/eslint-plugin-react-native/utils.js +++ b/packages/eslint-plugin-react-native/utils.js @@ -403,10 +403,6 @@ const publicAPIMapping = { default: 'usePressability', types: null, }, - 'Libraries/PushNotificationIOS/PushNotificationIOS': { - default: 'PushNotificationIOS', - types: ['PushNotificationEventName', 'PushNotificationPermissions'], - }, 'Libraries/ReactNative/AppRegistry': { default: null, types: [ diff --git a/packages/jest-preset/jest/mocks/NativeModules.js b/packages/jest-preset/jest/mocks/NativeModules.js index 63bc6f410e44..6a22608cc50a 100644 --- a/packages/jest-preset/jest/mocks/NativeModules.js +++ b/packages/jest-preset/jest/mocks/NativeModules.js @@ -135,49 +135,6 @@ const NativeModules = { }; }, }, - PushNotificationManager: { - presentLocalNotification: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - scheduleLocalNotification: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - cancelAllLocalNotifications: jest.fn() as JestMockFn< - $FlowFixMe, - $FlowFixMe, - >, - removeAllDeliveredNotifications: jest.fn() as JestMockFn< - $FlowFixMe, - $FlowFixMe, - >, - getDeliveredNotifications: jest.fn(callback => - process.nextTick(() => []), - ) as JestMockFn<$FlowFixMe, $FlowFixMe>, - removeDeliveredNotifications: jest.fn() as JestMockFn< - $FlowFixMe, - $FlowFixMe, - >, - setApplicationIconBadgeNumber: jest.fn() as JestMockFn< - $FlowFixMe, - $FlowFixMe, - >, - getApplicationIconBadgeNumber: jest.fn(callback => - process.nextTick(() => callback(0)), - ) as JestMockFn<$FlowFixMe, $FlowFixMe>, - cancelLocalNotifications: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - getScheduledLocalNotifications: jest.fn(callback => - process.nextTick(() => callback()), - ) as JestMockFn<$FlowFixMe, $FlowFixMe>, - requestPermissions: jest.fn(() => - Promise.resolve({alert: true, badge: true, sound: true}), - ) as JestMockFn<$FlowFixMe, $FlowFixMe>, - abandonPermissions: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - checkPermissions: jest.fn(callback => - process.nextTick(() => callback({alert: true, badge: true, sound: true})), - ) as JestMockFn<$FlowFixMe, $FlowFixMe>, - getInitialNotification: jest.fn(() => Promise.resolve(null)) as JestMockFn< - $FlowFixMe, - $FlowFixMe, - >, - addListener: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - removeListeners: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>, - }, SourceCode: { getConstants(): $FlowFixMe { return { diff --git a/packages/react-native-babel-preset/src/configs/lazy-imports.js b/packages/react-native-babel-preset/src/configs/lazy-imports.js index 95cb75e262c2..d9f7a7cabb9d 100644 --- a/packages/react-native-babel-preset/src/configs/lazy-imports.js +++ b/packages/react-native-babel-preset/src/configs/lazy-imports.js @@ -71,7 +71,6 @@ module.exports = new Set([ 'PanResponder', 'PermissionsAndroid', 'PixelRatio', - 'PushNotificationIOS', 'Settings', 'Share', 'StyleSheet', diff --git a/packages/react-native/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js b/packages/react-native/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js deleted file mode 100644 index c47a4b86db11..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -export * from '../../src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS'; -import NativePushNotificationManagerIOS from '../../src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS'; - -export default NativePushNotificationManagerIOS; diff --git a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js b/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js deleted file mode 100644 index 7de529ce4f8b..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ /dev/null @@ -1,692 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import type {EventSubscription} from '../vendor/emitter/EventEmitter'; - -import NativeEventEmitter from '../EventEmitter/NativeEventEmitter'; -import Platform from '../Utilities/Platform'; -import NativePushNotificationManagerIOS from './NativePushNotificationManagerIOS'; -import invariant from 'invariant'; - -export type PushNotificationPermissions = { - alert: boolean, - badge: boolean, - sound: boolean, - [key: string]: boolean | number, -}; - -type PresentLocalNotificationDetails = { - alertBody: string, - alertAction?: string, - alertTitle?: string, - soundName?: string, - category?: string, - // $FlowFixMe[unclear-type] - userInfo?: Object, - applicationIconBadgeNumber?: number, - fireDate?: number, - isSilent?: boolean, -}; - -type ScheduleLocalNotificationDetails = { - ...PresentLocalNotificationDetails, - repeatInterval?: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute', -}; - -type NativePushNotificationIOSEventDefinitions = { - remoteNotificationReceived: [ - { - notificationId: string, - remote: boolean, - ... - }, - ], - remoteNotificationsRegistered: [ - { - deviceToken?: ?string, - ... - }, - ], - remoteNotificationRegistrationError: [ - { - message: string, - code: number, - details: {...}, - }, - ], - localNotificationReceived: [{...}], -}; - -const PushNotificationEmitter = - new NativeEventEmitter( - // T88715063: NativeEventEmitter only used this parameter on iOS. Now it uses it on all platforms, so this code was modified automatically to preserve its behavior - // If you want to use the native module on other platforms, please remove this condition and test its behavior - Platform.OS !== 'ios' ? null : NativePushNotificationManagerIOS, - ); - -const _notifHandlers = new Map(); - -const DEVICE_NOTIF_EVENT = 'remoteNotificationReceived'; -const NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered'; -const NOTIF_REGISTRATION_ERROR_EVENT = 'remoteNotificationRegistrationError'; -const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived'; - -export type ContentAvailable = 1 | null | void; - -export type FetchResult = { - NewData: 'UIBackgroundFetchResultNewData', - NoData: 'UIBackgroundFetchResultNoData', - ResultFailed: 'UIBackgroundFetchResultFailed', - ... -}; - -/** - * An event emitted by PushNotificationIOS. - */ -export type PushNotificationEventName = keyof { - /** - * Fired when a remote notification is received. The handler will be invoked - * with an instance of `PushNotificationIOS`. This will handle notifications - * that arrive in the foreground or were tapped to open the app from the - * background. - */ - notification: string, - /** - * Fired when a local notification is received. The handler will be invoked - * with an instance of `PushNotificationIOS`. This will handle notifications - * that arrive in the foreground or were tapped to open the app from the - * background. - */ - localNotification: string, - /** - * Fired when the user registers for remote notifications. The handler will be - * invoked with a hex string representing the deviceToken. - */ - register: string, - /** - * Fired when the user fails to register for remote notifications. Typically - * occurs due to APNS issues or if the device is a simulator. The handler - * will be invoked with {message: string, code: number, details: any}. - */ - registrationError: string, - ... -}; - -export interface PushNotification { - /** - * An alias for `getAlert` to get the notification's main message string - */ - // $FlowFixMe[unclear-type] - getMessage(): ?string | ?Object; - - /** - * Gets the sound string from the `aps` object - */ - getSound(): ?string; - - /** - * Gets the category string from the `aps` object - */ - getCategory(): ?string; - - /** - * Gets the notification's main message from the `aps` object - */ - // $FlowFixMe[unclear-type] - getAlert(): ?string | ?Object; - - /** - * Gets the content-available number from the `aps` object - */ - getContentAvailable(): ContentAvailable; - - /** - * Gets the badge count number from the `aps` object - */ - getBadgeCount(): ?number; - - /** - * Gets the data object on the notif - */ - // $FlowFixMe[unclear-type] - getData(): ?Object; - - /** - * Gets the thread ID on the notif - */ - getThreadID(): ?string; - - /** - * iOS Only - * Signifies remote notification handling is complete - */ - finish(result: string): void; -} - -/** - * Handle notifications for your app, including scheduling and permissions. - * - * See https://reactnative.dev/docs/pushnotificationios - * - * @deprecated Use [@react-native-community/push-notification-ios](https://www.npmjs.com/package/@react-native-community/push-notification-ios) instead - */ -class PushNotificationIOS { - // $FlowFixMe[unclear-type] - _data: Object; - // $FlowFixMe[unclear-type] - _alert: string | Object; - _sound: string; - _category: string; - _contentAvailable: ContentAvailable; - _badgeCount: number; - _notificationId: string; - _isRemote: boolean; - _remoteNotificationCompleteCallbackCalled: boolean; - _threadID: string; - - /** - * iOS fetch results that best describe the result of a finished remote notification handler. - * For a list of possible values, see `PushNotificationIOS.FetchResult`. - */ - static FetchResult: FetchResult = { - NewData: 'UIBackgroundFetchResultNewData', - NoData: 'UIBackgroundFetchResultNoData', - ResultFailed: 'UIBackgroundFetchResultFailed', - }; - - /** - * Schedules the localNotification for immediate presentation. - * details is an object containing: - * alertBody : The message displayed in the notification alert. - * alertAction : The "action" displayed beneath an actionable notification. Defaults to "view"; - * soundName : The sound played when the notification is fired (optional). - * category : The category of this notification, required for actionable notifications (optional). - * userInfo : An optional object containing additional notification data. - * applicationIconBadgeNumber (optional) : The number to display as the app's icon badge. The default value of this property is 0, which means that no badge is displayed. - * - * See https://reactnative.dev/docs/pushnotificationios#presentlocalnotification - */ - static presentLocalNotification( - details: PresentLocalNotificationDetails, - ): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - // $FlowFixMe[incompatible-type] - NativePushNotificationManagerIOS.presentLocalNotification(details); - } - - /** - * Schedules a local notification for future presentation. - * - * details is an object containing: - * fireDate : The date and time when the system should deliver the notification. - * alertBody : The message displayed in the notification alert. - * alertAction : The "action" displayed beneath an actionable notification. Defaults to "view"; - * soundName : The sound played when the notification is fired (optional). - * category : The category of this notification, required for actionable notifications (optional). - * userInfo : An optional object containing additional notification data. - * applicationIconBadgeNumber (optional) : The number to display as the app's icon badge. Setting the number to 0 removes the icon badge. - * - * See https://reactnative.dev/docs/pushnotificationios#schedulelocalnotification - */ - static scheduleLocalNotification( - details: ScheduleLocalNotificationDetails, - ): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - // $FlowFixMe[incompatible-type] - NativePushNotificationManagerIOS.scheduleLocalNotification(details); - } - - /** - * Cancels all scheduled local notifications. - * - * See https://reactnative.dev/docs/pushnotificationios#cancelalllocalnotifications - */ - static cancelAllLocalNotifications(): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.cancelAllLocalNotifications(); - } - - /** - * Removes all delivered notifications from Notification Center. - * - * See https://reactnative.dev/docs/pushnotificationios#removealldeliverednotifications - */ - static removeAllDeliveredNotifications(): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.removeAllDeliveredNotifications(); - } - - /** - * Provides a list of the app’s notifications that are currently displayed - * in Notification Center. - * - * See https://reactnative.dev/docs/pushnotificationios#getdeliverednotifications - */ - static getDeliveredNotifications( - // $FlowFixMe[unclear-type] - callback: (notifications: Array) => void, - ): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.getDeliveredNotifications(callback); - } - - /** - * Removes the specified notifications from Notification Center. - * - * See https://reactnative.dev/docs/pushnotificationios#removedeliverednotifications - */ - static removeDeliveredNotifications(identifiers: Array): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.removeDeliveredNotifications(identifiers); - } - - /** - * Sets the badge number for the app icon on the Home Screen. - * - * See https://reactnative.dev/docs/pushnotificationios#setapplicationiconbadgenumber - */ - static setApplicationIconBadgeNumber(number: number): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.setApplicationIconBadgeNumber(number); - } - - /** - * Gets the current badge number for the app icon on the Home Screen. - * - * See https://reactnative.dev/docs/pushnotificationios#getapplicationiconbadgenumber - */ - // $FlowFixMe[unclear-type] - static getApplicationIconBadgeNumber(callback: Function): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.getApplicationIconBadgeNumber(callback); - } - - /** - * Cancels any scheduled local notifications which match the fields in the - * provided `userInfo`. - * - * See https://reactnative.dev/docs/pushnotificationios#cancellocalnotification - */ - // $FlowFixMe[unclear-type] - static cancelLocalNotifications(userInfo: Object): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.cancelLocalNotifications(userInfo); - } - - /** - * Gets the list of local notifications that are currently scheduled. - * - * See https://reactnative.dev/docs/pushnotificationios#getscheduledlocalnotifications - */ - // $FlowFixMe[unclear-type] - static getScheduledLocalNotifications(callback: Function): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.getScheduledLocalNotifications(callback); - } - - /** - * Attaches a listener to notification events including local notifications, - * remote notifications, and notification registration results. - * - * See https://reactnative.dev/docs/pushnotificationios#addeventlistener - */ - static addEventListener( - type: PushNotificationEventName, - // $FlowFixMe[unclear-type] - handler: Function, - ): void { - invariant( - type === 'notification' || - type === 'register' || - type === 'registrationError' || - type === 'localNotification', - 'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events', - ); - let listener; - if (type === 'notification') { - listener = PushNotificationEmitter.addListener( - DEVICE_NOTIF_EVENT, - notifData => { - handler(new PushNotificationIOS(notifData)); - }, - ); - } else if (type === 'localNotification') { - listener = PushNotificationEmitter.addListener( - DEVICE_LOCAL_NOTIF_EVENT, - notifData => { - handler(new PushNotificationIOS(notifData)); - }, - ); - } else if (type === 'register') { - listener = PushNotificationEmitter.addListener( - NOTIF_REGISTER_EVENT, - registrationInfo => { - handler(registrationInfo.deviceToken); - }, - ); - } else if (type === 'registrationError') { - listener = PushNotificationEmitter.addListener( - NOTIF_REGISTRATION_ERROR_EVENT, - errorInfo => { - handler(errorInfo); - }, - ); - } - _notifHandlers.set(type, listener); - } - - /** - * Removes the event listener. Do this in `componentWillUnmount` to prevent - * memory leaks. - * - * See https://reactnative.dev/docs/pushnotificationios#removeeventlistener - */ - static removeEventListener(type: PushNotificationEventName): void { - invariant( - type === 'notification' || - type === 'register' || - type === 'registrationError' || - type === 'localNotification', - 'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events', - ); - const listener = _notifHandlers.get(type); - if (!listener) { - return; - } - listener.remove(); - _notifHandlers.delete(type); - } - - /** - * Requests notification permissions from iOS, prompting the user with a - * dialog box. By default, it will request all notification permissions, but - * you can optionally specify which permissions to request. - * - * See https://reactnative.dev/docs/pushnotificationios#requestpermissions - */ - static requestPermissions( - permissions?: PushNotificationPermissions, - ): Promise<{ - alert: boolean, - badge: boolean, - sound: boolean, - ... - }> { - let requestedPermissions = { - alert: true, - badge: true, - sound: true, - }; - if (permissions) { - requestedPermissions = { - alert: !!permissions.alert, - badge: !!permissions.badge, - sound: !!permissions.sound, - }; - } - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - return NativePushNotificationManagerIOS.requestPermissions( - requestedPermissions, - ); - } - - /** - * Unregister for all remote notifications received via Apple Push Notification - * service. - * You should call this method in rare circumstances only, such as when - * a new version of the app removes support for all types of remote - * notifications. Users can temporarily prevent apps from receiving - * remote notifications through the Notifications section of the - * Settings app. Apps unregistered through this method can always - * re-register. - * - * See https://reactnative.dev/docs/pushnotificationios#abandonpermissions - */ - static abandonPermissions(): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.abandonPermissions(); - } - - /** - * Check which push permissions are currently enabled. `callback` will be - * invoked with a `Permissions` object. - * - * - `alert` :boolean - * - `badge` :boolean - * - `sound` :boolean - * - * See https://reactnative.dev/docs/pushnotificationios#checkpermissions - */ - static checkPermissions( - callback: (permissions: PushNotificationPermissions) => void, - ): void { - invariant(typeof callback === 'function', 'Must provide a valid callback'); - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.checkPermissions(callback); - } - - /** - * This method returns a promise that resolves to either the notification - * object if the app was launched by a push notification, or `null` otherwise. - * - * See https://reactnative.dev/docs/pushnotificationios#getinitialnotification - */ - static getInitialNotification(): Promise { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - return NativePushNotificationManagerIOS.getInitialNotification().then( - notification => { - return notification && new PushNotificationIOS(notification); - }, - ); - } - - /** - * This method returns a promise that resolves to the current notification - * authorization status. See UNAuthorizationStatus for possible values. - */ - static getAuthorizationStatus( - callback: (authorizationStatus: number) => void, - ): void { - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - - NativePushNotificationManagerIOS.getAuthorizationStatus(callback); - } - - /** - * You will never need to instantiate `PushNotificationIOS` yourself. - * Listening to the `notification` event and invoking - * `getInitialNotification` is sufficient. - * - */ - // $FlowFixMe[unclear-type] - constructor(nativeNotif: Object) { - this._data = {}; - this._remoteNotificationCompleteCallbackCalled = false; - this._isRemote = nativeNotif.remote; - if (this._isRemote) { - this._notificationId = nativeNotif.notificationId; - } - - if (nativeNotif.remote) { - // Extract data from Apple's `aps` dict as defined: - // https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService - Object.keys(nativeNotif).forEach(notifKey => { - const notifVal = nativeNotif[notifKey]; - if (notifKey === 'aps') { - this._alert = notifVal.alert; - this._sound = notifVal.sound; - this._badgeCount = notifVal.badge; - this._category = notifVal.category; - this._contentAvailable = notifVal['content-available']; - this._threadID = notifVal['thread-id']; - } else { - this._data[notifKey] = notifVal; - } - }); - } else { - // Local notifications aren't being sent down with `aps` dict. - this._badgeCount = nativeNotif.applicationIconBadgeNumber; - this._sound = nativeNotif.soundName; - this._alert = nativeNotif.alertBody; - this._data = nativeNotif.userInfo; - this._category = nativeNotif.category; - } - } - - /** - * This method is available for remote notifications that have been received via: - * `application:didReceiveRemoteNotification:fetchCompletionHandler:`. See docs - * for more information. - * - * See https://reactnative.dev/docs/pushnotificationios#finish - */ - finish(fetchResult: string): void { - if ( - !this._isRemote || - !this._notificationId || - this._remoteNotificationCompleteCallbackCalled - ) { - return; - } - this._remoteNotificationCompleteCallbackCalled = true; - - invariant( - NativePushNotificationManagerIOS, - 'PushNotificationManager is not available.', - ); - NativePushNotificationManagerIOS.onFinishRemoteNotification( - this._notificationId, - fetchResult, - ); - } - - /** - * An alias for `getAlert` to get the notification's main message string. - */ - // $FlowFixMe[unclear-type] - getMessage(): ?string | ?Object { - // alias because "alert" is an ambiguous name - return this._alert; - } - - /** - * Gets the sound string from the `aps` object. This will be `null` for local - * notifications. - * - * See https://reactnative.dev/docs/pushnotificationios#getsound - */ - getSound(): ?string { - return this._sound; - } - - /** - * Gets the category string from the `aps` object. - * - * See https://reactnative.dev/docs/pushnotificationios#getcategory - */ - getCategory(): ?string { - return this._category; - } - - /** - * Gets the notification's main message from the `aps` object. Also see the - * alias: `getMessage()`. - * - * See https://reactnative.dev/docs/pushnotificationios#getalert - */ - // $FlowFixMe[unclear-type] - getAlert(): ?string | ?Object { - return this._alert; - } - - /** - * Gets the content-available number from the `aps` object. - * - * See https://reactnative.dev/docs/pushnotificationios#getcontentavailable - */ - getContentAvailable(): ContentAvailable { - return this._contentAvailable; - } - - /** - * Gets the badge count number from the `aps` object. - * - * See https://reactnative.dev/docs/pushnotificationios#getbadgecount - */ - getBadgeCount(): ?number { - return this._badgeCount; - } - - /** - * Gets the data object on the notification. - * - * See https://reactnative.dev/docs/pushnotificationios#getdata - */ - // $FlowFixMe[unclear-type] - getData(): ?Object { - return this._data; - } - - /** - * Gets the thread ID on the notification. - * - * See https://reactnative.dev/docs/pushnotificationios#getthreadid - */ - getThreadID(): ?string { - return this._threadID; - } -} - -export default PushNotificationIOS; diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h deleted file mode 100644 index 3f72180dfa78..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -extern NSString *const RCTRemoteNotificationReceived; - -@interface RCTPushNotificationManager : RCTEventEmitter - -typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result); - -+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; -+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; -/** - * Triggers remoteNotificationReceived or localNotificationReceived events. - * - * Call this method from UNUserNotificationCenterDelegate's - * `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:` in order to process a user tap on a - * notification. - * - * To process notifications received while the app is in the foreground, call this method from - * `userNotificationCenter:willPresentNotification:withCompletionHandler:`. Use the completion handler to determine if - * the push notification should be shown; to match prior behavior which does not show foreground notifications, use - * UNNotificationPresentationOptionNone. - * - * If you need to determine if the notification is remote, check that notification.request.trigger - * is an instance of UNPushNotificationTrigger. - */ -+ (void)didReceiveNotification:(UNNotification *)notification; -/** - * Call this from your app delegate's `application:didReceiveRemoteNotification:fetchCompletionHandler:`. If you - * implement both that method and `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:`, only - * the latter will be called. - */ -+ (void)didReceiveRemoteNotification:(NSDictionary *)notification - fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler; - -/** - * Call this in `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:` - * to get the correct value from .getInitialNotification in JS. - */ -+ (void)setInitialNotification:(UNNotification *)notification; - -@end diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm deleted file mode 100644 index 963edd3edcb8..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import - -#import -#import -#import -#import - -#import "RCTPushNotificationPlugins.h" - -NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived"; - -static NSString *const kLocalNotificationReceived = @"LocalNotificationReceived"; -static NSString *const kRemoteNotificationsRegistered = @"RemoteNotificationsRegistered"; -static NSString *const kRemoteNotificationRegistrationFailed = @"RemoteNotificationRegistrationFailed"; - -static NSString *const kErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS"; -static UNNotification *kInitialNotification = nil; - -@interface RCTPushNotificationManager () -@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks; -@end - -@implementation RCTConvert (UNNotificationContent) - -+ (UNNotificationContent *)UNNotificationContent:(id)json -{ - NSDictionary *details = [self NSDictionary:json]; - UNMutableNotificationContent *content = [UNMutableNotificationContent new]; -#if !TARGET_OS_TV - BOOL isSilent = [RCTConvert BOOL:details[@"isSilent"]]; - content.title = [RCTConvert NSString:details[@"alertTitle"]]; - content.body = [RCTConvert NSString:details[@"alertBody"]]; - content.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]]; - content.categoryIdentifier = [RCTConvert NSString:details[@"category"]]; - if (!isSilent) { - NSString *soundName = [RCTConvert NSString:details[@"soundName"]]; - content.sound = - soundName ? [UNNotificationSound soundNamed:details[@"soundName"]] : [UNNotificationSound defaultSound]; - } -#endif - if (details[@"applicationIconBadgeNumber"]) { - content.badge = [RCTConvert NSNumber:details[@"applicationIconBadgeNumber"]]; - } - - return content; -} - -+ (NSDictionary *)NSDictionaryForNotification: - (JS::NativePushNotificationManagerIOS::Notification &)notification -{ - // Note: alertAction is not set, as it is no longer relevant with UNNotification - NSMutableDictionary *notificationDict = [NSMutableDictionary new]; - notificationDict[@"alertTitle"] = notification.alertTitle(); - notificationDict[@"alertBody"] = notification.alertBody(); - notificationDict[@"userInfo"] = notification.userInfo(); - notificationDict[@"category"] = notification.category(); - if (notification.fireIntervalSeconds()) { - notificationDict[@"fireIntervalSeconds"] = @(*notification.fireIntervalSeconds()); - } - if (notification.fireDate()) { - notificationDict[@"fireDate"] = @(*notification.fireDate()); - } - if (notification.applicationIconBadgeNumber()) { - notificationDict[@"applicationIconBadgeNumber"] = @(*notification.applicationIconBadgeNumber()); - } - if (notification.isSilent()) { - notificationDict[@"isSilent"] = @(*notification.isSilent()); - if ([notificationDict[@"isSilent"] isEqualToNumber:@(NO)]) { - notificationDict[@"soundName"] = notification.soundName(); - } - } - return notificationDict; -} - -@end - -@implementation RCTConvert (UIBackgroundFetchResult) - -RCT_ENUM_CONVERTER( - UIBackgroundFetchResult, - (@{ - @"UIBackgroundFetchResultNewData" : @(UIBackgroundFetchResultNewData), - @"UIBackgroundFetchResultNoData" : @(UIBackgroundFetchResultNoData), - @"UIBackgroundFetchResultFailed" : @(UIBackgroundFetchResultFailed), - }), - UIBackgroundFetchResultNoData, - integerValue) - -@end - -@implementation RCTPushNotificationManager - -/** For delivered notifications */ -static NSDictionary *RCTFormatUNNotification(UNNotification *notification) -{ - NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary]; - if (notification.date) { - formattedLocalNotification[@"fireDate"] = RCTFormatNotificationDateFromNSDate(notification.date); - } - [formattedLocalNotification addEntriesFromDictionary:RCTFormatUNNotificationContent(notification.request.content)]; - return formattedLocalNotification; -} - -/** For scheduled notification requests */ -static NSDictionary *RCTFormatUNNotificationRequest(UNNotificationRequest *request) -{ - NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary]; - if (request.trigger) { - NSDate *triggerDate = nil; - if ([request.trigger isKindOfClass:[UNTimeIntervalNotificationTrigger class]]) { - triggerDate = [(UNTimeIntervalNotificationTrigger *)request.trigger nextTriggerDate]; - } else if ([request.trigger isKindOfClass:[UNCalendarNotificationTrigger class]]) { - triggerDate = [(UNCalendarNotificationTrigger *)request.trigger nextTriggerDate]; - } - - if (triggerDate) { - formattedLocalNotification[@"fireDate"] = RCTFormatNotificationDateFromNSDate(triggerDate); - } - } - [formattedLocalNotification addEntriesFromDictionary:RCTFormatUNNotificationContent(request.content)]; - return formattedLocalNotification; -} - -static NSDictionary *RCTFormatUNNotificationContent(UNNotificationContent *content) -{ - // Note: soundName is not set because this can't be read from UNNotificationSound. - // Note: alertAction is no longer relevant with UNNotification - NSMutableDictionary *formattedLocalNotification = [NSMutableDictionary dictionary]; -#if !TARGET_OS_TV - formattedLocalNotification[@"alertTitle"] = RCTNullIfNil(content.title); - formattedLocalNotification[@"alertBody"] = RCTNullIfNil(content.body); - formattedLocalNotification[@"userInfo"] = RCTNullIfNil(RCTJSONClean(content.userInfo)); - formattedLocalNotification[@"category"] = content.categoryIdentifier; -#endif - formattedLocalNotification[@"applicationIconBadgeNumber"] = content.badge; - formattedLocalNotification[@"remote"] = @NO; - return formattedLocalNotification; -} - -static NSString *RCTFormatNotificationDateFromNSDate(NSDate *date) -{ - NSDateFormatter *formatter = [NSDateFormatter new]; - [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"]; - return [formatter stringFromDate:date]; -} - -static BOOL IsNotificationRemote(UNNotification *notification) -{ - return [notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]; -} - -RCT_EXPORT_MODULE() - -- (dispatch_queue_t)methodQueue -{ - return dispatch_get_main_queue(); -} - -- (void)startObserving -{ - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleLocalNotificationReceived:) - name:kLocalNotificationReceived - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleRemoteNotificationReceived:) - name:RCTRemoteNotificationReceived - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleRemoteNotificationsRegistered:) - name:kRemoteNotificationsRegistered - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleRemoteNotificationRegistrationError:) - name:kRemoteNotificationRegistrationFailed - object:nil]; -} - -- (void)stopObserving -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (NSArray *)supportedEvents -{ - return @[ - @"localNotificationReceived", - @"remoteNotificationReceived", - @"remoteNotificationsRegistered", - @"remoteNotificationRegistrationError" - ]; -} - -+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - NSMutableString *hexString = [NSMutableString string]; - NSUInteger deviceTokenLength = deviceToken.length; - const unsigned char *bytes = reinterpret_cast(deviceToken.bytes); - for (NSUInteger i = 0; i < deviceTokenLength; i++) { - [hexString appendFormat:@"%02x", bytes[i]]; - } - [[NSNotificationCenter defaultCenter] postNotificationName:kRemoteNotificationsRegistered - object:self - userInfo:@{@"deviceToken" : [hexString copy]}]; -} - -+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error -{ - [[NSNotificationCenter defaultCenter] postNotificationName:kRemoteNotificationRegistrationFailed - object:self - userInfo:@{@"error" : error}]; -} - -+ (void)didReceiveNotification:(UNNotification *)notification -{ - BOOL const isRemoteNotification = IsNotificationRemote(notification); - if (isRemoteNotification) { -#if !TARGET_OS_TV - NSDictionary *userInfo = @{@"notification" : notification.request.content.userInfo}; - [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived - object:self - userInfo:userInfo]; -#endif - } else { - [[NSNotificationCenter defaultCenter] postNotificationName:kLocalNotificationReceived - object:self - userInfo:RCTFormatUNNotification(notification)]; - } -} - -+ (void)didReceiveRemoteNotification:(NSDictionary *)notification - fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler -{ - NSDictionary *userInfo = completionHandler - ? @{@"notification" : notification, @"completionHandler" : completionHandler} - : @{@"notification" : notification}; - [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived - object:self - userInfo:userInfo]; -} - -+ (void)setInitialNotification:(UNNotification *)notification -{ - kInitialNotification = notification; -} - -- (void)invalidate -{ - [super invalidate]; - - kInitialNotification = nil; -} - -- (void)dealloc -{ - kInitialNotification = nil; -} - -- (void)handleLocalNotificationReceived:(NSNotification *)notification -{ - [self sendEventWithName:@"localNotificationReceived" body:notification.userInfo]; -} - -- (void)handleRemoteNotificationReceived:(NSNotification *)notification -{ - NSMutableDictionary *remoteNotification = - [NSMutableDictionary dictionaryWithDictionary:notification.userInfo[@"notification"]]; - RCTRemoteNotificationCallback completionHandler = notification.userInfo[@"completionHandler"]; - NSString *notificationId = [[NSUUID UUID] UUIDString]; - remoteNotification[@"notificationId"] = notificationId; - remoteNotification[@"remote"] = @YES; - if (completionHandler) { - if (!self.remoteNotificationCallbacks) { - // Lazy initialization - self.remoteNotificationCallbacks = [NSMutableDictionary dictionary]; - } - self.remoteNotificationCallbacks[notificationId] = completionHandler; - } - - [self sendEventWithName:@"remoteNotificationReceived" body:remoteNotification]; -} - -- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification -{ - [self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo]; -} - -- (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification -{ - NSError *error = notification.userInfo[@"error"]; - NSDictionary *errorDetails = @{ - @"message" : error.localizedDescription, - @"code" : @(error.code), - @"details" : error.userInfo, - }; - [self sendEventWithName:@"remoteNotificationRegistrationError" body:errorDetails]; -} - -- (void)onFinishRemoteNotification:(NSString *)notificationId fetchResult:(NSString *)fetchResult -{ - UIBackgroundFetchResult result = [RCTConvert UIBackgroundFetchResult:fetchResult]; - RCTRemoteNotificationCallback completionHandler = self.remoteNotificationCallbacks[notificationId]; - if (!completionHandler) { - RCTLogError(@"There is no completion handler with notification id: %@", notificationId); - return; - } - completionHandler(result); - [self.remoteNotificationCallbacks removeObjectForKey:notificationId]; -} - -/** - * Update the application icon badge number on the home screen - */ -- (void)setApplicationIconBadgeNumber:(double)number -{ - NSInteger badgeCount = (NSInteger)lround(number); - if (@available(iOS 16.0, *)) { - [UNUserNotificationCenter.currentNotificationCenter - setBadgeCount:badgeCount - withCompletionHandler:^(NSError *_Nullable error) { - if (error != nil) { - RCTLogWarn(@"Failed to set application icon badge number: %@", error); - } - }]; - } else { - RCTSharedApplication().applicationIconBadgeNumber = badgeCount; - } -} - -/** - * Get the current application icon badge number on the home screen - */ -- (void)getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback -{ - callback(@[ @(RCTSharedApplication().applicationIconBadgeNumber) ]); -} - -- (void)requestPermissions:(JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission &)permissions - resolve:(RCTPromiseResolveBlock)resolve - reject:(RCTPromiseRejectBlock)reject -{ - if (RCTRunningInAppExtension()) { - reject( - kErrorUnableToRequestPermissions, - nil, - RCTErrorWithMessage(@"Requesting push notifications is currently unavailable in an app extension")); - return; - } - - // Add a listener to make sure that startObserving has been called - [self addListener:@"remoteNotificationsRegistered"]; - - UNAuthorizationOptions options = UNAuthorizationOptionNone; - - if (permissions.alert()) { - options |= UNAuthorizationOptionAlert; - } - if (permissions.badge()) { - options |= UNAuthorizationOptionBadge; - } - if (permissions.sound()) { - options |= UNAuthorizationOptionSound; - } - - [UNUserNotificationCenter.currentNotificationCenter - requestAuthorizationWithOptions:options - completionHandler:^(BOOL granted, NSError *_Nullable error) { - if (error != NULL) { - reject(@"-1", @"Error - Push authorization request failed.", error); - } else { - dispatch_async(dispatch_get_main_queue(), ^{ - [RCTSharedApplication() registerForRemoteNotifications]; - [UNUserNotificationCenter.currentNotificationCenter - getNotificationSettingsWithCompletionHandler:^( - UNNotificationSettings *_Nonnull settings) { - resolve(RCTPromiseResolveValueForUNNotificationSettings(settings)); - }]; - }); - } - }]; -} - -- (void)abandonPermissions -{ - [RCTSharedApplication() unregisterForRemoteNotifications]; -} - -- (void)checkPermissions:(RCTResponseSenderBlock)callback -{ - if (RCTRunningInAppExtension()) { - callback(@[ RCTSettingsDictForUNNotificationSettings(NO, NO, NO, NO, NO, NO, UNAuthorizationStatusNotDetermined) ]); - return; - } - - [UNUserNotificationCenter.currentNotificationCenter - getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) { - callback(@[ RCTPromiseResolveValueForUNNotificationSettings(settings) ]); - }]; -} - -static inline NSDictionary *RCTPromiseResolveValueForUNNotificationSettings(UNNotificationSettings *_Nonnull settings) -{ -#if TARGET_OS_TV - return RCTSettingsDictForUNNotificationSettings( - NO, settings.badgeSetting == UNNotificationSettingEnabled, NO, NO, NO, NO, settings.authorizationStatus); -#else - return RCTSettingsDictForUNNotificationSettings( - settings.alertSetting == UNNotificationSettingEnabled, - settings.badgeSetting == UNNotificationSettingEnabled, - settings.soundSetting == UNNotificationSettingEnabled, - settings.criticalAlertSetting == UNNotificationSettingEnabled, - settings.lockScreenSetting == UNNotificationSettingEnabled, - settings.notificationCenterSetting == UNNotificationSettingEnabled, - settings.authorizationStatus); -#endif -} - -static inline NSDictionary *RCTSettingsDictForUNNotificationSettings( - BOOL alert, - BOOL badge, - BOOL sound, - BOOL critical, - BOOL lockScreen, - BOOL notificationCenter, - UNAuthorizationStatus authorizationStatus) -{ - return @{ - @"alert" : @(alert), - @"badge" : @(badge), - @"sound" : @(sound), - @"critical" : @(critical), - @"lockScreen" : @(lockScreen), - @"notificationCenter" : @(notificationCenter), - @"authorizationStatus" : @(authorizationStatus) - }; -} - -- (void)presentLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification -{ - NSDictionary *notificationDict = [RCTConvert NSDictionaryForNotification:notification]; - UNNotificationContent *content = [RCTConvert UNNotificationContent:notificationDict]; - UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 - repeats:NO]; - UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[[NSUUID UUID] UUIDString] - content:content - trigger:trigger]; - - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center addNotificationRequest:request withCompletionHandler:nil]; -} - -- (void)scheduleLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification -{ - NSDictionary *notificationDict = [RCTConvert NSDictionaryForNotification:notification]; - UNNotificationContent *content = [RCTConvert UNNotificationContent:notificationDict]; - - UNNotificationTrigger *trigger = nil; - if (notificationDict[@"fireDate"]) { - NSDate *fireDate = [RCTConvert NSDate:notificationDict[@"fireDate"]] ?: [NSDate date]; - NSCalendar *calendar = [NSCalendar currentCalendar]; - NSDateComponents *components = - [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | - NSCalendarUnitMinute | NSCalendarUnitSecond) - fromDate:fireDate]; - trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:NO]; - } else if (notificationDict[@"fireIntervalSeconds"]) { - trigger = [UNTimeIntervalNotificationTrigger - triggerWithTimeInterval:[notificationDict[@"fireIntervalSeconds"] doubleValue] - repeats:NO]; - } - - UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[[NSUUID UUID] UUIDString] - content:content - trigger:trigger]; - - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center addNotificationRequest:request withCompletionHandler:nil]; -} - -- (void)cancelAllLocalNotifications -{ - [[UNUserNotificationCenter currentNotificationCenter] - getPendingNotificationRequestsWithCompletionHandler:^(NSArray *requests) { - NSMutableArray *notificationIdentifiersToCancel = [NSMutableArray new]; - for (UNNotificationRequest *request in requests) { - [notificationIdentifiersToCancel addObject:request.identifier]; - } - [[UNUserNotificationCenter currentNotificationCenter] - removePendingNotificationRequestsWithIdentifiers:notificationIdentifiersToCancel]; - }]; -} - -- (void)cancelLocalNotifications:(NSDictionary *)userInfoRaw -{ -#if !TARGET_OS_TV - NSDictionary *userInfo = [RCTConvert NSDictionary:userInfoRaw]; - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center getPendingNotificationRequestsWithCompletionHandler:^(NSArray *_Nonnull requests) { - NSMutableArray *notificationIdentifiersToCancel = [NSMutableArray new]; - for (UNNotificationRequest *request in requests) { - NSDictionary *notificationInfo = request.content.userInfo; - // Note: we do this with a loop instead of just `isEqualToDictionary:` - // because we only require that all specified userInfo values match the - // notificationInfo values - notificationInfo may contain additional values - // which we don't care about. - __block BOOL shouldCancel = YES; - [userInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { - if (![notificationInfo[key] isEqual:obj]) { - shouldCancel = NO; - *stop = YES; - } - }]; - - if (shouldCancel) { - [notificationIdentifiersToCancel addObject:request.identifier]; - } - } - - [center removePendingNotificationRequestsWithIdentifiers:notificationIdentifiersToCancel]; - }]; -#endif -} - -- (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(__unused RCTPromiseRejectBlock)reject -{ - // The user actioned a local or remote notification to launch the app. Notification is represented by UNNotification. - // Set this property in the implementation of - // userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler. - if (kInitialNotification) { - NSDictionary *notificationDict = - RCTFormatUNNotificationContent(kInitialNotification.request.content); - if (IsNotificationRemote(kInitialNotification)) { - // For backwards compatibility, remote notifications only returns a userInfo dict. - NSMutableDictionary *userInfoCopy = [notificationDict[@"userInfo"] mutableCopy]; - userInfoCopy[@"remote"] = @YES; - resolve(userInfoCopy); - } else { - // For backwards compatibility, local notifications return the notification. - resolve(notificationDict); - } - return; - } - - resolve((id)kCFNull); -} - -- (void)getScheduledLocalNotifications:(RCTResponseSenderBlock)callback -{ - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center getPendingNotificationRequestsWithCompletionHandler:^(NSArray *_Nonnull requests) { - NSMutableArray *formattedScheduledLocalNotifications = [NSMutableArray new]; - for (UNNotificationRequest *request in requests) { - [formattedScheduledLocalNotifications addObject:RCTFormatUNNotificationRequest(request)]; - } - callback(@[ formattedScheduledLocalNotifications ]); - }]; -} - -- (void)removeAllDeliveredNotifications -{ -#if !TARGET_OS_TV - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center removeAllDeliveredNotifications]; -#endif -} - -- (void)removeDeliveredNotifications:(NSArray *)identifiersRaw -{ -#if !TARGET_OS_TV - NSArray *identifiers = [RCTConvert NSStringArray:identifiersRaw]; - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center removeDeliveredNotificationsWithIdentifiers:identifiers]; -#endif -} - -- (void)getDeliveredNotifications:(RCTResponseSenderBlock)callback -{ -#if !TARGET_OS_TV - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center getDeliveredNotificationsWithCompletionHandler:^(NSArray *_Nonnull notifications) { - NSMutableArray *formattedNotifications = [NSMutableArray new]; - - for (UNNotification *notification in notifications) { - [formattedNotifications addObject:RCTFormatUNNotification(notification)]; - } - callback(@[ formattedNotifications ]); - }]; -#else - callback(@[ @[] ]); -#endif -} - -- (void)getAuthorizationStatus:(RCTResponseSenderBlock)callback -{ - UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; - [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) { - callback(@[ @(settings.authorizationStatus) ]); - }]; -} - -- (std::shared_ptr)getTurboModule: - (const facebook::react::ObjCTurboModule::InitParams &)params -{ - return std::make_shared(params); -} - -@end - -Class RCTPushNotificationManagerCls(void) -{ - return RCTPushNotificationManager.class; -} diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h deleted file mode 100644 index d25e019c14b3..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal plugin build system - */ - -#ifdef RN_DISABLE_OSS_PLUGIN_HEADER - -// FB Internal: FBRCTPushNotificationPlugins.h is autogenerated by the build system. -#import - -#else - -// OSS-compatibility layer - -#import - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage" - -#ifdef __cplusplus -extern "C" { -#endif - -// RCTTurboModuleManagerDelegate should call this to resolve module classes. -Class RCTPushNotificationClassProvider(const char *name); - -// Lookup functions -Class RCTPushNotificationManagerCls(void) __attribute__((used)); - -#ifdef __cplusplus -} -#endif - -#pragma GCC diagnostic pop - -#endif // RN_DISABLE_OSS_PLUGIN_HEADER diff --git a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm b/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm deleted file mode 100644 index 650b17d01b87..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/RCTPushNotificationPlugins.mm +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @generated by an internal plugin build system - */ - -#ifndef RN_DISABLE_OSS_PLUGIN_HEADER - -// OSS-compatibility layer - -#import "RCTPushNotificationPlugins.h" - -#import - -using namespace std::literals; - -Class RCTPushNotificationClassProvider(const char *name) -{ - - if (name == "PushNotificationManager"sv) { - return RCTPushNotificationManagerCls(); - } - - return nil; -} - -#endif // RN_DISABLE_OSS_PLUGIN_HEADER diff --git a/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec b/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec deleted file mode 100644 index 8c1879129d3a..000000000000 --- a/packages/react-native/Libraries/PushNotificationIOS/React-RCTPushNotification.podspec +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -require "json" - -package = JSON.parse(File.read(File.join(__dir__, "..", "..", "package.json"))) -version = package['version'] - -source = { :git => 'https://github.com/facebook/react-native.git' } -if version == '1000.0.0' - # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. - source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") -else - source[:tag] = "v#{version}" -end - -header_search_paths = [ - "\"${PODS_ROOT}/Headers/Public/ReactCodegen/react/renderer/components\"", -] - -Pod::Spec.new do |s| - s.name = "React-RCTPushNotification" - s.version = version - s.summary = "A library for handling push notifications for your app, including permission handling and icon badge number." - s.homepage = "https://reactnative.dev/" - s.documentation_url = "https://reactnative.dev/docs/pushnotificationios" - s.license = package["license"] - s.author = "Meta Platforms, Inc. and its affiliates" - s.platforms = min_supported_versions - s.compiler_flags = '-Wno-nullability-completeness' - s.source = source - s.source_files = "*.{m,mm}" - s.preserve_paths = "package.json", "LICENSE", "LICENSE-docs" - s.header_dir = "RCTPushNotification" - s.pod_target_xcconfig = { - "USE_HEADERMAP" => "YES", - "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(), - "HEADER_SEARCH_PATHS" => header_search_paths.join(' ') - } - s.framework = ["UIKit", "UserNotifications"] - - s.dependency "RCTTypeSafety" - s.dependency "React-Core/RCTPushNotificationHeaders" - s.dependency "React-jsi" - - add_dependency(s, "React-RCTFBReactNativeSpec") - add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"]) - add_dependency(s, "React-NativeModulesApple") - - add_rn_third_party_dependencies(s) - add_rncore_dependency(s) - - mark_as_react_native_build(s) -end diff --git a/packages/react-native/React-Core.podspec b/packages/react-native/React-Core.podspec index 4e5802e7035d..8cebf96d331b 100644 --- a/packages/react-native/React-Core.podspec +++ b/packages/react-native/React-Core.podspec @@ -24,7 +24,6 @@ header_subspecs = { 'RCTImageHeaders' => 'Libraries/Image/*.h', 'RCTLinkingHeaders' => 'Libraries/LinkingIOS/*.h', 'RCTNetworkHeaders' => 'Libraries/Network/*.h', - 'RCTPushNotificationHeaders' => 'Libraries/PushNotificationIOS/*.h', 'RCTSettingsHeaders' => 'Libraries/Settings/*.h', 'RCTTextHeaders' => 'Libraries/Text/**/*.h', 'RCTVibrationHeaders' => 'Libraries/Vibration/*.h', diff --git a/packages/react-native/React/Base/RCTBridge.mm b/packages/react-native/React/Base/RCTBridge.mm index b2258a62c0b9..36f82f119a27 100644 --- a/packages/react-native/React/Base/RCTBridge.mm +++ b/packages/react-native/React/Base/RCTBridge.mm @@ -98,7 +98,6 @@ @"RCTFileRequestHandler", @"RCTHTTPRequestHandler", @"RCTNetworking", - @"RCTPushNotificationManager", @"RCTSettingsManager", @"RCTBaseTextViewManager", @"RCTBaseTextInputViewManager", diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index cb67856cb4b3..2d10560f77dc 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2ceaa8e472a53fc667994edb63ccd995>> + * @generated SignedSource<> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -1767,7 +1767,6 @@ declare function configureNext( onAnimationDidEnd?: OnAnimationDidEndCallback, onAnimationDidFail?: OnAnimationDidFailCallback, ): void -declare type ContentAvailable = 1 | null | void declare type Context = { readonly cellKey: string | undefined readonly getCellVisibilityByKey?: (cellKey: string) => boolean | undefined @@ -2131,11 +2130,6 @@ declare type Extras = { [key: string]: ExtraValue } declare type ExtraValue = boolean | number | string -declare type FetchResult = { - NewData: "UIBackgroundFetchResultNewData" - NoData: "UIBackgroundFetchResultNoData" - ResultFailed: "UIBackgroundFetchResultFailed" -} declare class FillRateHelper_default { activate(): void static addListener(callback: ($$PARAM_0$$: FillRateInfo) => void): { @@ -3574,17 +3568,6 @@ declare type PointValue = { x: number y: number } -declare type PresentLocalNotificationDetails = { - alertAction?: string - alertBody: string - alertTitle?: string - applicationIconBadgeNumber?: number - category?: string - fireDate?: number - isSilent?: boolean - soundName?: string - userInfo?: Object -} declare class Pressability_default { configure(config: PressabilityConfig): void constructor(config: PressabilityConfig) @@ -3706,78 +3689,6 @@ declare type PublicRootInstance = symbol & { __PublicRootInstance__: string } declare type PublicTextInstance = ReturnType -declare interface PushNotification { - finish(result: string): void - getAlert(): (Object | undefined) | (string | undefined) - getBadgeCount(): number | undefined - getCategory(): string | undefined - getContentAvailable(): ContentAvailable - getData(): Object | undefined - getMessage(): (Object | undefined) | (string | undefined) - getSound(): string | undefined - getThreadID(): string | undefined -} -declare type PushNotificationEventName = keyof { - localNotification: string - notification: string - register: string - registrationError: string -} -declare class PushNotificationIOS { - static FetchResult: FetchResult - static abandonPermissions(): void - static addEventListener( - type: PushNotificationEventName, - handler: Function, - ): void - static cancelAllLocalNotifications(): void - static cancelLocalNotifications(userInfo: Object): void - static checkPermissions( - callback: (permissions: PushNotificationPermissions) => void, - ): void - constructor(nativeNotif: Object) - finish(fetchResult: string): void - getAlert(): (null | Object | undefined) | (null | string | undefined) - static getApplicationIconBadgeNumber(callback: Function): void - static getAuthorizationStatus( - callback: (authorizationStatus: number) => void, - ): void - getBadgeCount(): null | number | undefined - getCategory(): null | string | undefined - getContentAvailable(): ContentAvailable - getData(): null | Object | undefined - static getDeliveredNotifications( - callback: (notifications: Array) => void, - ): void - static getInitialNotification(): Promise - getMessage(): (null | Object | undefined) | (null | string | undefined) - static getScheduledLocalNotifications(callback: Function): void - getSound(): null | string | undefined - getThreadID(): null | string | undefined - static presentLocalNotification( - details: PresentLocalNotificationDetails, - ): void - static removeAllDeliveredNotifications(): void - static removeDeliveredNotifications(identifiers: Array): void - static removeEventListener(type: PushNotificationEventName): void - static requestPermissions( - permissions?: PushNotificationPermissions, - ): Promise<{ - alert: boolean - badge: boolean - sound: boolean - }> - static scheduleLocalNotification( - details: ScheduleLocalNotificationDetails, - ): void - static setApplicationIconBadgeNumber(number: number): void -} -declare type PushNotificationPermissions = { - [key: string]: boolean | number - alert: boolean - badge: boolean - sound: boolean -} declare type RadialExtent = "closest-corner" | "closest-side" | "farthest-corner" | "farthest-side" declare type RadialGradientPosition = @@ -4249,10 +4160,6 @@ declare type SafeAreaInsetsChangeEvent = NativeSyntheticEvent<{ declare type SafeAreaView = typeof SafeAreaView declare type SafeAreaViewInstance = HostInstance declare type ScaledSize = DisplayMetrics -declare type ScheduleLocalNotificationDetails = - PresentLocalNotificationDetails & { - repeatInterval?: "day" | "hour" | "minute" | "month" | "week" | "year" - } declare type ScrollEvent = NativeSyntheticEvent declare type ScrollResponderType = ScrollViewImperativeMethods declare type ScrollToLocationParamsType = { @@ -5949,9 +5856,6 @@ export { ProgressBarAndroidProps, // 7205b2a5 PublicRootInstance, // 8040afd7 PublicTextInstance, // f9adf69a - PushNotificationEventName, // 84e7e150 - PushNotificationIOS, // b4d1fe78 - PushNotificationPermissions, // c2e7ae4f Rationale, // 5df1b1c1 ReactNativeVersion, // abd76827 RefreshControl, // db24bb7e diff --git a/packages/react-native/__typetests__/index.tsx b/packages/react-native/__typetests__/index.tsx index 54ea8b7694ba..69726b692f63 100644 --- a/packages/react-native/__typetests__/index.tsx +++ b/packages/react-native/__typetests__/index.tsx @@ -76,7 +76,6 @@ import { PlatformColor, Pressable, ProgressBarAndroid, - PushNotificationIOS, RefreshControl, // @ts-ignore RegisteredStyle, @@ -2001,30 +2000,6 @@ const ProgressBarAndroidTest = () => { />; }; -// Push notification -const PushNotificationTest = () => { - PushNotificationIOS.presentLocalNotification({ - alertBody: 'notificatus', - userInfo: 'informius', - alertTitle: 'Titulus', - alertAction: 'view', - }); - - PushNotificationIOS.scheduleLocalNotification({ - alertAction: 'view', - alertBody: 'Look at me!', - alertTitle: 'Hello!', - applicationIconBadgeNumber: 999, - category: 'engagement', - fireDate: +new Date(), - isSilent: false, - repeatInterval: 'minute', - userInfo: { - abc: 123, - }, - }); -}; - // Appearance const DarkMode = () => { const color = useColorScheme(); diff --git a/packages/react-native/index.js b/packages/react-native/index.js index 79b601abb36d..6fb4fbb3af3f 100644 --- a/packages/react-native/index.js +++ b/packages/react-native/index.js @@ -322,16 +322,6 @@ module.exports = { return require('./Libraries/StyleSheet/PlatformColorValueTypes') .PlatformColor; }, - get PushNotificationIOS() { - warnOnce( - 'pushNotificationIOS-moved', - 'PushNotificationIOS has been extracted from react-native core and will be removed in a future release. ' + - "It can now be installed and imported from '@react-native-community/push-notification-ios' instead of 'react-native'. " + - 'See https://github.com/react-native-push-notification/ios', - ); - return require('./Libraries/PushNotificationIOS/PushNotificationIOS') - .default; - }, get processColor() { return require('./Libraries/StyleSheet/processColor').default; }, @@ -443,4 +433,20 @@ if (__DEV__) { ); }, }); + + /* $FlowFixMe[prop-missing] This is intentional: Flow will error when + * attempting to access PushNotificationIOS. */ + /* $FlowFixMe[invalid-export] This is intentional: Flow will error when + * attempting to access PushNotificationIOS. */ + Object.defineProperty(module.exports, 'PushNotificationIOS', { + configurable: true, + get() { + invariant( + false, + 'PushNotificationIOS has been removed from react-native core. ' + + "Please use '@react-native-community/push-notification-ios' instead. " + + 'See https://github.com/react-native-push-notification/ios', + ); + }, + }); } diff --git a/packages/react-native/index.js.flow b/packages/react-native/index.js.flow index 3d015144404b..f6066abd5c80 100644 --- a/packages/react-native/index.js.flow +++ b/packages/react-native/index.js.flow @@ -387,12 +387,6 @@ export {default as Platform} from './Libraries/Utilities/Platform'; export {PlatformColor} from './Libraries/StyleSheet/PlatformColorValueTypes'; -export type { - PushNotificationEventName, - PushNotificationPermissions, -} from './Libraries/PushNotificationIOS/PushNotificationIOS'; -export {default as PushNotificationIOS} from './Libraries/PushNotificationIOS/PushNotificationIOS'; - export type {ProcessedColorValue} from './Libraries/StyleSheet/processColor'; export {default as processColor} from './Libraries/StyleSheet/processColor'; diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 119ce41c24b0..779b0e3d84d1 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -785,7 +785,6 @@ def self.react_native_pods "React-RCTImage", "React-RCTLinking", "React-RCTNetwork", - "React-RCTPushNotification", "React-RCTSettings", "React-RCTText", "React-RCTTest", diff --git a/packages/react-native/scripts/ios-prebuild/headers-config.js b/packages/react-native/scripts/ios-prebuild/headers-config.js index 61addbc7a4c4..12c06fef68d5 100644 --- a/packages/react-native/scripts/ios-prebuild/headers-config.js +++ b/packages/react-native/scripts/ios-prebuild/headers-config.js @@ -609,10 +609,6 @@ const PodspecExceptions /*: {[key: string]: PodSpecConfiguration} */ = { headerPatterns: ['Libraries/LinkingIOS/*.h'], }, {name: 'RCTNetworkHeaders', headerPatterns: ['Libraries/Network/*.h']}, - { - name: 'RCTPushNotificationHeaders', - headerPatterns: ['Libraries/PushNotificationIOS/*.h'], - }, { name: 'RCTSettingsHeaders', headerPatterns: ['Libraries/Settings/*.h'], @@ -642,9 +638,6 @@ const PodspecExceptions /*: {[key: string]: PodSpecConfiguration} */ = { }, ], }, - 'Libraries/PushNotificationIOS/React-RCTPushNotification.podspec': { - disabled: true, - }, 'ReactCommon/react/renderer/css/React-renderercss.podspec': { name: 'React-renderercss', headerPatterns: [], diff --git a/packages/react-native/scripts/ios-prebuild/setup.js b/packages/react-native/scripts/ios-prebuild/setup.js index c8d6ef4a5324..594a8b1aec65 100644 --- a/packages/react-native/scripts/ios-prebuild/setup.js +++ b/packages/react-native/scripts/ios-prebuild/setup.js @@ -88,9 +88,6 @@ async function setup( link('Libraries/NativeAnimation', 'React'); link('Libraries/LinkingIOS', 'React'); link('Libraries/Settings', 'React'); - - link('Libraries/PushNotificationIOS', 'React'); - link('Libraries/Settings', 'React'); link('Libraries/Vibration', 'React'); link('ReactCommon/hermes', 'reacthermes'); diff --git a/packages/react-native/src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS.js b/packages/react-native/src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS.js deleted file mode 100644 index c754130d8a55..000000000000 --- a/packages/react-native/src/private/specs_DEPRECATED/modules/NativePushNotificationManagerIOS.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; -import type {UnsafeObject} from '../../../../Libraries/Types/CodegenTypes'; - -import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; - -type Permissions = { - alert: boolean, - badge: boolean, - sound: boolean, -}; - -type Notification = { - readonly alertTitle?: ?string, - readonly alertBody?: ?string, - readonly userInfo?: ?UnsafeObject, - /** - * Identifier for the notification category. See the [Apple documentation](https://developer.apple.com/documentation/usernotifications/declaring_your_actionable_notification_types) - * for more details. - */ - readonly category?: ?string, - /** - * Actual type: string | number - * - * Schedule notifications using EITHER `fireDate` or `fireIntervalSeconds`. - * If both are specified, `fireDate` takes precedence. - * If you use `presentLocalNotification`, both will be ignored - * and the notification will be shown immediately. - */ - readonly fireDate?: ?number, - /** - * Seconds from now to display the notification. - * - * Schedule notifications using EITHER `fireDate` or `fireIntervalSeconds`. - * If both are specified, `fireDate` takes precedence. - * If you use `presentLocalNotification`, both will be ignored - * and the notification will be shown immediately. - */ - readonly fireIntervalSeconds?: ?number, - /** Badge count to display on the app icon. */ - readonly applicationIconBadgeNumber?: ?number, - /** Whether to silence the notification sound. */ - readonly isSilent?: ?boolean, - /** - * Custom notification sound. Can only be set when creating notifications. - * This will be null for notifications retrieved via - * getScheduledLocalNotifications or getDeliveredNotifications. - */ - readonly soundName?: ?string, -}; - -export interface Spec extends TurboModule { - readonly getConstants: () => {}; - readonly onFinishRemoteNotification: ( - notificationId: string, - /** - * Type: - * 'UIBackgroundFetchResultNewData' | - * 'UIBackgroundFetchResultNoData' | - * 'UIBackgroundFetchResultFailed' - */ - fetchResult: string, - ) => void; - readonly setApplicationIconBadgeNumber: (num: number) => void; - readonly getApplicationIconBadgeNumber: ( - callback: (num: number) => void, - ) => void; - readonly requestPermissions: (permission: { - readonly alert: boolean, - readonly badge: boolean, - readonly sound: boolean, - }) => Promise; - readonly abandonPermissions: () => void; - readonly checkPermissions: ( - callback: (permissions: Permissions) => void, - ) => void; - readonly presentLocalNotification: (notification: Notification) => void; - readonly scheduleLocalNotification: (notification: Notification) => void; - readonly cancelAllLocalNotifications: () => void; - readonly cancelLocalNotifications: (userInfo: UnsafeObject) => void; - readonly getInitialNotification: () => Promise; - readonly getScheduledLocalNotifications: ( - callback: (notification: Notification) => void, - ) => void; - readonly removeAllDeliveredNotifications: () => void; - readonly removeDeliveredNotifications: (identifiers: Array) => void; - readonly getDeliveredNotifications: ( - callback: (notification: Array) => void, - ) => void; - readonly getAuthorizationStatus: ( - callback: (authorizationStatus: number) => void, - ) => void; - readonly addListener: (eventType: string) => void; - readonly removeListeners: (count: number) => void; -} - -export default TurboModuleRegistry.get( - 'PushNotificationManager', -) as ?Spec; diff --git a/packages/react-native/types_DEPRECATED/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts b/packages/react-native/types_DEPRECATED/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts deleted file mode 100644 index f68bd1ff85b1..000000000000 --- a/packages/react-native/types_DEPRECATED/Libraries/PushNotificationIOS/PushNotificationIOS.d.ts +++ /dev/null @@ -1,286 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -export interface PushNotificationPermissions { - alert?: boolean | undefined; - badge?: boolean | undefined; - sound?: boolean | undefined; -} - -export interface PushNotification { - /** - * An alias for `getAlert` to get the notification's main message string - */ - getMessage(): string | Object; - - /** - * Gets the sound string from the `aps` object - */ - getSound(): string; - - /** - * Gets the category string from the `aps` object - */ - getCategory(): string; - - /** - * Gets the notification's main message from the `aps` object - */ - getAlert(): string | Object; - - /** - * Gets the content-available number from the `aps` object - */ - getContentAvailable(): number; - - /** - * Gets the badge count number from the `aps` object - */ - getBadgeCount(): number; - - /** - * Gets the data object on the notif - */ - getData(): Object; - - /** - * Gets the thread ID on the notif - */ - getThreadId(): string; - - /** - * iOS Only - * Signifies remote notification handling is complete - */ - finish(result: string): void; -} - -type PresentLocalNotificationDetails = { - alertBody: string; - alertAction: string; - alertTitle?: string | undefined; - soundName?: string | undefined; - category?: string | undefined; - userInfo?: Object | undefined; - applicationIconBadgeNumber?: number | undefined; -}; - -type ScheduleLocalNotificationDetails = { - alertAction?: string | undefined; - alertBody?: string | undefined; - alertTitle?: string | undefined; - applicationIconBadgeNumber?: number | undefined; - category?: string | undefined; - fireDate?: number | string | undefined; - isSilent?: boolean | undefined; - repeatInterval?: - 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | undefined; - soundName?: string | undefined; - userInfo?: Object | undefined; -}; - -export type PushNotificationEventName = - 'notification' | 'localNotification' | 'register' | 'registrationError'; - -type FetchResult = { - NewData: 'UIBackgroundFetchResultNewData'; - NoData: 'UIBackgroundFetchResultNoData'; - ResultFailed: 'UIBackgroundFetchResultFailed'; -}; - -/** - * Handle push notifications for your app, including permission handling and icon badge number. - * @see https://reactnative.dev/docs/pushnotificationios#content - * - * //FIXME: BGR: The documentation seems completely off compared to the actual js implementation. I could never get the example to run - */ -export interface PushNotificationIOSStatic { - /** - * Schedules the localNotification for immediate presentation. - * details is an object containing: - * alertBody : The message displayed in the notification alert. - * alertAction : The "action" displayed beneath an actionable notification. Defaults to "view"; - * soundName : The sound played when the notification is fired (optional). - * category : The category of this notification, required for actionable notifications (optional). - * userInfo : An optional object containing additional notification data. - * applicationIconBadgeNumber (optional) : The number to display as the app's icon badge. The default value of this property is 0, which means that no badge is displayed. - */ - presentLocalNotification(details: PresentLocalNotificationDetails): void; - - /** - * Schedules the localNotification for future presentation. - * details is an object containing: - * fireDate : The date and time when the system should deliver the notification. - * alertBody : The message displayed in the notification alert. - * alertAction : The "action" displayed beneath an actionable notification. Defaults to "view"; - * soundName : The sound played when the notification is fired (optional). - * category : The category of this notification, required for actionable notifications (optional). - * userInfo : An optional object containing additional notification data. - * applicationIconBadgeNumber (optional) : The number to display as the app's icon badge. Setting the number to 0 removes the icon badge. - */ - scheduleLocalNotification(details: ScheduleLocalNotificationDetails): void; - - /** - * Cancels all scheduled localNotifications - */ - cancelAllLocalNotifications(): void; - - /** - * Remove all delivered notifications from Notification Center. - */ - removeAllDeliveredNotifications(): void; - - /** - * Provides you with a list of the app’s notifications that are still displayed in Notification Center. - */ - getDeliveredNotifications(callback: (notifications: Object[]) => void): void; - - /** - * Removes the specified notifications from Notification Center - */ - removeDeliveredNotifications(identifiers: string[]): void; - - /** - * Cancel local notifications. - * Optionally restricts the set of canceled notifications to those notifications whose userInfo fields match the corresponding fields in the userInfo argument. - */ - cancelLocalNotifications(userInfo: Object): void; - - /** - * Sets the badge number for the app icon on the home screen - */ - setApplicationIconBadgeNumber(number: number): void; - - /** - * Gets the current badge number for the app icon on the home screen - */ - getApplicationIconBadgeNumber(callback: (badge: number) => void): void; - - /** - * Gets the local notifications that are currently scheduled. - */ - getScheduledLocalNotifications( - callback: (notifications: ScheduleLocalNotificationDetails[]) => void, - ): void; - - /** - * Attaches a listener to remote notifications while the app is running in the - * foreground or the background. - * - * The handler will get be invoked with an instance of `PushNotificationIOS` - * - * The type MUST be 'notification' - */ - addEventListener( - type: 'notification' | 'localNotification', - handler: (notification: PushNotification) => void, - ): void; - - /** - * Fired when the user registers for remote notifications. - * - * The handler will be invoked with a hex string representing the deviceToken. - * - * The type MUST be 'register' - */ - addEventListener( - type: 'register', - handler: (deviceToken: string) => void, - ): void; - - /** - * Fired when the user fails to register for remote notifications. - * Typically occurs when APNS is having issues, or the device is a simulator. - * - * The handler will be invoked with {message: string, code: number, details: any}. - * - * The type MUST be 'registrationError' - */ - addEventListener( - type: 'registrationError', - handler: (error: {message: string; code: number; details: any}) => void, - ): void; - - /** - * Removes the event listener. Do this in `componentWillUnmount` to prevent - * memory leaks - */ - removeEventListener( - type: PushNotificationEventName, - handler: - | ((notification: PushNotification) => void) - | ((deviceToken: string) => void) - | ((error: {message: string; code: number; details: any}) => void), - ): void; - - /** - * Requests all notification permissions from iOS, prompting the user's - * dialog box. - */ - requestPermissions(permissions?: PushNotificationPermissions[]): void; - - /** - * Requests all notification permissions from iOS, prompting the user's - * dialog box. - */ - requestPermissions( - permissions?: PushNotificationPermissions, - ): Promise; - - /** - * Unregister for all remote notifications received via Apple Push - * Notification service. - * You should call this method in rare circumstances only, such as when - * a new version of the app removes support for all types of remote - * notifications. Users can temporarily prevent apps from receiving - * remote notifications through the Notifications section of the - * Settings app. Apps unregistered through this method can always - * re-register. - */ - abandonPermissions(): void; - - /** - * See what push permissions are currently enabled. `callback` will be - * invoked with a `permissions` object: - * - * - `alert` :boolean - * - `badge` :boolean - * - `sound` :boolean - */ - checkPermissions( - callback: (permissions: PushNotificationPermissions) => void, - ): void; - - /** - * This method returns a promise that resolves to either the notification - * object if the app was launched by a push notification, or `null` otherwise. - */ - getInitialNotification(): Promise; - - /** - * iOS fetch results that best describe the result of a finished remote notification handler. - * For a list of possible values, see `PushNotificationIOS.FetchResult`. - */ - FetchResult: FetchResult; -} - -/** - * PushNotificationIOS has been extracted from react-native core and will be removed in a future release. - * It can now be installed and imported from `@react-native-community/push-notification-ios` instead of 'react-native'. - * @see https://github.com/react-native-community/react-native-push-notification-ios - * @deprecated - */ -export const PushNotificationIOS: PushNotificationIOSStatic; -/** - * PushNotificationIOS has been extracted from react-native core and will be removed in a future release. - * It can now be installed and imported from `@react-native-community/push-notification-ios` instead of 'react-native'. - * @see https://github.com/react-native-community/react-native-push-notification-ios - * @deprecated - */ -export type PushNotificationIOS = PushNotificationIOSStatic; diff --git a/packages/react-native/types_DEPRECATED/index.d.ts b/packages/react-native/types_DEPRECATED/index.d.ts index b5541260cb62..6a48245bc000 100644 --- a/packages/react-native/types_DEPRECATED/index.d.ts +++ b/packages/react-native/types_DEPRECATED/index.d.ts @@ -123,7 +123,6 @@ export * from './Libraries/LogBox/LogBox'; export * from './Libraries/Modal/Modal'; export * as Systrace from './Libraries/Performance/Systrace'; export * from './Libraries/PermissionsAndroid/PermissionsAndroid'; -export * from './Libraries/PushNotificationIOS/PushNotificationIOS'; export * from './Libraries/ReactNative/AppRegistry'; export * from './Libraries/ReactNative/I18nManager'; export * from './Libraries/ReactNative/RendererProxy'; diff --git a/packages/rn-tester/Podfile b/packages/rn-tester/Podfile index 24b30cffa59d..0e0faf69feb9 100644 --- a/packages/rn-tester/Podfile +++ b/packages/rn-tester/Podfile @@ -44,8 +44,6 @@ def pods(target_name, options = {}) ) pod 'ReactCommon-Samples', :path => "#{@prefix_path}/ReactCommon/react/nativemodule/samples" - # Additional Pods which aren't included in the default Podfile - pod 'React-RCTPushNotification', :path => "#{@prefix_path}/Libraries/PushNotificationIOS" # Additional Pods which are classed as unstable # RNTester native modules and components diff --git a/packages/rn-tester/Podfile.lock b/packages/rn-tester/Podfile.lock index e05fb962dc81..a0db4f5e3298 100644 --- a/packages/rn-tester/Podfile.lock +++ b/packages/rn-tester/Podfile.lock @@ -369,31 +369,6 @@ PODS: - React-utils - SocketRocket - Yoga - - React-Core/RCTPushNotificationHeaders (1000.0.0): - - boost - - DoubleConversion - - fast_float - - fmt - - glog - - hermes-engine - - RCT-Folly - - RCT-Folly/Fabric - - RCTDeprecation - - React-Core/Default - - React-cxxreact - - React-featureflags - - React-hermes - - React-jsi - - React-jsiexecutor - - React-jsinspector - - React-jsinspectorcdp - - React-jsitooling - - React-perflogger - - React-runtimeexecutor - - React-runtimescheduler - - React-utils - - SocketRocket - - Yoga - React-Core/RCTSettingsHeaders (1000.0.0): - boost - DoubleConversion @@ -2310,13 +2285,6 @@ PODS: - React-RCTFBReactNativeSpec - ReactCommon - SocketRocket - - React-RCTPushNotification (1000.0.0): - - RCTTypeSafety - - React-Core/RCTPushNotificationHeaders - - React-jsi - - React-NativeModulesApple - - React-RCTFBReactNativeSpec - - ReactCommon - React-RCTRuntime (1000.0.0): - boost - DoubleConversion @@ -2772,7 +2740,6 @@ DEPENDENCIES: - React-RCTImage (from `../react-native/Libraries/Image`) - React-RCTLinking (from `../react-native/Libraries/LinkingIOS`) - React-RCTNetwork (from `../react-native/Libraries/Network`) - - React-RCTPushNotification (from `../react-native/Libraries/PushNotificationIOS`) - React-RCTRuntime (from `../react-native/React/Runtime`) - React-RCTSettings (from `../react-native/Libraries/Settings`) - React-RCTTest (from `./RCTTest`) @@ -2934,8 +2901,6 @@ EXTERNAL SOURCES: :path: "../react-native/Libraries/LinkingIOS" React-RCTNetwork: :path: "../react-native/Libraries/Network" - React-RCTPushNotification: - :path: "../react-native/Libraries/PushNotificationIOS" React-RCTRuntime: :path: "../react-native/React/Runtime" React-RCTSettings: @@ -3051,7 +3016,6 @@ SPEC CHECKSUMS: React-RCTImage: bb0eb46db1e24ad906cb31c21e21b514db5b8a55 React-RCTLinking: 6fb1ec3188dbf07f87b29afe172064a46d331446 React-RCTNetwork: f424e280b3f9edd4d6692296c69d3dd5de92f78a - React-RCTPushNotification: 49c1acca24d107235c15a61af9ed856ef9e4c956 React-RCTRuntime: feb1d8054fd1128af1622a6ec477ed5585dd01cc React-RCTSettings: a932ad87f8dc6601deb45220a9bfa7da4a44df03 React-RCTTest: 35876bf3e89cbbb357d52292f0e525996e5ce60c @@ -3078,6 +3042,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: a9afa834491f5b80bc3b10d2d91e8bfb15ab1100 -PODFILE CHECKSUM: abfcf138a255569f3324d5118cecdcbc64bdb8c6 +PODFILE CHECKSUM: db07ab6d8e9f392be23257e43287ba2e56b83787 COCOAPODS: 1.16.2 diff --git a/packages/rn-tester/RNTester/AppDelegate.mm b/packages/rn-tester/RNTester/AppDelegate.mm index 8f885bc96699..3c1fc0f31210 100644 --- a/packages/rn-tester/RNTester/AppDelegate.mm +++ b/packages/rn-tester/RNTester/AppDelegate.mm @@ -7,70 +7,11 @@ #import "AppDelegate.h" -#if !TARGET_OS_TV -#import -#import -#endif - -#if !TARGET_OS_TV -@interface AppDelegate () -@end -#endif - @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { -#if !TARGET_OS_TV - [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self]; -#endif return YES; } -#if !TARGET_OS_TV -// Required for the remoteNotificationsRegistered event. -- (void)application:(__unused UIApplication *)application - didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; -} - -// Required for the remoteNotificationRegistrationError event. -- (void)application:(__unused UIApplication *)application - didFailToRegisterForRemoteNotificationsWithError:(NSError *)error -{ - [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error]; -} - -#pragma mark - UNUserNotificationCenterDelegate - -// Required for the remoteNotificationReceived and localNotificationReceived events -- (void)userNotificationCenter:(UNUserNotificationCenter *)center - willPresentNotification:(UNNotification *)notification - withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler -{ - [RCTPushNotificationManager didReceiveNotification:notification]; - completionHandler(UNNotificationPresentationOptionNone); -} - -// Required for the remoteNotificationReceived and localNotificationReceived events -// Called when a notification is tapped from background. (Foreground notification will not be shown per -// the presentation option selected above). -- (void)userNotificationCenter:(UNUserNotificationCenter *)center - didReceiveNotificationResponse:(UNNotificationResponse *)response - withCompletionHandler:(void (^)(void))completionHandler -{ - UNNotification *notification = response.notification; - - // This condition will be true if tapping the notification launched the app. - if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) { - // This can be retrieved with getInitialNotification. - [RCTPushNotificationManager setInitialNotification:notification]; - } - - [RCTPushNotificationManager didReceiveNotification:notification]; - completionHandler(); -} -#endif - @end diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 76c55b4f55e5..266149155eab 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -151,7 +151,6 @@ E7DB210E22B2BD53005AC45F /* libReact-RCTImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTImage.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E7DB211022B2BD53005AC45F /* libReact-RCTLinking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTLinking.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E7DB211222B2BD53005AC45F /* libReact-RCTNetwork.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTNetwork.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - E7DB211422B2BD53005AC45F /* libReact-RCTPushNotification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTPushNotification.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E7DB211622B2BD53005AC45F /* libReact-RCTSettings.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTSettings.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E7DB211822B2BD53005AC45F /* libReact-RCTText.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTText.a"; sourceTree = BUILT_PRODUCTS_DIR; }; E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = "libReact-RCTVibration.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -257,7 +256,6 @@ E7DB210E22B2BD53005AC45F /* libReact-RCTImage.a */, E7DB211022B2BD53005AC45F /* libReact-RCTLinking.a */, E7DB211222B2BD53005AC45F /* libReact-RCTNetwork.a */, - E7DB211422B2BD53005AC45F /* libReact-RCTPushNotification.a */, E7DB211622B2BD53005AC45F /* libReact-RCTSettings.a */, E7DB211822B2BD53005AC45F /* libReact-RCTText.a */, E7DB211A22B2BD53005AC45F /* libReact-RCTVibration.a */, diff --git a/packages/rn-tester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js b/packages/rn-tester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js deleted file mode 100644 index 2c76f238dc93..000000000000 --- a/packages/rn-tester/js/examples/PushNotificationIOS/PushNotificationIOSExample.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - */ - -'use strict'; - -import type {RNTesterModuleExample} from '../../types/RNTesterTypes'; - -import RNTesterText from '../../components/RNTesterText'; -import * as React from 'react'; -import {useCallback, useState} from 'react'; -import {Button, PushNotificationIOS, StyleSheet, View} from 'react-native'; - -// Fires setApplicationIconBadgeNumber many times back-to-back. -const RAPID_FIRE_COUNT = 50; - -function BadgeExample(): React.Node { - const [reported, setReported] = useState(null); - - const updateBadge = useCallback((n: number) => { - PushNotificationIOS.setApplicationIconBadgeNumber(n); - }, []); - - const readBadge = useCallback(() => { - PushNotificationIOS.getApplicationIconBadgeNumber((n: number) => { - setReported(n); - }); - }, []); - - const rapidFire = useCallback(() => { - for (let i = 1; i <= RAPID_FIRE_COUNT; i++) { - PushNotificationIOS.setApplicationIconBadgeNumber(i); - } - }, []); - - return ( - - - {reported == null - ? 'Tap "Read current badge" to query the badge number.' - : `Last read badge number: ${reported}`} - - -