customerio-expo-plugin 0.0.5 → 1.0.0-alpha.1

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 (143) hide show
  1. package/lib/commonjs/android/withAppGoogleServices.js +16 -0
  2. package/lib/commonjs/android/withAppGoogleServices.js.map +1 -0
  3. package/lib/commonjs/android/withCIOAndroid.js +18 -0
  4. package/lib/commonjs/android/withCIOAndroid.js.map +1 -0
  5. package/lib/commonjs/android/withGistMavenRepository.js +16 -0
  6. package/lib/commonjs/android/withGistMavenRepository.js.map +1 -0
  7. package/lib/commonjs/android/withGoogleServicesJSON.js +30 -0
  8. package/lib/commonjs/android/withGoogleServicesJSON.js.map +1 -0
  9. package/lib/commonjs/android/withProjectGoogleServices.js +16 -0
  10. package/lib/commonjs/android/withProjectGoogleServices.js.map +1 -0
  11. package/lib/commonjs/helpers/constants/android.js +19 -0
  12. package/lib/commonjs/helpers/constants/android.js.map +1 -0
  13. package/lib/commonjs/helpers/constants/globals.d.js +2 -0
  14. package/lib/commonjs/helpers/constants/globals.d.js.map +1 -0
  15. package/lib/commonjs/helpers/constants/ios.js +138 -0
  16. package/lib/commonjs/helpers/constants/ios.js.map +1 -0
  17. package/{build/helpers → lib/commonjs/helpers/native-files}/ios/CIONotificationService-Info.plist +0 -0
  18. package/{build/helpers → lib/commonjs/helpers/native-files}/ios/CIONotificationService.h +0 -0
  19. package/{build/helpers → lib/commonjs/helpers/native-files}/ios/CIONotificationService.m +0 -0
  20. package/{build/helpers → lib/commonjs/helpers/native-files}/ios/CIONotificationService.swift +0 -0
  21. package/{build/helpers → lib/commonjs/helpers/native-files}/ios/PushNotification.swift +0 -0
  22. package/lib/commonjs/helpers/utils/codeInjection.js +33 -0
  23. package/lib/commonjs/helpers/utils/codeInjection.js.map +1 -0
  24. package/lib/commonjs/helpers/utils/fileManagement.js +44 -0
  25. package/lib/commonjs/helpers/utils/fileManagement.js.map +1 -0
  26. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +32 -0
  27. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -0
  28. package/lib/commonjs/index.js +17 -0
  29. package/lib/commonjs/index.js.map +1 -0
  30. package/lib/commonjs/ios/withAppDelegateModifications.js +76 -0
  31. package/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -0
  32. package/lib/commonjs/ios/withAppDelegateXcodeProject.js +96 -0
  33. package/lib/commonjs/ios/withAppDelegateXcodeProject.js.map +1 -0
  34. package/lib/commonjs/ios/withCIOIos.js +18 -0
  35. package/lib/commonjs/ios/withCIOIos.js.map +1 -0
  36. package/lib/commonjs/ios/withNotificationsXcodeProject.js +157 -0
  37. package/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -0
  38. package/lib/commonjs/ios/withXcodeProject.js +28 -0
  39. package/lib/commonjs/ios/withXcodeProject.js.map +1 -0
  40. package/lib/commonjs/types/cio-types.js +15 -0
  41. package/lib/commonjs/types/cio-types.js.map +1 -0
  42. package/lib/module/android/withAppGoogleServices.js +9 -0
  43. package/lib/module/android/withAppGoogleServices.js.map +1 -0
  44. package/lib/module/android/withCIOAndroid.js +12 -0
  45. package/lib/module/android/withCIOAndroid.js.map +1 -0
  46. package/lib/module/android/withGistMavenRepository.js +9 -0
  47. package/lib/module/android/withGistMavenRepository.js.map +1 -0
  48. package/lib/module/android/withGoogleServicesJSON.js +23 -0
  49. package/lib/module/android/withGoogleServicesJSON.js.map +1 -0
  50. package/lib/module/android/withProjectGoogleServices.js +9 -0
  51. package/lib/module/android/withProjectGoogleServices.js.map +1 -0
  52. package/lib/module/helpers/constants/android.js +7 -0
  53. package/lib/module/helpers/constants/android.js.map +1 -0
  54. package/lib/module/helpers/constants/globals.d.js +2 -0
  55. package/lib/module/helpers/constants/globals.d.js.map +1 -0
  56. package/lib/module/helpers/constants/ios.js +102 -0
  57. package/lib/module/helpers/constants/ios.js.map +1 -0
  58. package/lib/module/helpers/native-files/ios/CIONotificationService-Info.plist +31 -0
  59. package/lib/module/helpers/native-files/ios/CIONotificationService.h +5 -0
  60. package/lib/module/helpers/native-files/ios/CIONotificationService.m +30 -0
  61. package/lib/module/helpers/native-files/ios/CIONotificationService.swift +21 -0
  62. package/lib/module/helpers/native-files/ios/PushNotification.swift +56 -0
  63. package/lib/module/helpers/utils/codeInjection.js +24 -0
  64. package/lib/module/helpers/utils/codeInjection.js.map +1 -0
  65. package/lib/module/helpers/utils/fileManagement.js +37 -0
  66. package/lib/module/helpers/utils/fileManagement.js.map +1 -0
  67. package/lib/module/helpers/utils/injectCIOPodfileCode.js +25 -0
  68. package/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -0
  69. package/lib/module/index.js +10 -0
  70. package/lib/module/index.js.map +1 -0
  71. package/lib/module/ios/withAppDelegateModifications.js +69 -0
  72. package/lib/module/ios/withAppDelegateModifications.js.map +1 -0
  73. package/lib/module/ios/withAppDelegateXcodeProject.js +88 -0
  74. package/lib/module/ios/withAppDelegateXcodeProject.js.map +1 -0
  75. package/lib/module/ios/withCIOIos.js +12 -0
  76. package/lib/module/ios/withCIOIos.js.map +1 -0
  77. package/lib/module/ios/withNotificationsXcodeProject.js +149 -0
  78. package/lib/module/ios/withNotificationsXcodeProject.js.map +1 -0
  79. package/lib/module/ios/withXcodeProject.js +21 -0
  80. package/lib/module/ios/withXcodeProject.js.map +1 -0
  81. package/lib/module/types/cio-types.js +10 -0
  82. package/lib/module/types/cio-types.js.map +1 -0
  83. package/lib/typescript/android/withAppGoogleServices.d.ts +3 -0
  84. package/lib/typescript/android/withCIOAndroid.d.ts +3 -0
  85. package/lib/typescript/android/withGistMavenRepository.d.ts +3 -0
  86. package/lib/typescript/android/withGoogleServicesJSON.d.ts +3 -0
  87. package/lib/typescript/android/withProjectGoogleServices.d.ts +3 -0
  88. package/lib/typescript/helpers/constants/android.d.ts +6 -0
  89. package/lib/typescript/helpers/constants/ios.d.ts +30 -0
  90. package/lib/typescript/helpers/utils/codeInjection.d.ts +4 -0
  91. package/lib/typescript/helpers/utils/fileManagement.d.ts +5 -0
  92. package/lib/typescript/helpers/utils/injectCIOPodfileCode.d.ts +2 -0
  93. package/lib/typescript/index.d.ts +4 -0
  94. package/lib/typescript/ios/withAppDelegateModifications.d.ts +2 -0
  95. package/lib/typescript/ios/withAppDelegateXcodeProject.d.ts +3 -0
  96. package/lib/typescript/ios/withCIOIos.d.ts +3 -0
  97. package/lib/typescript/ios/withNotificationsXcodeProject.d.ts +3 -0
  98. package/lib/typescript/ios/withXcodeProject.d.ts +3 -0
  99. package/lib/typescript/types/cio-types.d.ts +22 -0
  100. package/package.json +87 -13
  101. package/src/android/withAppGoogleServices.ts +19 -0
  102. package/src/android/withCIOAndroid.ts +19 -0
  103. package/src/android/withGistMavenRepository.ts +19 -0
  104. package/src/android/withGoogleServicesJSON.ts +30 -0
  105. package/src/android/withProjectGoogleServices.ts +19 -0
  106. package/src/helpers/constants/android.ts +12 -0
  107. package/src/helpers/constants/globals.d.ts +8 -0
  108. package/src/helpers/constants/ios.ts +116 -0
  109. package/src/helpers/native-files/ios/CIONotificationService-Info.plist +31 -0
  110. package/src/helpers/native-files/ios/CIONotificationService.h +5 -0
  111. package/src/helpers/native-files/ios/CIONotificationService.m +30 -0
  112. package/src/helpers/native-files/ios/CIONotificationService.swift +21 -0
  113. package/src/helpers/native-files/ios/PushNotification.swift +56 -0
  114. package/src/helpers/utils/codeInjection.ts +46 -0
  115. package/src/helpers/utils/fileManagement.ts +39 -0
  116. package/src/helpers/utils/injectCIOPodfileCode.ts +47 -0
  117. package/src/index.ts +21 -0
  118. package/src/ios/withAppDelegateModifications.ts +150 -0
  119. package/src/ios/withAppDelegateXcodeProject.ts +110 -0
  120. package/src/ios/withCIOIos.ts +19 -0
  121. package/src/ios/withNotificationsXcodeProject.ts +231 -0
  122. package/src/ios/withXcodeProject.ts +25 -0
  123. package/src/types/cio-types.ts +28 -0
  124. package/build/helpers/.DS_Store +0 -0
  125. package/build/helpers/ios/.DS_Store +0 -0
  126. package/build/package.json +0 -36
  127. package/build/src/android/withAppGoogleServices.js +0 -12
  128. package/build/src/android/withCIOAndroid.js +0 -15
  129. package/build/src/android/withGistMavenRepository.js +0 -12
  130. package/build/src/android/withGoogleServicesJSON.js +0 -24
  131. package/build/src/android/withProjectGoogleServices.js +0 -12
  132. package/build/src/helpers/constants/android.js +0 -9
  133. package/build/src/helpers/constants/ios.js +0 -102
  134. package/build/src/helpers/utils/codeInjection.js +0 -30
  135. package/build/src/helpers/utils/fileManagement.js +0 -40
  136. package/build/src/helpers/utils/injectCIOPodfileCode.js +0 -37
  137. package/build/src/index.js +0 -11
  138. package/build/src/ios/withAppDelegateModifications.js +0 -77
  139. package/build/src/ios/withAppDelegateXcodeProject.js +0 -78
  140. package/build/src/ios/withCIOIos.js +0 -15
  141. package/build/src/ios/withNotificationsXcodeProject.js +0 -133
  142. package/build/src/ios/withXcodeProject.js +0 -22
  143. package/build/src/types/cio-types.js +0 -8
