@aws-amplify/rtn-push-notification 1.0.1-push-notification-dryrun.7810

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/AmplifyRTNPushNotification.podspec +36 -0
  2. package/LICENSE +201 -0
  3. package/android/build.gradle +76 -0
  4. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  5. package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
  6. package/android/gradle.properties +23 -0
  7. package/android/gradlew +234 -0
  8. package/android/gradlew.bat +89 -0
  9. package/android/src/main/AndroidManifest.xml +22 -0
  10. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationAWSPinpointUtils.kt +159 -0
  11. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationEventManager.kt +49 -0
  12. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationFirebaseMessagingService.kt +74 -0
  13. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationHeadlessTaskService.kt +28 -0
  14. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationLaunchActivity.kt +27 -0
  15. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationModule.kt +188 -0
  16. package/android/src/main/kotlin/com/amazonaws/amplify/rtnpushnotification/PushNotificationPackage.kt +22 -0
  17. package/android/src/test/kotlin/PushNotificationAWSPinpointUtilsTest.kt +326 -0
  18. package/android/src/test/kotlin/PushNotificationEventManagerTest.kt +45 -0
  19. package/android/src/test/kotlin/PushNotificationFirebaseMessagingServiceTest.kt +92 -0
  20. package/android/src/test/kotlin/PushNotificationLaunchActivityTest.kt +45 -0
  21. package/android/src/test/kotlin/PushNotificationModuleTest.kt +201 -0
  22. package/ios/AmplifyPushNotification.h +17 -0
  23. package/ios/AmplifyPushNotification.m +21 -0
  24. package/ios/AmplifyPushNotificationAppDelegateHelper.swift +31 -0
  25. package/ios/AmplifyRTNEventManager.swift +73 -0
  26. package/ios/AmplifyRTNPushNotification-Bridging-Header.h +7 -0
  27. package/ios/AmplifyRTNPushNotification.m +26 -0
  28. package/ios/AmplifyRTNPushNotification.swift +121 -0
  29. package/ios/AmplifyRTNPushNotification.xcworkspace/contents.xcworkspacedata +28 -0
  30. package/ios/AmplifyRTNPushNotification.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  31. package/ios/AmplifyRTNPushNotificationManager.swift +258 -0
  32. package/lib/.tsbuildinfo +3 -0
  33. package/lib/index.d.ts +3 -0
  34. package/lib/index.js +7 -0
  35. package/lib/index.js.map +1 -0
  36. package/lib/types.d.ts +18 -0
  37. package/lib/types.js +5 -0
  38. package/lib/types.js.map +1 -0
  39. package/lib-esm/.tsbuildinfo +3 -0
  40. package/lib-esm/index.d.ts +3 -0
  41. package/lib-esm/index.js +5 -0
  42. package/lib-esm/index.js.map +1 -0
  43. package/lib-esm/types.d.ts +18 -0
  44. package/lib-esm/types.js +3 -0
  45. package/lib-esm/types.js.map +1 -0
  46. package/package.json +48 -0
  47. package/src/index.ts +10 -0
  48. package/src/types.ts +23 -0
