diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..105898580 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [Dallas62] +custom: ["https://www.buymeacoffee.com/Dallas62"] diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a267b11e..394d594df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed -## [4.4.0] 2020-07-06 +## [4.0.0] 2020-07-06 ### Breaking changes diff --git a/README.md b/README.md index 0857abf0b..3bc4cade5 100644 --- a/README.md +++ b/README.md @@ -299,7 +299,6 @@ EXAMPLE: ```javascript PushNotification.localNotification({ /* Android Only Properties */ - id: 0, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID ticker: "My Notification Ticker", // (optional) showWhen: true, // (optional) default: true autoCancel: true, // (optional) default: true @@ -330,11 +329,12 @@ PushNotification.localNotification({ /* iOS only properties */ alertAction: "view", // (optional) default: view category: "", // (optional) default: empty string - userInfo: {}, // (optional) default: {} (using null throws a JSON value '' error) /* iOS and Android properties */ + id: 0, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID title: "My Notification Title", // (optional) message: "My Notification Message", // (required) + userInfo: {}, // (optional) default: {} (using null throws a JSON value '' error) playSound: false, // (optional) default: true soundName: "default", // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played) number: 10, // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java index c268cd452..10d5835ef 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotification.java @@ -89,8 +89,6 @@ private Bundle getBundleFromIntent(Intent intent) { public void onNewIntent(Intent intent) { Bundle bundle = this.getBundleFromIntent(intent); if (bundle != null) { - bundle.putBoolean("foreground", false); - intent.putExtra("notification", bundle); mJsDelivery.notifyNotification(bundle); } } diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java index ecd61b03e..22c2622b1 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationHelper.java @@ -422,6 +422,7 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB Intent intent = new Intent(context, intentClass); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + bundle.putBoolean("foreground", this.isApplicationInForeground()); bundle.putBoolean("userInteraction", true); intent.putExtra("notification", bundle); @@ -583,7 +584,7 @@ public void sendToNotificationCentreWithPicture(Bundle bundle, Bitmap largeIconB editor.apply(); } - if (!(this.isApplicationInForeground(context) && bundle.getBoolean("ignoreInForeground"))) { + if (!(this.isApplicationInForeground() && bundle.getBoolean("ignoreInForeground"))) { Notification info = notification.build(); info.defaults |= Notification.DEFAULT_LIGHTS; @@ -938,7 +939,7 @@ private void checkOrCreateChannel(NotificationManager manager, String channel_id } } - public boolean isApplicationInForeground(Context context) { + public boolean isApplicationInForeground() { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List processInfos = activityManager.getRunningAppProcesses(); if (processInfos != null) { diff --git a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java index cb3c6d33f..613e23eee 100644 --- a/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java +++ b/android/src/main/java/com/dieam/reactnativepushnotification/modules/RNPushNotificationPublisher.java @@ -40,7 +40,7 @@ private void handleLocalNotification(Context context, Bundle bundle) { Application applicationContext = (Application) context.getApplicationContext(); RNPushNotificationHelper pushNotificationHelper = new RNPushNotificationHelper(applicationContext); - boolean isForeground = pushNotificationHelper.isApplicationInForeground(applicationContext); + boolean isForeground = pushNotificationHelper.isApplicationInForeground(); Log.v(LOG_TAG, "sendNotification: " + bundle); diff --git a/example/NotifService.js b/example/NotifService.js index 66c32b67e..eb8259704 100644 --- a/example/NotifService.js +++ b/example/NotifService.js @@ -24,7 +24,6 @@ export default class NotifService { this.lastId++; PushNotification.localNotification({ /* Android Only Properties */ - id: this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID ticker: 'My Notification Ticker', // (optional) autoCancel: true, // (optional) default: true largeIcon: 'ic_launcher', // (optional) default: "ic_launcher" @@ -39,15 +38,16 @@ export default class NotifService { ongoing: false, // (optional) set whether this is an "ongoing" notification actions: ['Yes', 'No'], // (Android only) See the doc for notification actions to know more invokeApp: true, // (optional) This enable click on actions to bring back the application to foreground or stay in background, default: true - + /* iOS only properties */ alertAction: 'view', // (optional) default: view category: '', // (optional) default: empty string - userInfo: {}, // (optional) default: {} (using null throws a JSON value '' error) - + /* iOS and Android properties */ + id: this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID title: 'Local Notification', // (optional) message: 'My Notification Message', // (required) + userInfo: { screen: 'home' }, // (optional) default: {} (using null throws a JSON value '' error) playSound: !!soundName, // (optional) default: true soundName: soundName ? soundName : 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played) number: 10, // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) @@ -60,7 +60,6 @@ export default class NotifService { date: new Date(Date.now() + 30 * 1000), // in 30 secs /* Android Only Properties */ - id: this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID ticker: 'My Notification Ticker', // (optional) autoCancel: true, // (optional) default: true largeIcon: 'ic_launcher', // (optional) default: "ic_launcher" @@ -79,11 +78,12 @@ export default class NotifService { /* iOS only properties */ alertAction: 'view', // (optional) default: view category: '', // (optional) default: empty string - userInfo: {}, // (optional) default: {} (using null throws a JSON value '' error) - + /* iOS and Android properties */ + id: this.lastId, // (optional) Valid unique 32 bit integer specified as string. default: Autogenerated Unique ID title: 'Scheduled Notification', // (optional) message: 'My Notification Message', // (required) + userInfo: { sceen: "home" }, // (optional) default: {} (using null throws a JSON value '' error) playSound: !!soundName, // (optional) default: true number: 10, // (optional) Valid 32 bit integer specified as string. default: none (Cannot be zero) soundName: soundName ? soundName : 'default', // (optional) Sound to play when the notification is shown. Value of 'default' plays the default sound. It can be set to a custom sound such as 'android.resource://com.xyz/raw/my_sound'. It will look for the 'my_sound' audio file in 'res/raw' directory and play it. default: 'default' (default sound is played) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 3ebf68810..1ef8335cd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -292,7 +292,7 @@ PODS: - React-cxxreact (= 0.62.2) - React-jsi (= 0.62.2) - ReactCommon/callinvoker (= 0.62.2) - - RNCPushNotificationIOS (1.2.2): + - RNCPushNotificationIOS (1.4.0): - React - Yoga (1.14.0) - YogaKit (1.18.1): @@ -453,10 +453,10 @@ SPEC CHECKSUMS: React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256 ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3 - RNCPushNotificationIOS: 4c97a36dbec42dba411cc35e6dac25e34a805fde + RNCPushNotificationIOS: dc1c0c6aa18a128df123598149f42e848d26a4ac Yoga: 3ebccbdd559724312790e7742142d062476b698e YogaKit: f782866e155069a2cca2517aafea43200b01fd5a PODFILE CHECKSUM: 56c2537f71f3f02200d6918c542a8e89a0b422fa -COCOAPODS: 1.9.1 +COCOAPODS: 1.9.3 diff --git a/example/package.json b/example/package.json index 606b5d146..ca8632cae 100644 --- a/example/package.json +++ b/example/package.json @@ -11,7 +11,7 @@ "pod-install": "cd ios && pod install" }, "dependencies": { - "@react-native-community/push-notification-ios": "^1.2.2", + "@react-native-community/push-notification-ios": "^1.4.0", "react": "16.11.0", "react-native": "0.62.2", "react-native-push-notification": "git+https://git@github.com/zo0r/react-native-push-notification.git" diff --git a/index.js b/index.js index e71db401f..46e1c6fcc 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,7 @@ var Notifications = { onAction: false, onRemoteFetch: false, isLoaded: false, - idInitialNotification: null, + isPopInitialNotification: false, isPermissionsRequestPending: false, @@ -95,27 +95,31 @@ Notifications.configure = function(options) { this.isLoaded = true; } - const handlePopInitialNotification = function(state) { + const handlePopInitialNotification = (state) => { if('active' !== state) { return; } if (options.popInitialNotification === undefined || options.popInitialNotification === true) { this.popInitialNotification(function(firstNotification) { - if ( firstNotification !== null ) { - if(false === firstNotification.userInteraction || this.idInitialNotification === firstNotification.id) { - return; - } - - this.idInitialNotification = firstNotification.id; - this._onNotification(firstNotification, true); + if(this.isPopInitialNotification) { + return; } + + this.isPopInitialNotification = true; + + if (!firstNotification || false === firstNotification.userInteraction) { + return; + } + + this._onNotification(firstNotification, true); }.bind(this)); } } AppState.addEventListener('change', handlePopInitialNotification.bind(this)); - handlePopInitialNotification(); + + handlePopInitialNotification(AppState.currentState); if ( options.requestPermissions !== false ) { this._requestPermissions(); @@ -152,6 +156,12 @@ Notifications.localNotification = function(details) { } } + if (details.userInfo) { + details.userInfo.id = details.userInfo.id || details.id; + } else { + details.userInfo = {id: details.id}; + } + if (Platform.OS === 'ios') { // https://developer.apple.com/reference/uikit/uilocalnotification @@ -161,12 +171,6 @@ Notifications.localNotification = function(details) { soundName = ''; // empty string results in no sound (and no vibration) } - if (details.userInfo) { - details.userInfo.id = details.userInfo.id || details.id; - } else { - details.userInfo = {id: details.id}; - } - // for valid fields see: https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html // alertTitle only valid for apple watch: https://developer.apple.com/library/ios/documentation/iPhone/Reference/UILocalNotification_Class/#//apple_ref/occ/instp/UILocalNotification/alertTitle @@ -224,6 +228,12 @@ Notifications.localNotificationSchedule = function(details) { } } + if (details.userInfo) { + details.userInfo.id = details.userInfo.id || details.id; + } else { + details.userInfo = {id: details.id}; + } + if (Platform.OS === 'ios') { let soundName = details.soundName ? details.soundName : 'default'; // play sound (and vibrate) as default behaviour @@ -231,12 +241,6 @@ Notifications.localNotificationSchedule = function(details) { soundName = ''; // empty string results in no sound (and no vibration) } - if (details.userInfo) { - details.userInfo.id = details.userInfo.id || details.id; - } else { - details.userInfo = {id: details.id}; - } - const iosDetails = { fireDate: details.date.toISOString(), alertTitle: details.title, @@ -326,7 +330,11 @@ Notifications._onAction = function(notification) { this.onAction(notification); } -Notifications._onNotification = function(data, isFromBackground = null) { +Notifications._transformNotificationObject = function(data, isFromBackground = null) { + if(!data) { + return; + } + if ( isFromBackground === null ) { isFromBackground = ( data.foreground === false || @@ -334,37 +342,59 @@ Notifications._onNotification = function(data, isFromBackground = null) { ); } - if ( this.onNotification !== false ) { - if ( Platform.OS === 'ios' ) { - this.onNotification({ - id: data?.userInfo?.id, - foreground: ! isFromBackground, - userInteraction: isFromBackground, - message: data.getMessage(), - data: data.getData(), - badge: data.getBadgeCount(), - alert: data.getAlert(), - sound: data.getSound(), - fireDate: data._fireDate, - finish: (res) => data.finish(res) - }); - } else { - var notificationData = { - foreground: ! isFromBackground, - finish: () => {}, - ...data - }; - - if ( typeof notificationData.data === 'string' ) { - try { - notificationData.data = JSON.parse(notificationData.data); - } catch(e) { - /* void */ - } + let _notification; + + if ( Platform.OS === 'ios' ) { + const notifData = data.getData(); + + _notification = { + id: notifData?.id, + foreground: !isFromBackground, + userInteraction: isFromBackground, + message: data.getMessage(), + data: notifData, + badge: data.getBadgeCount(), + title: data.getTitle(), + soundName: data.getSound(), + fireDate: Date.parse(data._fireDate), + finish: (res) => data.finish(res) + }; + } else { + _notification = { + foreground: ! isFromBackground, + finish: () => {}, + ...data, + }; + + if ( typeof _notification.data === 'string' ) { + try { + _notification.data = JSON.parse(_notification.data); + } catch(e) { + /* void */ } + } + + _notification.data = { + ...(typeof _notification.userInfo === 'object' ? _notification.userInfo : {}), + ...(typeof _notification.data === 'object' ? _notification.data : {}), + }; - this.onNotification(notificationData); + delete _notification.userInfo; + delete _notification.notificationId; + } + + return _notification; +} + +Notifications._onNotification = function(data, initialNotification = false) { + if ( this.onNotification !== false ) { + let notification = data; + + if(!initialNotification) { + notification = this._transformNotificationObject(data); } + + this.onNotification(notification); } }; @@ -434,8 +464,10 @@ Notifications.getApplicationIconBadgeNumber = function() { }; Notifications.popInitialNotification = function(handler) { - this.callNative('getInitialNotification').then(function(result){ - handler(result); + this.callNative('getInitialNotification').then((result) => { + handler( + this._transformNotificationObject(result, true) + ); }); }; @@ -471,7 +503,7 @@ Notifications.getScheduledLocalNotifications = function(callback) { soundName: notif.soundName, repeatInterval: notif.repeatInterval, id: notif.userInfo?.id, - date: new Date(notif.fireDate), + date: new Date(notif.fireDate), number: notif?.applicationIconBadgeNumber, message: notif?.alertBody, title: notif?.alertTitle, diff --git a/package.json b/package.json index 619625482..ad4c56cbd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-push-notification", - "version": "3.5.2", + "version": "4.0.0", "description": "React Native Local and Remote Notifications", "main": "index.js", "scripts": { @@ -24,7 +24,7 @@ "url": "git+ssh://git@github.com:zo0r/react-native-push-notification.git" }, "dependencies": { - "@react-native-community/push-notification-ios": "^1.2.2" + "@react-native-community/push-notification-ios": "^1.4.0" }, "peerDependencies": { "react-native": ">=0.33"