@@ -0,0 +1,116 @@
1
+ export const LOCAL_PATH_TO_CIO_NSE_FILES = `node_modules/customerio-expo-plugin/src/helpers/native-files/ios`;
2
+ export const IOS_DEPLOYMENT_TARGET = '13.0';
3
+ export const CIO_PODFILE_REGEX = /pod 'RCT-Folly'/;
4
+ export const CIO_PODFILE_NOTIFICATION_REGEX =
5
+ /target 'CIONotificationService' do/;
6
+ export const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
7
+ export const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;
8
+ export const BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;
9
+ export const CIO_PODFILE_POST_INSTALL_REGEX = /post_install do \|installer\|/;
10
+ export const CIO_DIDFINISHLAUNCHINGMETHOD_REGEX =
11
+ /(- \(BOOL\)application:\(UIApplication \*\)application didFinishLaunchingWithOptions:\(NSDictionary \*\)launchOptions(\s|\n)*?\{)((.|\n)*)\[super(\s)application:application(\s)didFinishLaunchingWithOptions:launchOptions\];/;
12
+
13
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX =
14
+ /return \[super application:application didFailToRegisterForRemoteNotificationsWithError:error\];/;
15
+
16
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX =
17
+ /(- \(void\)application:\(UIApplication \*\)application didFailToRegisterForRemoteNotificationsWithError:\(NSError \*\)error(\s|\n)*?\{)(.|\n){2}.*\n\}/;
18
+
19
+ export const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX =
20
+ /return \[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken\];/;
21
+
22
+ export const CIO_APPDELEGATEDECLARATION_REGEX =
23
+ /@implementation AppDelegate(.|\n)/;
24
+
25
+ export const CIO_APPDELEGATEHEADER_REGEX =
26
+ /@interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate>/;
27
+ export const DEFAULT_BUNDLE_VERSION = '1';
28
+ export const DEFAULT_BUNDLE_SHORT_VERSION = '1.0';
29
+ export const CIO_TARGET_NAME = 'CustomerIOSDK';
30
+ export const CIO_NOTIFICATION_TARGET_NAME = 'CIONotificationService';
31
+ export const CIO_APPDELEGATEHEADER_SNIPPET = `
32
+ #import <UserNotifications/UserNotifications.h>
33
+
34
+ @interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate, UNUserNotificationCenterDelegate>
35
+ `;
36
+
37
+ export const CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = `
38
+ CIOAppPushNotificationsHandler* pnHandlerObj = [[CIOAppPushNotificationsHandler alloc] init];
39
+ `;
40
+
41
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = `
42
+ [pnHandlerObj application:application error:error];
43
+ `;
44
+
45
+ export const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `
46
+ return [pnHandlerObj application:application deviceToken:deviceToken];
47
+ `;
48
+
49
+ // Configure Customerio push notifications SDK by adding to application:didFinishLaunchingWithOptions: delegate method
50
+ // From Braze docs: https://www.customer.io/docs/sdk/react-native/push/#obj-c-push
51
+ export const CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `
52
+ // Register for push notifications
53
+ [pnHandlerObj registerPushNotification:self];
54
+ `;
55
+
56
+ // Enable push handling - notification response
57
+ export const CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET = `
58
+ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
59
+ [pnHandlerObj userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
60
+ }`;
61
+
62
+ // Foreground push handling
63
+ export const CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET = `
64
+ // show push when the app is in foreground
65
+ - (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
66
+ completionHandler( UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);
67
+ }`;
68
+ export const CIO_PODFILE_NOTIFICATION_SNIPPET = `
69
+ target '${CIO_NOTIFICATION_TARGET_NAME}' do
70
+ pod 'CustomerIO/MessagingPushAPN', '~> 1.2.0-alpha.3'
71
+ end`;
72
+ export const CIO_PODFILE_SNIPPET = `
73
+ pod 'RCT-Folly', :podspec => '../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec'
74
+ pod 'boost', :podspec => '../node_modules/react-native/third-party-podspecs/boost.podspec'
75
+ pod 'CustomerIO/MessagingPushAPN', '~> 1.2.0-alpha.3'`;
76
+ export const CIO_PODFILE_TARGET_NAMES_SNIPPET = `
77
+ cio_target_names = [
78
+ 'CustomerIOTracking',
79
+ 'CustomerIOCommon',
80
+ 'CustomerIOMessagingPushAPN',
81
+ 'CustomerIOMessagingPush'
82
+ ]`;
83
+ export const CIO_PODFILE_POST_INSTALL_SNIPPET = `
84
+ installer.pods_project.targets.each do |target|
85
+ if cio_target_names.include? target.name
86
+ puts "Modifying target #{target.name}"
87
+
88
+ target.build_configurations.each do |config|
89
+ puts "Setting build config settings for #{target.name}"
90
+ config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
91
+ end
92
+ end
93
+ end`;
94
+ export const CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET = `
95
+ cio_target_names = [
96
+ 'CustomerIOTracking',
97
+ 'CustomerIOCommon',
98
+ 'CustomerIOMessagingPushAPN',
99
+ 'CustomerIOMessagingPush'
100
+ ]
101
+
102
+ post_install do |installer|
103
+
104
+ installer.pods_project.targets.each do |target|
105
+ if cio_target_names.include? target.name
106
+ puts "Modifying target #{target.name}"
107
+
108
+ target.build_configurations.each do |config|
109
+ puts "Setting build config settings for #{target.name}"
110
+ config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
111
+ end
112
+ end
113
+ end
114
+ react_native_post_install(installer)
115
+ __apply_Xcode_12_5_M1_post_install_workaround(installer)
116
+ end`;
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleShortVersionString</key>
6
+ <string>{{BUNDLE_SHORT_VERSION}}</string>
7
+ <key>CFBundleVersion</key>
8
+ <string>{{BUNDLE_VERSION}}</string>
9
+ <key>CFBundleDevelopmentRegion</key>
10
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
11
+ <key>CFBundleDisplayName</key>
12
+ <string>CIONotificationServiceExtension</string>
13
+ <key>CFBundleExecutable</key>
14
+ <string>$(EXECUTABLE_NAME)</string>
15
+ <key>CFBundleIdentifier</key>
16
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
17
+ <key>CFBundleInfoDictionaryVersion</key>
18
+ <string>6.0</string>
19
+ <key>CFBundleName</key>
20
+ <string>$(PRODUCT_NAME)</string>
21
+ <key>CFBundlePackageType</key>
22
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
23
+ <key>NSExtension</key>
24
+ <dict>
25
+ <key>NSExtensionPointIdentifier</key>
26
+ <string>com.apple.usernotifications.service</string>
27
+ <key>NSExtensionPrincipalClass</key>
28
+ <string>CIONotificationService</string>
29
+ </dict>
30
+ </dict>
31
+ </plist>
@@ -0,0 +1,5 @@
1
+ #import <UserNotifications/UserNotifications.h>
2
+
3
+ @interface NotificationService : UNNotificationServiceExtension
4
+
5
+ @end
@@ -0,0 +1,30 @@
1
+
2
+ #import "CIONotificationService.h"
3
+ // MARK: - CIO-TECH-ASSISTANCE
4
+ // Import "Your-target-name-Swift.h" file
5
+ #import "CIONotificationService-Swift.h"
6
+
7
+ @interface NotificationService ()
8
+
9
+ @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
10
+ @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
11
+
12
+ @end
13
+
14
+ @implementation NotificationService
15
+
16
+ - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
17
+ // MARK: - CIO-TECH-ASSISTANCE
18
+ NotificationServiceCioManager* cioManagerObj = [[NotificationServiceCioManager alloc] init];
19
+ [cioManagerObj didReceive:request withContentHandler:contentHandler];
20
+ }
21
+
22
+ - (void)serviceExtensionTimeWillExpire {
23
+ // Called just before the extension will be terminated by the system.
24
+ // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
25
+ // MARK: - CIO-TECH-ASSISTANCE
26
+ NotificationServiceCioManager* cioManagerObj = [[NotificationServiceCioManager alloc] init];
27
+ [cioManagerObj serviceExtensionTimeWillExpire];
28
+ }
29
+
30
+ @end
@@ -0,0 +1,21 @@
1
+ import Foundation
2
+ import UserNotifications
3
+ import CioMessagingPush
4
+
5
+ // MARK: - CIO-TECH-ASSISTANCE
6
+ // This is another example of handling ObjC calls for Swift CustomerIO SDK
7
+ @objc
8
+ public class NotificationServiceCioManager : NSObject {
9
+
10
+ public override init() {}
11
+
12
+ @objc(didReceive:withContentHandler:)
13
+ public func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
14
+ MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
15
+ }
16
+
17
+ @objc(serviceExtensionTimeWillExpire)
18
+ public func serviceExtensionTimeWillExpire() {
19
+ MessagingPush.shared.serviceExtensionTimeWillExpire()
20
+ }
21
+ }
@@ -0,0 +1,56 @@
1
+ //
2
+ // PushNotification.swift
3
+ // testandroidapp
4
+ //
5
+ // Created by Segun Xtreem on 10/09/2022.
6
+ //
7
+
8
+ import Foundation
9
+ import CioMessagingPushAPN
10
+ import CioTracking
11
+ import UserNotifications
12
+ import UIKit
13
+
14
+ @objc
15
+ public class CIOAppPushNotificationsHandler : NSObject {
16
+
17
+ public override init() {}
18
+
19
+ // MARK: - ObjCNEW
20
+ @objc(registerPushNotification:)
21
+ public func registerPushNotification(withNotificationDelegate notificationDelegate: UNUserNotificationCenterDelegate) {
22
+
23
+ let center = UNUserNotificationCenter.current()
24
+ center.delegate = notificationDelegate // MARK: - ObjCNEW
25
+ center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
26
+ if error == nil{
27
+ DispatchQueue.main.async {
28
+ UIApplication.shared.registerForRemoteNotifications()
29
+ }
30
+ }
31
+ }
32
+ }
33
+
34
+ @objc(application:deviceToken:)
35
+ public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
36
+ MessagingPush.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
37
+ }
38
+
39
+ @objc(application:error:)
40
+ public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
41
+ MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
42
+ }
43
+
44
+ // MARK: - ObjCNEW
45
+ @objc(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)
46
+ public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
47
+ let handled = MessagingPush.shared.userNotificationCenter(center, didReceive: response,
48
+ withCompletionHandler: completionHandler)
49
+
50
+ // If the Customer.io SDK does not handle the push, it's up to you to handle it and call the
51
+ // completion handler. If the SDK did handle it, it called the completion handler for you.
52
+ if !handled {
53
+ completionHandler()
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,46 @@
1
+ export function injectCodeByRegex(
2
+ fileContent: string,
3
+ lineRegex: RegExp,
4
+ snippet: string
5
+ ) {
6
+ const lines = fileContent.split('\n');
7
+ const index = lines.findIndex((line) => lineRegex.test(line));
8
+ let content: string[] = lines;
9
+
10
+ if (index > -1) {
11
+ content = [...lines.slice(0, index), snippet, ...lines.slice(index)];
12
+ }
13
+
14
+ return content;
15
+ }
16
+
17
+ export function injectCodeByMultiLineRegex(
18
+ fileContent: string,
19
+ lineRegex: RegExp,
20
+ snippet: string
21
+ ) {
22
+ return fileContent.replace(lineRegex, `$&\n${snippet}`);
23
+ }
24
+
25
+ export function injectCodeByMultiLineRegexAndReplaceLine(
26
+ fileContent: string,
27
+ lineRegex: RegExp,
28
+ snippet: string
29
+ ) {
30
+ return fileContent.replace(lineRegex, `${snippet}`);
31
+ }
32
+
33
+ export function injectCodeByLineNumber(
34
+ fileContent: string,
35
+ index: number,
36
+ snippet: string
37
+ ) {
38
+ const lines = fileContent.split('\n');
39
+ let content: string[] = lines;
40
+
41
+ if (index > -1) {
42
+ content = [...lines.slice(0, index), snippet, ...lines.slice(index)];
43
+ }
44
+
45
+ return content;
46
+ }
@@ -0,0 +1,39 @@
1
+ import { readFile, writeFile, appendFile } from 'fs';
2
+
3
+ export class FileManagement {
4
+ static async read(path: string): Promise<string> {
5
+ return new Promise<string>((resolve, reject) => {
6
+ readFile(path, 'utf8', (err, data) => {
7
+ if (err || !data) {
8
+ reject(err);
9
+ return;
10
+ }
11
+ resolve(data);
12
+ });
13
+ });
14
+ }
15
+
16
+ static async write(path: string, contents: string): Promise<void> {
17
+ return new Promise<void>((resolve, reject) => {
18
+ writeFile(path, contents, 'utf8', (err) => {
19
+ if (err) {
20
+ reject(err);
21
+ return;
22
+ }
23
+ resolve();
24
+ });
25
+ });
26
+ }
27
+
28
+ static async append(path: string, contents: string): Promise<void> {
29
+ return new Promise<void>((resolve, reject) => {
30
+ appendFile(path, contents, 'utf8', (err) => {
31
+ if (err) {
32
+ reject(err);
33
+ return;
34
+ }
35
+ resolve();
36
+ });
37
+ });
38
+ }
39
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ CIO_PODFILE_REGEX,
3
+ CIO_PODFILE_SNIPPET,
4
+ CIO_PODFILE_POST_INSTALL_REGEX,
5
+ CIO_PODFILE_TARGET_NAMES_SNIPPET,
6
+ CIO_PODFILE_POST_INSTALL_SNIPPET,
7
+ CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET,
8
+ CIO_PODFILE_NOTIFICATION_SNIPPET,
9
+ CIO_PODFILE_NOTIFICATION_REGEX,
10
+ } from '../constants/ios';
11
+ import { FileManagement } from './fileManagement';
12
+
13
+ export async function injectCIOPodfileCode(iosPath: string) {
14
+ const filename = `${iosPath}/Podfile`;
15
+ const podfile = await FileManagement.read(filename);
16
+ const matches = podfile.match(CIO_PODFILE_REGEX);
17
+
18
+ const lines = podfile.split('\n');
19
+ const index = lines.findIndex((line) =>
20
+ CIO_PODFILE_POST_INSTALL_REGEX.test(line)
21
+ );
22
+ let content: string[] = lines;
23
+ if (index > -1) {
24
+ content = [
25
+ ...lines.slice(0, index - 1),
26
+ !matches ? CIO_PODFILE_SNIPPET : '',
27
+ CIO_PODFILE_TARGET_NAMES_SNIPPET,
28
+ ...lines.slice(index - 1, index + 1),
29
+ CIO_PODFILE_POST_INSTALL_SNIPPET,
30
+ ...lines.slice(index + 1),
31
+ ];
32
+ } else {
33
+ content.push(CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET);
34
+ }
35
+
36
+ FileManagement.write(filename, content.join('\n'));
37
+ }
38
+
39
+ export async function injectCIONotificationPodfileCode(iosPath: string) {
40
+ const filename = `${iosPath}/Podfile`;
41
+ const podfile = await FileManagement.read(filename);
42
+ const matches = podfile.match(CIO_PODFILE_NOTIFICATION_REGEX);
43
+
44
+ if (!matches) {
45
+ FileManagement.append(filename, CIO_PODFILE_NOTIFICATION_SNIPPET);
46
+ }
47
+ }
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { ExpoConfig } from '@expo/config-types';
2
+
3
+ import { withCIOAndroid } from './android/withCIOAndroid';
4
+ import { withCIOIos } from './ios/withCIOIos';
5
+ import type {
6
+ CustomerIOPluginOptionsIOS,
7
+ CustomerIOPluginOptionsAndroid,
8
+ } from './types/cio-types';
9
+
10
+ // Entry point for config plugin
11
+ function withCustomerIOPlugin(
12
+ config: ExpoConfig,
13
+ props: CustomerIOPluginOptionsIOS | CustomerIOPluginOptionsAndroid
14
+ ) {
15
+ config = withCIOIos(config, props as CustomerIOPluginOptionsIOS);
16
+ config = withCIOAndroid(config, props as CustomerIOPluginOptionsAndroid);
17
+
18
+ return config;
19
+ }
20
+
21
+ export default withCustomerIOPlugin;
@@ -0,0 +1,150 @@
1
+ import { ConfigPlugin, withAppDelegate } from '@expo/config-plugins';
2
+ import { getAppDelegateHeaderFilePath } from '@expo/config-plugins/build/ios/Paths';
3
+
4
+ import {
5
+ CIO_APPDELEGATEDECLARATION_REGEX,
6
+ CIO_APPDELEGATEHEADER_REGEX,
7
+ CIO_APPDELEGATEHEADER_SNIPPET,
8
+ CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET,
9
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
10
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX,
11
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET,
12
+ CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
13
+ CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
14
+ CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX,
15
+ CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET,
16
+ CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET,
17
+ CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
18
+ } from '../helpers/constants/ios';
19
+ import {
20
+ injectCodeByLineNumber,
21
+ injectCodeByMultiLineRegex,
22
+ injectCodeByMultiLineRegexAndReplaceLine,
23
+ } from '../helpers/utils/codeInjection';
24
+ import { FileManagement } from '../helpers/utils/fileManagement';
25
+
26
+ const pushCodeSnippets = [
27
+ CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
28
+ CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
29
+ ];
30
+
31
+ const additionalMethodsForPushNotifications = `${pushCodeSnippets.join(
32
+ '\n'
33
+ )}\n`; // Join w/ newlines and ensure a newline at the end.
34
+
35
+ const addImport = (stringContents: string) => {
36
+ const importRegex = /^(#import .*)\n/gm;
37
+ const addedImport = `
38
+ // Add swift bridge imports
39
+ #import <ExpoModulesCore-Swift.h>
40
+ #import <testiosapp-Swift.h>
41
+ `;
42
+
43
+ const match = stringContents.match(importRegex);
44
+ let endOfMatchIndex: number;
45
+ if (!match || match.index === undefined) {
46
+ // No imports found, just add to start of file:
47
+ endOfMatchIndex = 0;
48
+ } else {
49
+ // Add after first import:
50
+ endOfMatchIndex = match.index + match[0].length;
51
+ }
52
+
53
+ stringContents = injectCodeByLineNumber(
54
+ stringContents,
55
+ endOfMatchIndex,
56
+ addedImport
57
+ ).join('\n');
58
+
59
+ return stringContents;
60
+ };
61
+
62
+ const addNotificationHandlerDeclaration = (stringContents: string) => {
63
+ stringContents = injectCodeByMultiLineRegex(
64
+ stringContents,
65
+ CIO_APPDELEGATEDECLARATION_REGEX,
66
+ CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET
67
+ );
68
+
69
+ return stringContents;
70
+ };
71
+
72
+ const addNotificationConfiguration = (stringContents: string) => {
73
+ stringContents = injectCodeByMultiLineRegex(
74
+ stringContents,
75
+ CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
76
+ CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET
77
+ );
78
+
79
+ return stringContents;
80
+ };
81
+
82
+ const addDidFailToRegisterForRemoteNotificationsWithError = (
83
+ stringContents: string
84
+ ) => {
85
+ stringContents = injectCodeByMultiLineRegexAndReplaceLine(
86
+ stringContents,
87
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX,
88
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET
89
+ );
90
+
91
+ return stringContents;
92
+ };
93
+
94
+ const AddDidRegisterForRemoteNotificationsWithDeviceToken = (
95
+ stringContents: string
96
+ ) => {
97
+ stringContents = injectCodeByMultiLineRegexAndReplaceLine(
98
+ stringContents,
99
+ CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX,
100
+ CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET
101
+ );
102
+
103
+ return stringContents;
104
+ };
105
+
106
+ const addAdditionalMethodsForPushNotifications = (stringContents: string) => {
107
+ stringContents = injectCodeByMultiLineRegex(
108
+ stringContents,
109
+ CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
110
+ additionalMethodsForPushNotifications
111
+ );
112
+
113
+ return stringContents;
114
+ };
115
+
116
+ const addAppdelegateHeaderModification = (stringContents: string) => {
117
+ stringContents = injectCodeByMultiLineRegexAndReplaceLine(
118
+ stringContents,
119
+ CIO_APPDELEGATEHEADER_REGEX,
120
+ CIO_APPDELEGATEHEADER_SNIPPET
121
+ );
122
+
123
+ return stringContents;
124
+ };
125
+
126
+ export const withAppDelegateModifications: ConfigPlugin<any> = (
127
+ configOuter
128
+ ) => {
129
+ return withAppDelegate(configOuter, async (config) => {
130
+ let stringContents = config.modResults.contents;
131
+ const headerPath = getAppDelegateHeaderFilePath(
132
+ config.modRequest.projectRoot
133
+ );
134
+ let headerContent = await FileManagement.read(headerPath);
135
+ headerContent = addAppdelegateHeaderModification(headerContent);
136
+ FileManagement.write(headerPath, headerContent);
137
+
138
+ stringContents = addImport(stringContents);
139
+ stringContents = addNotificationHandlerDeclaration(stringContents);
140
+ stringContents = addNotificationConfiguration(stringContents);
141
+ stringContents = addAdditionalMethodsForPushNotifications(stringContents);
142
+ stringContents =
143
+ addDidFailToRegisterForRemoteNotificationsWithError(stringContents);
144
+ stringContents =
145
+ AddDidRegisterForRemoteNotificationsWithDeviceToken(stringContents);
146
+
147
+ config.modResults.contents = stringContents;
148
+ return config;
149
+ });
150
+ };
@@ -0,0 +1,110 @@
1
+ import { ConfigPlugin, withXcodeProject } from '@expo/config-plugins';
2
+ import fs from 'fs';
3
+ import xcode from 'xcode';
4
+
5
+ import {
6
+ DEFAULT_BUNDLE_VERSION,
7
+ LOCAL_PATH_TO_CIO_NSE_FILES,
8
+ } from '../helpers/constants/ios';
9
+ import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
10
+
11
+ const addNotificationServiceExtensionFile = async (
12
+ options: CustomerIOPluginOptionsIOS
13
+ ) => {
14
+ const { iosPath, appName } = options;
15
+
16
+ const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
17
+
18
+ const xcodeProject = xcode.project(projPath);
19
+
20
+ xcodeProject.parse(async function (err: Error) {
21
+ if (err) {
22
+ throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
23
+ }
24
+
25
+ fs.mkdirSync(`${iosPath}/${appName}`, {
26
+ recursive: true,
27
+ });
28
+
29
+ const file = 'PushNotification.swift';
30
+
31
+ const getTargetFile = (filename: string) =>
32
+ `${iosPath}/${appName}/${filename}`;
33
+
34
+ const targetFile = getTargetFile(file);
35
+ fs.copyFileSync(`${LOCAL_PATH_TO_CIO_NSE_FILES}/${file}`, targetFile);
36
+
37
+ // Create new PBXGroup for the extension
38
+ const extGroup = xcodeProject.addPbxGroup([file], appName, appName);
39
+
40
+ // Add the new PBXGroup to the top level group. This makes the
41
+ // files / folder appear in the file explorer in Xcode.
42
+ const groups = xcodeProject.hash.project.objects['PBXGroup'];
43
+ Object.keys(groups).forEach((key) => {
44
+ if (groups[key].name === undefined) {
45
+ xcodeProject.addToPbxGroup(extGroup.uuid, key);
46
+ }
47
+ });
48
+
49
+ // WORK AROUND for codeProject.addTarget BUG
50
+ // Xcode projects don't contain these if there is only one target
51
+ // An upstream fix should be made to the code referenced in this link:
52
+ // - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
53
+ const projObjects = xcodeProject.hash.project.objects;
54
+ projObjects['PBXTargetDependency'] =
55
+ projObjects['PBXTargetDependency'] || {};
56
+ projObjects['PBXContainerItemProxy'] =
57
+ projObjects['PBXTargetDependency'] || {};
58
+
59
+ fs.writeFileSync(projPath, xcodeProject.writeSync());
60
+ });
61
+ };
62
+
63
+ export const withCioAppdelegateXcodeProject: ConfigPlugin<
64
+ CustomerIOPluginOptionsIOS
65
+ > = (configOuter, props) => {
66
+ return withXcodeProject(configOuter, async (config) => {
67
+ const { modRequest, ios, version: bundleShortVersion } = config;
68
+ const { appleTeamId, iosDeploymentTarget } = props;
69
+
70
+ if (ios === undefined)
71
+ throw new Error(
72
+ 'Adding NotificationServiceExtension failed: ios config missing from app.config.js.'
73
+ );
74
+
75
+ const { projectName, platformProjectRoot } = modRequest;
76
+ const { bundleIdentifier, buildNumber } = ios;
77
+
78
+ if (bundleShortVersion === undefined) {
79
+ throw new Error(
80
+ 'Adding NotificationServiceExtension failed: version missing from app.config.js'
81
+ );
82
+ }
83
+
84
+ if (bundleIdentifier === undefined) {
85
+ throw new Error(
86
+ 'Adding NotificationServiceExtension failed: ios.bundleIdentifier missing from app.config.js'
87
+ );
88
+ }
89
+
90
+ if (projectName === undefined) {
91
+ throw new Error(
92
+ 'Adding NotificationServiceExtension failed: name missing from app.config.js'
93
+ );
94
+ }
95
+
96
+ const options = {
97
+ appleTeamId,
98
+ bundleIdentifier,
99
+ bundleShortVersion,
100
+ bundleVersion: buildNumber ?? DEFAULT_BUNDLE_VERSION,
101
+ iosPath: platformProjectRoot,
102
+ appName: projectName,
103
+ iosDeploymentTarget,
104
+ };
105
+
106
+ await addNotificationServiceExtensionFile(options);
107
+
108
+ return config;
109
+ });
110
+ };