@@ -0,0 +1,258 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import Foundation
5
+ import AmplifyUtilsNotifications
6
+
7
+ private let completionHandlerIdKey = "completionHandlerId"
8
+
9
+ extension UNAuthorizationStatus {
10
+ var description : String {
11
+ switch self {
12
+ case .notDetermined:
13
+ return "NotDetermined"
14
+ case .denied:
15
+ return "Denied"
16
+ case .authorized:
17
+ return "Authorized"
18
+ case .provisional:
19
+ return "Provisional"
20
+ case .ephemeral:
21
+ return "Ephemeral"
22
+ @unknown default:
23
+ return "NotDetermined"
24
+ }
25
+ }
26
+ }
27
+
28
+ class AmplifyRTNPushNotificationManager {
29
+ static let shared = AmplifyRTNPushNotificationManager()
30
+
31
+ private var cachedDeviceToken: String?
32
+ private var launchNotification: [AnyHashable: Any]?
33
+ private var remoteNotificationCompletionHandlers: [String: (UIBackgroundFetchResult) -> Void] = [:]
34
+ private let sharedEventManager: AmplifyRTNEventManager
35
+
36
+ init() {
37
+ sharedEventManager = AmplifyRTNEventManager.shared
38
+ setUpObservers()
39
+ }
40
+
41
+ deinit {
42
+ removeObservers()
43
+ }
44
+
45
+ func handleLaunchOptions(launchOptions: [AnyHashable: Any]) {
46
+ // 1. The host App launch is caused by a notification
47
+ if let remoteNotification = launchOptions[UIApplication.LaunchOptionsKey.remoteNotification] as? [AnyHashable: Any],
48
+ let application = RCTSharedApplication() {
49
+ // 2. The host App is launched from terminated state to the foreground
50
+ // (including transitioning to foregound), i.e. .active .inactive.
51
+ // This happens under one of below conditions:
52
+ // a. Remote notifications are not able to launch the host App (without `content-available: 1`)
53
+ // b. Remote notifications background mode was not enabled on the host App
54
+ // c. The end user disabled background refresh of the host App
55
+ // 3. This notification must be tapped by an end user which is recorded as the launch notification
56
+ if application.applicationState != .background {
57
+ launchNotification = remoteNotification
58
+
59
+ // NOTE: the notification payload will also be passed into didReceiveRemoteNotification below after
60
+ // this delegate method, didFinishLaunchingWithOptions completes.
61
+ // As this notification will already be recorded as the launch notification, it should not be sent as
62
+ // notificationOpened event, this check is handled in didReceiveRemoteNotification.
63
+ }
64
+
65
+ // Otherwise the host App is launched in the background, this notification will be sent to react-native
66
+ // as backgroundMessageReceived event in didReceiveRemoteNotification below.
67
+ // After the host App launched in the background, didFinishLaunchingWithOptions will no longer
68
+ // be fired when an end user taps a notification.
69
+ // After the host App launched in the background, it runs developers' react-native code as well.
70
+ }
71
+ }
72
+
73
+ func requestPermissions(
74
+ _ permissions: [AnyHashable: Any],
75
+ resolve: @escaping RCTPromiseResolveBlock,
76
+ reject: @escaping RCTPromiseRejectBlock
77
+ ) {
78
+ if RCTRunningInAppExtension() {
79
+ reject("ERROR", "requestPermissions can not be called in App Extensions", nil)
80
+ return
81
+ }
82
+
83
+ Task {
84
+ var options: UNAuthorizationOptions = []
85
+
86
+ if permissions["alert"] as? Bool == true {
87
+ options.insert(.alert)
88
+ }
89
+
90
+ if permissions["badge"] as? Bool == true {
91
+ options.insert(.badge)
92
+ }
93
+
94
+ if permissions["sound"] as? Bool == true {
95
+ options.insert(.sound)
96
+ }
97
+
98
+ if permissions["criticalAlert"] as? Bool == true {
99
+ options.insert(.criticalAlert)
100
+ }
101
+
102
+ if permissions["provisional"] as? Bool == true {
103
+ options.insert(.provisional)
104
+ }
105
+
106
+ do {
107
+ let granted = try await AUNotificationPermissions.request(options)
108
+ resolve(granted)
109
+ } catch {
110
+ reject("ERROR", error.localizedDescription, error)
111
+ }
112
+ }
113
+ }
114
+
115
+ func getPermissionStatus(
116
+ _ resolve: @escaping RCTPromiseResolveBlock,
117
+ reject: @escaping RCTPromiseRejectBlock
118
+ ) {
119
+ Task {
120
+ let status = await AmplifyUtilsNotifications.AUNotificationPermissions.status
121
+ resolve(status.description)
122
+ }
123
+ }
124
+
125
+ func getLaunchNotification(
126
+ _ resolve: RCTPromiseResolveBlock,
127
+ reject: RCTPromiseRejectBlock
128
+ ) {
129
+ let launchNotification = self.launchNotification
130
+ self.launchNotification = nil
131
+ resolve(launchNotification == nil ? NSNull() : launchNotification)
132
+ }
133
+
134
+ func setBadgeCount(_ count: Int) {
135
+ DispatchQueue.main.async {
136
+ RCTSharedApplication()?.applicationIconBadgeNumber = count
137
+ }
138
+ }
139
+
140
+ func getBadgeCount(
141
+ _ resolve: @escaping RCTPromiseResolveBlock,
142
+ reject: RCTPromiseRejectBlock
143
+ ) {
144
+ DispatchQueue.main.async {
145
+ resolve(RCTSharedApplication()?.applicationIconBadgeNumber ?? 0)
146
+ }
147
+ }
148
+
149
+ func didRegisterForRemoteNotificationsWithDeviceToken(deviceToken: Data) {
150
+ let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
151
+
152
+ // Reduce frequency of tokenReceived event emitting to RN
153
+ if (cachedDeviceToken != token) {
154
+ cachedDeviceToken = token
155
+ sharedEventManager.sendEventToJS(
156
+ AmplifyRTNEvent(type: NativeEvent.tokenReceived, payload: ["token": cachedDeviceToken])
157
+ )
158
+ }
159
+ }
160
+
161
+ func didFailToRegisterForRemoteNotificationsWithError(error: Error) {
162
+ print("Register for remote notifications failed due to \(error).")
163
+ }
164
+
165
+ func didReceiveRemoteNotification(
166
+ userInfo: [AnyHashable: Any],
167
+ completionHandler: @escaping (UIBackgroundFetchResult) -> Void
168
+ ) {
169
+ if let application = RCTSharedApplication() {
170
+ switch application.applicationState {
171
+ case .background:
172
+ let completionHandlerId = UUID().uuidString
173
+ var userInfoCopy = userInfo
174
+
175
+ remoteNotificationCompletionHandlers[completionHandlerIdKey] = completionHandler
176
+ userInfoCopy[completionHandlerIdKey] = completionHandlerId
177
+
178
+ sharedEventManager.sendEventToJS(
179
+ AmplifyRTNEvent(type: NativeEvent.backgroundMessageReceived, payload: userInfoCopy)
180
+ )
181
+
182
+ // Expecting remoteNotificationCompletionHandlers[completionHandlerIdKey] to be called from JS to complete
183
+ // the background notification
184
+ case .inactive:
185
+ if let launchNotification = launchNotification {
186
+ if NSDictionary(dictionary: launchNotification).isEqual(to: userInfo) {
187
+ // When the last tapped notification is the same as the launch notification,
188
+ // it's sent as launchNotificationOpened event, and retrievable via getLaunchNotification.
189
+ AmplifyRTNEventManager.shared.sendEventToJS(
190
+ AmplifyRTNEvent(type: NativeEvent.launchNotificationOpened, payload: launchNotification)
191
+ )
192
+ } else {
193
+ // When a launch notification is recorded in handleLaunchOptions above,
194
+ // but the last tapped notification is not the recorded launch notification, the last
195
+ // tapped notification will be sent to react-native as notificationOpened event.
196
+ // This may happen when an end user rapidly tapped on multiple notifications.
197
+ self.launchNotification = nil
198
+ sharedEventManager.sendEventToJS(
199
+ AmplifyRTNEvent(type: NativeEvent.notificationOpened, payload: userInfo)
200
+ )
201
+ }
202
+ } else {
203
+ // When there is no launch notification recorded, the last tapped notification
204
+ // will be sent to react-native as notificationOpened event.
205
+ sharedEventManager.sendEventToJS(
206
+ AmplifyRTNEvent(type: NativeEvent.notificationOpened, payload: userInfo)
207
+ )
208
+ }
209
+ completionHandler(.noData)
210
+ case .active:
211
+ sharedEventManager.sendEventToJS(
212
+ AmplifyRTNEvent(type: NativeEvent.foregroundMessageReceived, payload: userInfo)
213
+ )
214
+ completionHandler(.noData)
215
+ @unknown default: break // we don't handle any possible new state added in the future for now
216
+ }
217
+ }
218
+ }
219
+
220
+ func completeNotification(_ completionHandlerId: String) {
221
+ if let completionHandler = remoteNotificationCompletionHandlers[completionHandlerId] {
222
+ completionHandler(.noData)
223
+ remoteNotificationCompletionHandlers.removeValue(forKey: completionHandlerId)
224
+ }
225
+ }
226
+
227
+ private func setUpObservers() {
228
+ NotificationCenter.default.addObserver(
229
+ self,
230
+ selector: #selector(applicationDidBecomeActive),
231
+ name: UIApplication.didBecomeActiveNotification,
232
+ object: nil
233
+ )
234
+ }
235
+
236
+ private func removeObservers() {
237
+ NotificationCenter.default.removeObserver(
238
+ self,
239
+ name: UIApplication.didBecomeActiveNotification,
240
+ object: nil
241
+ )
242
+ }
243
+
244
+ @objc
245
+ private func applicationDidBecomeActive() {
246
+ registerForRemoteNotifications()
247
+ }
248
+
249
+ private func registerForRemoteNotifications() {
250
+ if RCTRunningInAppExtension() {
251
+ return
252
+ }
253
+
254
+ DispatchQueue.main.async {
255
+ RCTSharedApplication()?.registerForRemoteNotifications()
256
+ }
257
+ }
258
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "version": "3.8.3"
3
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { PushNotificationNativeModule } from './types';
2
+ export { PushNotificationNativeModule } from './types';
3
+ export declare const AmplifyRTNPushNotification: PushNotificationNativeModule;
package/lib/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ var react_native_1 = require("react-native");
6
+ exports.AmplifyRTNPushNotification = react_native_1.NativeModules.AmplifyRTNPushNotification;
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC;;AAEtC,6CAA6C;AAI5C,QAAA,0BAA0B,GAE1B,4BAAa,4BAAC"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export interface PushNotificationNativeModule {
2
+ completeNotification?: (completionHandlerId: string) => void;
3
+ getConstants: () => {
4
+ NativeEvent: {
5
+ BACKGROUND_MESSAGE_RECEIVED?: string;
6
+ FOREGROUND_MESSAGE_RECEIVED: string;
7
+ LAUNCH_NOTIFICATION_OPENED: string;
8
+ NOTIFICATION_OPENED: string;
9
+ TOKEN_RECEIVED: string;
10
+ };
11
+ NativeHeadlessTaskKey?: string;
12
+ };
13
+ getLaunchNotification: () => Promise<Record<string, string>>;
14
+ getBadgeCount: () => Promise<number>;
15
+ setBadgeCount: (count: number) => void;
16
+ getPermissionStatus: () => Promise<string>;
17
+ requestPermissions: (permissions: Record<string, boolean>) => Promise<boolean>;
18
+ }
package/lib/types.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,sCAAsC"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "version": "3.8.3"
3
+ }
@@ -0,0 +1,3 @@
1
+ import { PushNotificationNativeModule } from './types';
2
+ export { PushNotificationNativeModule } from './types';
3
+ export declare const AmplifyRTNPushNotification: PushNotificationNativeModule;
@@ -0,0 +1,5 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { NativeModules } from 'react-native';
4
+ export var AmplifyRTNPushNotification = NativeModules.AmplifyRTNPushNotification;
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,CACL,IAAA,qEAA0B,CAEZ"}
@@ -0,0 +1,18 @@
1
+ export interface PushNotificationNativeModule {
2
+ completeNotification?: (completionHandlerId: string) => void;
3
+ getConstants: () => {
4
+ NativeEvent: {
5
+ BACKGROUND_MESSAGE_RECEIVED?: string;
6
+ FOREGROUND_MESSAGE_RECEIVED: string;
7
+ LAUNCH_NOTIFICATION_OPENED: string;
8
+ NOTIFICATION_OPENED: string;
9
+ TOKEN_RECEIVED: string;
10
+ };
11
+ NativeHeadlessTaskKey?: string;
12
+ };
13
+ getLaunchNotification: () => Promise<Record<string, string>>;
14
+ getBadgeCount: () => Promise<number>;
15
+ setBadgeCount: (count: number) => void;
16
+ getPermissionStatus: () => Promise<string>;
17
+ requestPermissions: (permissions: Record<string, boolean>) => Promise<boolean>;
18
+ }
@@ -0,0 +1,3 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,sCAAsC"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@aws-amplify/rtn-push-notification",
3
+ "version": "1.0.1-push-notification-dryrun.7810+1d076358b",
4
+ "description": "React Native module for aws-amplify push notifications",
5
+ "main": "./lib/index.js",
6
+ "module": "./lib-esm/index.js",
7
+ "typings": "./lib-esm/index.d.ts",
8
+ "sideEffects": false,
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "scripts": {
13
+ "test": "tslint 'src/**/*.ts'",
14
+ "test:android": "./android/gradlew test -p ./android",
15
+ "build-with-test": "npm run clean && npm test && tsc && webpack",
16
+ "build:cjs": "node ./build es5 && webpack && webpack --config ./webpack.config.dev.js",
17
+ "build:esm": "node ./build es6",
18
+ "build:cjs:watch": "node ./build es5 --watch",
19
+ "build:esm:watch": "node ./build es6 --watch",
20
+ "build": "npm run clean && npm run build:esm && npm run build:cjs",
21
+ "clean": "rimraf lib-esm lib dist",
22
+ "format": "echo \"Not implemented\"",
23
+ "lint": "tslint 'src/**/*.ts' && npm run ts-coverage",
24
+ "ts-coverage": "typescript-coverage-report -p ./tsconfig.build.json -t 88.21"
25
+ },
26
+ "react-native": {
27
+ "./lib/index": "./lib-esm/index.js"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/aws-amplify/amplify-js.git"
32
+ },
33
+ "author": "Amazon Web Services",
34
+ "license": "Apache-2.0",
35
+ "bugs": {
36
+ "url": "https://github.com/aws/aws-amplify/issues"
37
+ },
38
+ "homepage": "https://docs.amplify.aws/",
39
+ "files": [
40
+ "Amplify*.podspec",
41
+ "android",
42
+ "ios",
43
+ "lib",
44
+ "lib-esm",
45
+ "src"
46
+ ],
47
+ "gitHead": "1d076358bec5e941f1e03b4bae5a9ae0b4dd8c81"
48
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { NativeModules } from 'react-native';
5
+ import { PushNotificationNativeModule } from './types';
6
+ export { PushNotificationNativeModule } from './types';
7
+ export const {
8
+ AmplifyRTNPushNotification,
9
+ }: { AmplifyRTNPushNotification?: PushNotificationNativeModule } =
10
+ NativeModules;
package/src/types.ts ADDED
@@ -0,0 +1,23 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export interface PushNotificationNativeModule {
5
+ completeNotification?: (completionHandlerId: string) => void;
6
+ getConstants: () => {
7
+ NativeEvent: {
8
+ BACKGROUND_MESSAGE_RECEIVED?: string;
9
+ FOREGROUND_MESSAGE_RECEIVED: string;
10
+ LAUNCH_NOTIFICATION_OPENED: string;
11
+ NOTIFICATION_OPENED: string;
12
+ TOKEN_RECEIVED: string;
13
+ };
14
+ NativeHeadlessTaskKey?: string;
15
+ };
16
+ getLaunchNotification: () => Promise<Record<string, string>>;
17
+ getBadgeCount: () => Promise<number>;
18
+ setBadgeCount: (count: number) => void;
19
+ getPermissionStatus: () => Promise<string>;
20
+ requestPermissions: (
21
+ permissions: Record<string, boolean>
22
+ ) => Promise<boolean>;
23
+ }