From 3700819b003f787b00eab1035f6371634667e71b Mon Sep 17 00:00:00 2001 From: Jesse Katsumata Date: Mon, 26 Oct 2020 03:33:36 +0900 Subject: [PATCH] Feat/add notification request (#207) --- README.md | 129 +++++++++++++- example/App.js | 80 ++++++++- example/ios/example/AppDelegate.m | 1 - example/ios/example/example.entitlements | 8 + index.d.ts | 168 ++++++++++++++++-- ios/RNCPushNotificationIOS.m | 208 +++++++++++++++++++++-- js/index.js | 105 +++++++++++- js/types.js | 108 ++++++++++++ 8 files changed, 764 insertions(+), 43 deletions(-) create mode 100644 example/ios/example/example.entitlements create mode 100644 js/types.js diff --git a/README.md b/README.md index 95a40e56a..28e646049 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ React Native Push Notification API for iOS. +| Notification | With Action | With TextInput Action | +| ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| | | | + ## Getting started ### Install @@ -116,14 +120,7 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler { [RNCPushNotificationIOS didReceiveNotificationResponse:response]; - completionHandler(); -} -// IOS 4-10 Required for the localNotification event. -- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification -{ - [RNCPushNotificationIOS didReceiveLocalNotification:notification]; } - ``` And then in your AppDelegate implementation, add the following: @@ -184,6 +181,57 @@ export const App = () => { }; ``` +## How to perform different action based on user selected action. + +```js +export const App = () => { + const [permissions, setPermissions] = useState({}); + + /** + * By calling this function, notification with category `userAction` will have action buttons + */ + const setNotificationCategories = () => { + PushNotificationIOS.setNotificationCategories([ + { + id: 'userAction', + actions: [ + {id: 'open', title: 'Open', options: {foreground: true}}, + { + id: 'ignore', + title: 'Desruptive', + options: {foreground: true, destructive: true}, + }, + { + id: 'text', + title: 'Text Input', + options: {foreground: true}, + textInput: {buttonTitle: 'Send'}, + }, + ], + }, + ]); + }; + + useEffect(() => { + PushNotificationIOS.addEventListener('notification', onRemoteNotification); + }); + + const onRemoteNotification = (notification) => { + const actionIdentifier = notification.getActionIdentifier(); + + if (actionIdentifier === 'open') { + // Perform action based on open action + } + + if (actionIdentifier === 'text') { + // Text that of user input. + const userText = notification.getUserText(); + // Perform action based on textinput action + } + }; +}; +``` + # Reference ## Methods @@ -194,6 +242,7 @@ export const App = () => { PushNotificationIOS.presentLocalNotification(details); ``` +_Deprecated_ - use `addNotificationRequest` instead. Schedules the localNotification for immediate presentation. **Parameters:** @@ -221,6 +270,7 @@ details is an object containing: PushNotificationIOS.scheduleLocalNotification(details); ``` +_Deprecated_ - use `addNotificationRequest` instead. Schedules the localNotification for future presentation. **Parameters:** @@ -244,6 +294,71 @@ details is an object containing: --- +### `addNotificationRequest()` + +```jsx +PushNotificationIOS.addNotificationRequest(request); +``` + +Sends notificationRequest to notification center at specified firedate. +Fires immediately if firedate is not set. + +**Parameters:** + +| Name | Type | Required | Description | +| ------- | ------ | -------- | ----------- | +| request | object | Yes | See below. | + +request is an object containing: + +- `id`: Identifier of the notification. Required in order to be able to retrieve specific notification. (required) +- `title`: A short description of the reason for the alert. +- `subtitle`: A secondary description of the reason for the alert. +- `body` : The message displayed in the notification alert. +- `badge` The number to display as the app's icon badge. Setting the number to 0 removes the icon badge. +- `fireDate` : The date and time when the system should deliver the notification. +- `repeats` : Sets notification to repeat daily. Must be used with fireDate. +- `sound` : The sound played when the notification is fired. +- `category` : The category of this notification, required for actionable notifications. +- `isSilent` : If true, the notification will appear without sound. +- `userInfo` : An object containing additional notification data. + +--- + +### `setNotificationCategories()` + +```jsx +PushNotificationIOS.setNotificationCategories(categories); +``` + +Sets category for the notification center. +Allows you to add specific actions for notification with specific category. + +**Parameters:** + +| Name | Type | Required | Description | +| ---------- | -------- | -------- | ----------- | +| categories | object[] | Yes | See below. | + +`category` is an object containing: + +- `id`: Identifier of the notification category. Notification with this category will have the specified actions. (required) +- `actions`: An array of notification actions to be attached to the notification of category id. + +`action` is an object containing: + +- `id`: Identifier of Action. This value will be returned as actionIdentifier when notification is received. +- `title`: Text to be shown on notification action button. +- `options`: Options for notification action. + - `foreground`: If `true`, action will be displayed on notification. + - `destructive`: If `true`, action will be displayed as destructive notification. + - `authenticationRequired`: If `true`, action will only be displayed for authenticated user. +- `textInput`: Option for textInput action. If textInput prop exists, then user action will automatically become a text input action. The text user inputs will be in the userText field of the received notification. + - `buttonTitle`: Text to be shown on button when user finishes text input. Default is "Send" or its equivalent word in user's language setting. + - `placeholder`: Placeholder for text input for text input action. + +--- + ### `remooveAllPendingNotificationRequests()` ```jsx diff --git a/example/App.js b/example/App.js index 28196f922..093823582 100644 --- a/example/App.js +++ b/example/App.js @@ -66,12 +66,12 @@ export const App = () => { DeviceEventEmitter.emit('remoteNotificationReceived', { remote: true, aps: { - alert: 'Sample notification', - badge: '+1', + alert: {title: 'title', subtitle: 'subtitle', body: 'body'}, + badge: 1, sound: 'default', - alertTitle: 'title', category: 'REACT_NATIVE', 'content-available': 1, + 'mutable-content': 1, }, }); }; @@ -101,6 +101,61 @@ export const App = () => { }); }; + const addNotificationRequest = () => { + PushNotificationIOS.addNotificationRequest({ + id: 'test', + title: 'title', + subtitle: 'subtitle', + body: 'body', + category: 'test', + fireDate: new Date(new Date().valueOf() + 2000), + repeats: true, + }); + }; + + const getPendingNotificationRequests = () => { + PushNotificationIOS.getPendingNotificationRequests((requests) => { + Alert.alert('Push Notification Received', JSON.stringify(requests), [ + { + text: 'Dismiss', + onPress: null, + }, + ]); + }); + }; + + const setNotificationCategories = async () => { + PushNotificationIOS.setNotificationCategories([ + { + id: 'test', + actions: [ + {id: 'open', title: 'Open', options: {foreground: true}}, + { + id: 'ignore', + title: 'Desruptive', + options: {foreground: true, destructive: true}, + }, + { + id: 'text', + title: 'Text Input', + options: {foreground: true}, + textInput: {buttonTitle: 'Send'}, + }, + ], + }, + ]); + Alert.alert( + 'setNotificationCategories', + `Set notification category complete`, + [ + { + text: 'Dismiss', + onPress: null, + }, + ], + ); + }; + const removeAllPendingNotificationRequests = () => { PushNotificationIOS.removeAllPendingNotificationRequests(); }; @@ -132,6 +187,7 @@ export const App = () => { const result = ` Title: ${notification.getTitle()};\n + Subtitle: ${notification.getSubtitle()};\n Message: ${notification.getMessage()};\n badge: ${notification.getBadgeCount()};\n sound: ${notification.getSound()};\n @@ -162,7 +218,10 @@ export const App = () => { Alert.alert( 'Local Notification Received', `Alert title: ${notification.getTitle()}, - 'Alert message: ${notification.getMessage()}, + Alert subtitle: ${notification.getSubtitle()}, + Alert message: ${notification.getMessage()}, + Action Id: ${notification.getActionIdentifier()}, + User Text: ${notification.getUserText()}, Notification is clicked: ${String(isClicked)}.`, [ { @@ -191,6 +250,14 @@ export const App = () => { onPress={scheduleLocalNotification} label="Schedule fake local notification" /> +