first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
/**
* 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;

View File

@@ -0,0 +1,295 @@
/**
* 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 apps 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<PushNotificationPermissions>;
/**
* 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<PushNotification | null>;
/**
* 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;

View File

@@ -0,0 +1,673 @@
/**
* 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
* @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,
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<NativePushNotificationIOSEventDefinitions>(
// 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<string, void | EventSubscription>();
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 = $Keys<{
/**
* 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
*/
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(): ContentAvailable;
/**
* 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;
}
/**
* 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 {
_data: Object;
_alert: string | Object;
_sound: string;
_category: string;
_contentAvailable: ContentAvailable;
_badgeCount: number;
_notificationId: string;
_isRemote: boolean;
_remoteNotificationCompleteCallbackCalled: boolean;
_threadID: string;
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 apps notifications that are currently displayed
* in Notification Center.
*
* See https://reactnative.dev/docs/pushnotificationios#getdeliverednotifications
*/
static getDeliveredNotifications(
callback: (notifications: Array<Object>) => 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<string>): 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
*/
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
*/
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
*/
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,
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<?PushNotification> {
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.
*
*/
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.
*/
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
*/
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
*/
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;

View File

@@ -0,0 +1,48 @@
/*
* 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 <React/RCTEventEmitter.h>
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

View File

@@ -0,0 +1,588 @@
/*
* 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 <React/RCTPushNotificationManager.h>
#import <UserNotifications/UserNotifications.h>
#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
#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 () <NativePushNotificationManagerIOSSpec>
@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks;
@end
@implementation RCTConvert (UNNotificationContent)
+ (UNNotificationContent *)UNNotificationContent:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
BOOL isSilent = [RCTConvert BOOL:details[@"isSilent"]];
UNMutableNotificationContent *content = [UNMutableNotificationContent new];
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 (details[@"applicationIconBadgeNumber"]) {
content.badge = [RCTConvert NSNumber:details[@"applicationIconBadgeNumber"]];
}
if (!isSilent) {
NSString *soundName = [RCTConvert NSString:details[@"soundName"]];
content.sound =
soundName ? [UNNotificationSound soundNamed:details[@"soundName"]] : [UNNotificationSound defaultSound];
}
return content;
}
+ (NSDictionary<NSString *, id> *)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<NSString *, id> *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<NSString *, id> *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<NSString *, id> *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];
formattedLocalNotification[@"alertTitle"] = RCTNullIfNil(content.title);
formattedLocalNotification[@"alertBody"] = RCTNullIfNil(content.body);
formattedLocalNotification[@"userInfo"] = RCTNullIfNil(RCTJSONClean(content.userInfo));
formattedLocalNotification[@"category"] = content.categoryIdentifier;
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<NSString *> *)supportedEvents
{
return @[
@"localNotificationReceived",
@"remoteNotificationReceived",
@"remoteNotificationsRegistered",
@"remoteNotificationRegistrationError"
];
}
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSMutableString *hexString = [NSMutableString string];
NSUInteger deviceTokenLength = deviceToken.length;
const unsigned char *bytes = reinterpret_cast<const unsigned char *>(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) {
NSDictionary *userInfo = @{@"notification" : notification.request.content.userInfo};
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
object:self
userInfo:userInfo];
} 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];
}
RCT_EXPORT_METHOD(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
*/
RCT_EXPORT_METHOD(setApplicationIconBadgeNumber : (double)number)
{
RCTSharedApplication().applicationIconBadgeNumber = number;
}
/**
* Get the current application icon badge number on the home screen
*/
RCT_EXPORT_METHOD(getApplicationIconBadgeNumber : (RCTResponseSenderBlock)callback)
{
callback(@[ @(RCTSharedApplication().applicationIconBadgeNumber) ]);
}
RCT_EXPORT_METHOD(
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));
}];
});
}
}];
}
RCT_EXPORT_METHOD(abandonPermissions)
{
[RCTSharedApplication() unregisterForRemoteNotifications];
}
RCT_EXPORT_METHOD(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)
{
return RCTSettingsDictForUNNotificationSettings(
settings.alertSetting == UNNotificationSettingEnabled,
settings.badgeSetting == UNNotificationSettingEnabled,
settings.soundSetting == UNNotificationSettingEnabled,
settings.criticalAlertSetting == UNNotificationSettingEnabled,
settings.lockScreenSetting == UNNotificationSettingEnabled,
settings.notificationCenterSetting == UNNotificationSettingEnabled,
settings.authorizationStatus);
}
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)
};
}
RCT_EXPORT_METHOD(presentLocalNotification : (JS::NativePushNotificationManagerIOS::Notification &)notification)
{
NSDictionary<NSString *, id> *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];
}
RCT_EXPORT_METHOD(scheduleLocalNotification : (JS::NativePushNotificationManagerIOS::Notification &)notification)
{
NSDictionary<NSString *, id> *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];
}
RCT_EXPORT_METHOD(cancelAllLocalNotifications)
{
[[UNUserNotificationCenter currentNotificationCenter]
getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
NSMutableArray<NSString *> *notificationIdentifiersToCancel = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {
[notificationIdentifiersToCancel addObject:request.identifier];
}
[[UNUserNotificationCenter currentNotificationCenter]
removePendingNotificationRequestsWithIdentifiers:notificationIdentifiersToCancel];
}];
}
RCT_EXPORT_METHOD(cancelLocalNotifications : (NSDictionary<NSString *, id> *)userInfo)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *_Nonnull requests) {
NSMutableArray<NSString *> *notificationIdentifiersToCancel = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {
NSDictionary<NSString *, id> *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];
}];
}
RCT_EXPORT_METHOD(
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<NSString *, id> *notificationDict =
RCTFormatUNNotificationContent(kInitialNotification.request.content);
if (IsNotificationRemote(kInitialNotification)) {
// For backwards compatibility, remote notifications only returns a userInfo dict.
NSMutableDictionary<NSString *, id> *userInfoCopy = [notificationDict[@"userInfo"] mutableCopy];
userInfoCopy[@"remote"] = @YES;
resolve(userInfoCopy);
} else {
// For backwards compatibility, local notifications return the notification.
resolve(notificationDict);
}
return;
}
resolve((id)kCFNull);
}
RCT_EXPORT_METHOD(getScheduledLocalNotifications : (RCTResponseSenderBlock)callback)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *_Nonnull requests) {
NSMutableArray<NSDictionary *> *formattedScheduledLocalNotifications = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {
[formattedScheduledLocalNotifications addObject:RCTFormatUNNotificationRequest(request)];
}
callback(@[ formattedScheduledLocalNotifications ]);
}];
}
RCT_EXPORT_METHOD(removeAllDeliveredNotifications)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllDeliveredNotifications];
}
RCT_EXPORT_METHOD(removeDeliveredNotifications : (NSArray<NSString *> *)identifiers)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center removeDeliveredNotificationsWithIdentifiers:identifiers];
}
RCT_EXPORT_METHOD(getDeliveredNotifications : (RCTResponseSenderBlock)callback)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *_Nonnull notifications) {
NSMutableArray<NSDictionary *> *formattedNotifications = [NSMutableArray new];
for (UNNotification *notification in notifications) {
[formattedNotifications addObject:RCTFormatUNNotification(notification)];
}
callback(@[ formattedNotifications ]);
}];
}
RCT_EXPORT_METHOD(getAuthorizationStatus : (RCTResponseSenderBlock)callback)
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) {
callback(@[ @(settings.authorizationStatus) ]);
}];
}
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativePushNotificationManagerIOSSpecJSI>(params);
}
@end
Class RCTPushNotificationManagerCls(void)
{
return RCTPushNotificationManager.class;
}

View File

@@ -0,0 +1,40 @@
/**
* 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 <React/FBRCTPushNotificationPlugins.h>
#else
// OSS-compatibility layer
#import <Foundation/Foundation.h>
#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

View File

@@ -0,0 +1,33 @@
/**
* 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 <string>
#import <unordered_map>
Class RCTPushNotificationClassProvider(const char *name) {
// Intentionally leak to avoid crashing after static destructors are run.
static const auto sCoreModuleClassMap = new const std::unordered_map<std::string, Class (*)(void)>{
{"PushNotificationManager", RCTPushNotificationManagerCls},
};
auto p = sCoreModuleClassMap->find(name);
if (p != sCoreModuleClassMap->end()) {
auto classFunc = p->second;
return classFunc();
}
return nil;
}
#endif // RN_DISABLE_OSS_PLUGIN_HEADER

View File

@@ -0,0 +1,53 @@
# 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 were 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_rncore_dependency(s)
end