customerio-expo-plugin 1.0.0-beta.8 → 2.0.0-beta.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 (184) hide show
  1. package/README.md +8 -5
  2. package/package.json +34 -23
  3. package/plugin/app.plugin.js +1 -0
  4. package/{lib → plugin/lib}/commonjs/android/withAndroidManifestUpdates.js.map +1 -1
  5. package/{lib → plugin/lib}/commonjs/android/withAppGoogleServices.js.map +1 -1
  6. package/{lib → plugin/lib}/commonjs/android/withCIOAndroid.js +2 -0
  7. package/plugin/lib/commonjs/android/withCIOAndroid.js.map +1 -0
  8. package/{lib → plugin/lib}/commonjs/android/withGistMavenRepository.js.map +1 -1
  9. package/{lib → plugin/lib}/commonjs/android/withGoogleServicesJSON.js.map +1 -1
  10. package/{lib → plugin/lib}/commonjs/android/withProjectGoogleServices.js.map +1 -1
  11. package/plugin/lib/commonjs/android/withProjectStrings.js +70 -0
  12. package/plugin/lib/commonjs/android/withProjectStrings.js.map +1 -0
  13. package/plugin/lib/commonjs/helpers/constants/android.js +14 -0
  14. package/{lib → plugin/lib}/commonjs/helpers/constants/android.js.map +1 -1
  15. package/{lib → plugin/lib}/commonjs/helpers/constants/globals.d.js.map +1 -1
  16. package/plugin/lib/commonjs/helpers/constants/ios.js +119 -0
  17. package/plugin/lib/commonjs/helpers/constants/ios.js.map +1 -0
  18. package/plugin/lib/commonjs/helpers/native-files/ios/Env.swift +7 -0
  19. package/plugin/lib/commonjs/helpers/native-files/ios/NotificationService.swift +25 -0
  20. package/{src → plugin/lib/commonjs}/helpers/native-files/ios/PushService.swift +10 -13
  21. package/{lib → plugin/lib}/commonjs/helpers/utils/codeInjection.js +9 -1
  22. package/plugin/lib/commonjs/helpers/utils/codeInjection.js.map +1 -0
  23. package/{lib → plugin/lib}/commonjs/helpers/utils/fileManagement.js.map +1 -1
  24. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +50 -0
  25. package/plugin/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +1 -0
  26. package/plugin/lib/commonjs/helpers/utils/pluginUtils.js +26 -0
  27. package/plugin/lib/commonjs/helpers/utils/pluginUtils.js.map +1 -0
  28. package/{lib → plugin/lib}/commonjs/index.js +1 -2
  29. package/{lib → plugin/lib}/commonjs/index.js.map +1 -1
  30. package/{lib → plugin/lib}/commonjs/ios/withAppDelegateModifications.js +63 -9
  31. package/plugin/lib/commonjs/ios/withAppDelegateModifications.js.map +1 -0
  32. package/{lib → plugin/lib}/commonjs/ios/withCIOIos.js.map +1 -1
  33. package/{lib → plugin/lib}/commonjs/ios/withNotificationsXcodeProject.js +30 -34
  34. package/plugin/lib/commonjs/ios/withNotificationsXcodeProject.js.map +1 -0
  35. package/{lib → plugin/lib}/commonjs/ios/withXcodeProject.js.map +1 -1
  36. package/{lib → plugin/lib}/commonjs/postInstall.js.map +1 -1
  37. package/plugin/lib/commonjs/postInstallHelper.js +22 -0
  38. package/plugin/lib/commonjs/postInstallHelper.js.map +1 -0
  39. package/plugin/lib/commonjs/types/cio-types.js.map +1 -0
  40. package/{lib → plugin/lib}/module/android/withAndroidManifestUpdates.js.map +1 -1
  41. package/{lib → plugin/lib}/module/android/withAppGoogleServices.js.map +1 -1
  42. package/{lib → plugin/lib}/module/android/withCIOAndroid.js +2 -0
  43. package/plugin/lib/module/android/withCIOAndroid.js.map +1 -0
  44. package/{lib → plugin/lib}/module/android/withGistMavenRepository.js.map +1 -1
  45. package/{lib → plugin/lib}/module/android/withGoogleServicesJSON.js.map +1 -1
  46. package/{lib → plugin/lib}/module/android/withProjectGoogleServices.js.map +1 -1
  47. package/plugin/lib/module/android/withProjectStrings.js +63 -0
  48. package/plugin/lib/module/android/withProjectStrings.js.map +1 -0
  49. package/{lib → plugin/lib}/module/helpers/constants/android.js.map +1 -1
  50. package/{lib → plugin/lib}/module/helpers/constants/globals.d.js.map +1 -1
  51. package/plugin/lib/module/helpers/constants/ios.js +112 -0
  52. package/plugin/lib/module/helpers/constants/ios.js.map +1 -0
  53. package/plugin/lib/module/helpers/native-files/ios/Env.swift +7 -0
  54. package/plugin/lib/module/helpers/native-files/ios/NotificationService.swift +25 -0
  55. package/{lib → plugin/lib}/module/helpers/native-files/ios/PushService.swift +10 -13
  56. package/{lib → plugin/lib}/module/helpers/utils/codeInjection.js +7 -1
  57. package/plugin/lib/module/helpers/utils/codeInjection.js.map +1 -0
  58. package/{lib → plugin/lib}/module/helpers/utils/fileManagement.js.map +1 -1
  59. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js +43 -0
  60. package/plugin/lib/module/helpers/utils/injectCIOPodfileCode.js.map +1 -0
  61. package/plugin/lib/module/helpers/utils/pluginUtils.js +19 -0
  62. package/plugin/lib/module/helpers/utils/pluginUtils.js.map +1 -0
  63. package/{lib → plugin/lib}/module/index.js.map +1 -1
  64. package/plugin/lib/module/ios/withAppDelegateModifications.js +136 -0
  65. package/plugin/lib/module/ios/withAppDelegateModifications.js.map +1 -0
  66. package/{lib → plugin/lib}/module/ios/withCIOIos.js.map +1 -1
  67. package/{lib → plugin/lib}/module/ios/withNotificationsXcodeProject.js +30 -33
  68. package/plugin/lib/module/ios/withNotificationsXcodeProject.js.map +1 -0
  69. package/{lib → plugin/lib}/module/ios/withXcodeProject.js.map +1 -1
  70. package/{lib → plugin/lib}/module/postInstall.js.map +1 -1
  71. package/plugin/lib/module/postInstallHelper.js +20 -0
  72. package/plugin/lib/module/postInstallHelper.js.map +1 -0
  73. package/plugin/lib/module/types/cio-types.js.map +1 -0
  74. package/plugin/lib/typescript/android/withProjectStrings.d.ts +15 -0
  75. package/plugin/lib/typescript/helpers/constants/ios.d.ts +30 -0
  76. package/{lib → plugin/lib}/typescript/helpers/utils/codeInjection.d.ts +3 -1
  77. package/plugin/lib/typescript/helpers/utils/pluginUtils.d.ts +4 -0
  78. package/{lib → plugin/lib}/typescript/types/cio-types.d.ts +8 -2
  79. package/{src → plugin/src}/android/withCIOAndroid.ts +2 -0
  80. package/plugin/src/android/withProjectStrings.ts +57 -0
  81. package/plugin/src/helpers/constants/ios.ts +144 -0
  82. package/plugin/src/helpers/native-files/ios/Env.swift +7 -0
  83. package/plugin/src/helpers/native-files/ios/NotificationService.swift +25 -0
  84. package/{lib/commonjs → plugin/src}/helpers/native-files/ios/PushService.swift +10 -13
  85. package/{src → plugin/src}/helpers/utils/codeInjection.ts +12 -1
  86. package/plugin/src/helpers/utils/injectCIOPodfileCode.ts +67 -0
  87. package/plugin/src/helpers/utils/pluginUtils.ts +22 -0
  88. package/{src → plugin/src}/ios/withAppDelegateModifications.ts +118 -23
  89. package/{src → plugin/src}/ios/withNotificationsXcodeProject.ts +57 -35
  90. package/plugin/src/postInstallHelper.js +32 -0
  91. package/{src → plugin/src}/types/cio-types.ts +8 -2
  92. package/lib/commonjs/android/withCIOAndroid.js.map +0 -1
  93. package/lib/commonjs/helpers/constants/android.js +0 -21
  94. package/lib/commonjs/helpers/constants/ios.js +0 -115
  95. package/lib/commonjs/helpers/constants/ios.js.map +0 -1
  96. package/lib/commonjs/helpers/native-files/ios/Env.swift +0 -8
  97. package/lib/commonjs/helpers/native-files/ios/NotificationService.swift +0 -22
  98. package/lib/commonjs/helpers/utils/codeInjection.js.map +0 -1
  99. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js +0 -36
  100. package/lib/commonjs/helpers/utils/injectCIOPodfileCode.js.map +0 -1
  101. package/lib/commonjs/ios/withAppDelegateModifications.js.map +0 -1
  102. package/lib/commonjs/ios/withNotificationsXcodeProject.js.map +0 -1
  103. package/lib/commonjs/postInstallHelper.js +0 -20
  104. package/lib/commonjs/postInstallHelper.js.map +0 -1
  105. package/lib/commonjs/types/cio-types.js.map +0 -1
  106. package/lib/module/android/withCIOAndroid.js.map +0 -1
  107. package/lib/module/helpers/constants/ios.js +0 -78
  108. package/lib/module/helpers/constants/ios.js.map +0 -1
  109. package/lib/module/helpers/native-files/ios/Env.swift +0 -8
  110. package/lib/module/helpers/native-files/ios/NotificationService.swift +0 -22
  111. package/lib/module/helpers/utils/codeInjection.js.map +0 -1
  112. package/lib/module/helpers/utils/injectCIOPodfileCode.js +0 -29
  113. package/lib/module/helpers/utils/injectCIOPodfileCode.js.map +0 -1
  114. package/lib/module/ios/withAppDelegateModifications.js +0 -82
  115. package/lib/module/ios/withAppDelegateModifications.js.map +0 -1
  116. package/lib/module/ios/withNotificationsXcodeProject.js.map +0 -1
  117. package/lib/module/postInstallHelper.js +0 -18
  118. package/lib/module/postInstallHelper.js.map +0 -1
  119. package/lib/module/types/cio-types.js.map +0 -1
  120. package/lib/typescript/helpers/constants/ios.d.ts +0 -31
  121. package/src/helpers/constants/ios.ts +0 -93
  122. package/src/helpers/native-files/ios/Env.swift +0 -8
  123. package/src/helpers/native-files/ios/NotificationService.swift +0 -22
  124. package/src/helpers/utils/injectCIOPodfileCode.ts +0 -54
  125. package/src/postInstallHelper.js +0 -22
  126. /package/{lib → plugin/lib}/commonjs/android/withAndroidManifestUpdates.js +0 -0
  127. /package/{lib → plugin/lib}/commonjs/android/withAppGoogleServices.js +0 -0
  128. /package/{lib → plugin/lib}/commonjs/android/withGistMavenRepository.js +0 -0
  129. /package/{lib → plugin/lib}/commonjs/android/withGoogleServicesJSON.js +0 -0
  130. /package/{lib → plugin/lib}/commonjs/android/withProjectGoogleServices.js +0 -0
  131. /package/{lib → plugin/lib}/commonjs/helpers/constants/globals.d.js +0 -0
  132. /package/{lib → plugin/lib}/commonjs/helpers/native-files/ios/NotificationService-Info.plist +0 -0
  133. /package/{lib → plugin/lib}/commonjs/helpers/native-files/ios/NotificationService.h +0 -0
  134. /package/{lib → plugin/lib}/commonjs/helpers/native-files/ios/NotificationService.m +0 -0
  135. /package/{lib → plugin/lib}/commonjs/helpers/utils/fileManagement.js +0 -0
  136. /package/{lib → plugin/lib}/commonjs/ios/withCIOIos.js +0 -0
  137. /package/{lib → plugin/lib}/commonjs/ios/withXcodeProject.js +0 -0
  138. /package/{lib → plugin/lib}/commonjs/postInstall.js +0 -0
  139. /package/{lib → plugin/lib}/commonjs/types/cio-types.js +0 -0
  140. /package/{lib → plugin/lib}/module/android/withAndroidManifestUpdates.js +0 -0
  141. /package/{lib → plugin/lib}/module/android/withAppGoogleServices.js +0 -0
  142. /package/{lib → plugin/lib}/module/android/withGistMavenRepository.js +0 -0
  143. /package/{lib → plugin/lib}/module/android/withGoogleServicesJSON.js +0 -0
  144. /package/{lib → plugin/lib}/module/android/withProjectGoogleServices.js +0 -0
  145. /package/{lib → plugin/lib}/module/helpers/constants/android.js +0 -0
  146. /package/{lib → plugin/lib}/module/helpers/constants/globals.d.js +0 -0
  147. /package/{lib → plugin/lib}/module/helpers/native-files/ios/NotificationService-Info.plist +0 -0
  148. /package/{lib → plugin/lib}/module/helpers/native-files/ios/NotificationService.h +0 -0
  149. /package/{lib → plugin/lib}/module/helpers/native-files/ios/NotificationService.m +0 -0
  150. /package/{lib → plugin/lib}/module/helpers/utils/fileManagement.js +0 -0
  151. /package/{lib → plugin/lib}/module/index.js +0 -0
  152. /package/{lib → plugin/lib}/module/ios/withCIOIos.js +0 -0
  153. /package/{lib → plugin/lib}/module/ios/withXcodeProject.js +0 -0
  154. /package/{lib → plugin/lib}/module/postInstall.js +0 -0
  155. /package/{lib → plugin/lib}/module/types/cio-types.js +0 -0
  156. /package/{lib → plugin/lib}/typescript/android/withAndroidManifestUpdates.d.ts +0 -0
  157. /package/{lib → plugin/lib}/typescript/android/withAppGoogleServices.d.ts +0 -0
  158. /package/{lib → plugin/lib}/typescript/android/withCIOAndroid.d.ts +0 -0
  159. /package/{lib → plugin/lib}/typescript/android/withGistMavenRepository.d.ts +0 -0
  160. /package/{lib → plugin/lib}/typescript/android/withGoogleServicesJSON.d.ts +0 -0
  161. /package/{lib → plugin/lib}/typescript/android/withProjectGoogleServices.d.ts +0 -0
  162. /package/{lib → plugin/lib}/typescript/helpers/constants/android.d.ts +0 -0
  163. /package/{lib → plugin/lib}/typescript/helpers/utils/fileManagement.d.ts +0 -0
  164. /package/{lib → plugin/lib}/typescript/helpers/utils/injectCIOPodfileCode.d.ts +0 -0
  165. /package/{lib → plugin/lib}/typescript/index.d.ts +0 -0
  166. /package/{lib → plugin/lib}/typescript/ios/withAppDelegateModifications.d.ts +0 -0
  167. /package/{lib → plugin/lib}/typescript/ios/withCIOIos.d.ts +0 -0
  168. /package/{lib → plugin/lib}/typescript/ios/withNotificationsXcodeProject.d.ts +0 -0
  169. /package/{lib → plugin/lib}/typescript/ios/withXcodeProject.d.ts +0 -0
  170. /package/{src → plugin/src}/android/withAndroidManifestUpdates.ts +0 -0
  171. /package/{src → plugin/src}/android/withAppGoogleServices.ts +0 -0
  172. /package/{src → plugin/src}/android/withGistMavenRepository.ts +0 -0
  173. /package/{src → plugin/src}/android/withGoogleServicesJSON.ts +0 -0
  174. /package/{src → plugin/src}/android/withProjectGoogleServices.ts +0 -0
  175. /package/{src → plugin/src}/helpers/constants/android.ts +0 -0
  176. /package/{src → plugin/src}/helpers/constants/globals.d.ts +0 -0
  177. /package/{src → plugin/src}/helpers/native-files/ios/NotificationService-Info.plist +0 -0
  178. /package/{src → plugin/src}/helpers/native-files/ios/NotificationService.h +0 -0
  179. /package/{src → plugin/src}/helpers/native-files/ios/NotificationService.m +0 -0
  180. /package/{src → plugin/src}/helpers/utils/fileManagement.ts +0 -0
  181. /package/{src → plugin/src}/index.ts +0 -0
  182. /package/{src → plugin/src}/ios/withCIOIos.ts +0 -0
  183. /package/{src → plugin/src}/ios/withXcodeProject.ts +0 -0
  184. /package/{src → plugin/src}/postInstall.js +0 -0
@@ -0,0 +1,144 @@
1
+ const finder = require('find-package-json');
2
+ const path = require('path');
3
+ const resolveFrom = require('resolve-from');
4
+
5
+ const f = finder(__dirname);
6
+ let pluginPackageRoot = f.next().filename;
7
+ // This is the path to the root of the customerio-expo-plugin package
8
+ pluginPackageRoot = path.dirname(pluginPackageRoot);
9
+
10
+ export const LOCAL_PATH_TO_CIO_NSE_FILES = path.join(
11
+ pluginPackageRoot,
12
+ 'plugin/src/helpers/native-files/ios'
13
+ );
14
+
15
+ export function getRelativePathToRNSDK(iosPath: string) {
16
+ // Root path of the Expo project
17
+ const rootAppPath = path.dirname(iosPath);
18
+
19
+ // Path of the cio RN package.json file. Example: test-app/node_modules/customerio-reactnative/package.json
20
+ const pluginPackageJsonPath = resolveFrom.silent(rootAppPath, `customerio-reactnative/package.json`);
21
+
22
+ // Example: ../node_modules/customerio-reactnative
23
+ return path.relative(iosPath, path.dirname(pluginPackageJsonPath));
24
+ }
25
+
26
+ export const IOS_DEPLOYMENT_TARGET = '13.0';
27
+ export const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
28
+ export const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;
29
+ export const BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;
30
+ export const CIO_DIDFINISHLAUNCHINGMETHOD_REGEX =
31
+ /.*\[super(\s)application:application(\s)didFinishLaunchingWithOptions:launchOptions\];/;
32
+
33
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX =
34
+ /return \[super application:application didFailToRegisterForRemoteNotificationsWithError:error\];/;
35
+
36
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX =
37
+ /(- \(void\)application:\(UIApplication \*\)application didFailToRegisterForRemoteNotificationsWithError:\(NSError \*\)error(\s|\n)*?\{)(.|\n){2}.*\n\}/;
38
+
39
+ export const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX =
40
+ /return \[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken\];/;
41
+
42
+ export const CIO_APPDELEGATEDECLARATION_REGEX =
43
+ /@implementation AppDelegate(.|\n)/;
44
+
45
+ export const CIO_APPDELEGATEHEADER_REGEX =
46
+ /(@interface AppDelegate\s*:\s*EXAppDelegateWrapper\s*)(<([^>]+)>)?/;
47
+
48
+ export const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX =
49
+ /^\s*RCTBridge\s*\*\s*\w+\s*=\s*\[\s*self\.reactDelegate\s+createBridgeWithDelegate:self\s+launchOptions:launchOptions\s*\];\s*$/gm;
50
+
51
+ export const CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX =
52
+ /^\s*return\s\[\s*super\s*application:\s*application\s*didFinishLaunchingWithOptions\s*:\s*launchOptions\s*\];/gm;
53
+
54
+ export const CIO_DEEPLINK_COMMENT_REGEX =
55
+ /\sDeep link workaround for app killed state start/gm;
56
+ export const DEFAULT_BUNDLE_VERSION = '1';
57
+ export const DEFAULT_BUNDLE_SHORT_VERSION = '1.0';
58
+ export const CIO_TARGET_NAME = 'CustomerIOSDK';
59
+ export const CIO_NOTIFICATION_TARGET_NAME = 'NotificationService';
60
+
61
+ export const CIO_APPDELEGATEHEADER_IMPORT_SNIPPET = `#import <UserNotifications/UserNotifications.h>`;
62
+ export const CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET =
63
+ 'UNUserNotificationCenterDelegate';
64
+ export const CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = `
65
+ CIOAppPushNotificationsHandler* pnHandlerObj = [[CIOAppPushNotificationsHandler alloc] init];
66
+ `;
67
+ export const CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET = `
68
+ RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:modifiedLaunchOptions];
69
+ `;
70
+
71
+ export const CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET = `
72
+ return [super application:application didFinishLaunchingWithOptions:modifiedLaunchOptions];`;
73
+
74
+ export const CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = `
75
+ [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
76
+ [pnHandlerObj application:application error:error];
77
+ `;
78
+
79
+ export const CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `
80
+ [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
81
+ return [pnHandlerObj application:application deviceToken:deviceToken];
82
+ `;
83
+
84
+ export const CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `
85
+ // Register for push notifications
86
+ [pnHandlerObj registerPushNotification];
87
+ `;
88
+
89
+ export const CIO_INITIALIZECIOSDK_SNIPPET = `
90
+ [pnHandlerObj initializeCioSdk];
91
+
92
+ // Code to make the CIO SDK compatible with expo-notifications package.
93
+ //
94
+ // The CIO SDK and expo-notifications both need to handle when a push gets clicked. However, iOS only allows one click handler to be set per app.
95
+ // To get around this limitation, we set the CIO SDK as the click handler. The CIO SDK sets itself up so that when another SDK or host iOS app
96
+ // sets itself as the click handler, the CIO SDK will still be able to handle when the push gets clicked, even though it's not the designated
97
+ // click handler in iOS at runtime.
98
+ //
99
+ // This should work for most SDKs. However, expo-notifications is unique in it's implementation. It will not setup push click handling it if detects
100
+ // that another SDK or host iOS app has already set itself as the click handler:
101
+ // https://github.com/expo/expo/blob/1b29637bec0b9888e8bc8c310476293a3e2d9786/packages/expo-notifications/ios/EXNotifications/Notifications/EXNotificationCenterDelegate.m#L31-L37
102
+ // ...to get around this, we must manually set it as the click handler after the CIO SDK. That's what this code block does.
103
+ //
104
+ // Note: Initialize the native iOS SDK and setup SDK push click handling before running this code.
105
+ # if __has_include(<EXNotifications/EXNotificationCenterDelegate.h>)
106
+ // Creating a new instance, as the comments in expo-notifications suggests, does not work. With this code, if you send a CIO push to device and click on it,
107
+ // no push metrics reporting will occur.
108
+ // EXNotificationCenterDelegate *notificationCenterDelegate = [[EXNotificationCenterDelegate alloc] init];
109
+
110
+ // ...instead, get the singleton reference from Expo.
111
+ id<UNUserNotificationCenterDelegate> notificationCenterDelegate = (id<UNUserNotificationCenterDelegate>) [EXModuleRegistryProvider getSingletonModuleForClass:[EXNotificationCenterDelegate class]];
112
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
113
+ center.delegate = notificationCenterDelegate;
114
+ # endif
115
+ `;
116
+
117
+ export const CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET = `
118
+ // Deep link workaround for app killed state start
119
+ NSMutableDictionary *modifiedLaunchOptions = [NSMutableDictionary dictionaryWithDictionary:launchOptions];
120
+ if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
121
+ NSDictionary *pushContent = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
122
+ if (pushContent[@"CIO"] && pushContent[@"CIO"][@"push"] && pushContent[@"CIO"][@"push"][@"link"]) {
123
+ NSString *initialURL = pushContent[@"CIO"][@"push"][@"link"];
124
+ if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
125
+ modifiedLaunchOptions[UIApplicationLaunchOptionsURLKey] = [NSURL URLWithString:initialURL];
126
+ }
127
+ }
128
+ }
129
+ //Deep link workaround for app killed state ends
130
+ `;
131
+
132
+ export const CIO_REGISTER_PUSHNOTIFICATION_SNIPPET = `
133
+ @objc(registerPushNotification)
134
+ public func registerPushNotification() {
135
+
136
+ let center = UNUserNotificationCenter.current()
137
+ center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
138
+ if error == nil{
139
+ DispatchQueue.main.async {
140
+ UIApplication.shared.registerForRemoteNotifications()
141
+ }
142
+ }
143
+ }
144
+ }`;
@@ -0,0 +1,7 @@
1
+ import Foundation
2
+ import CioInternalCommon
3
+
4
+ class Env {
5
+ static var customerIOCdpApiKey: String = "{{CDP_API_KEY}}"
6
+ static var customerIORegion: Region = {{REGION}} // "us" or "eu"
7
+ }
@@ -0,0 +1,25 @@
1
+ import Foundation
2
+ import UserNotifications
3
+ import CioMessagingPushAPN
4
+
5
+ @objc
6
+ public class NotificationServiceCioManager : NSObject {
7
+
8
+ public override init() {}
9
+
10
+ @objc(didReceive:withContentHandler:)
11
+ public func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
12
+ MessagingPushAPN.initializeForExtension(
13
+ withConfig: MessagingPushConfigBuilder(cdpApiKey: Env.customerIOCdpApiKey)
14
+ .region(Env.customerIORegion)
15
+ .build()
16
+ )
17
+
18
+ MessagingPush.shared.didReceive(request, withContentHandler: contentHandler)
19
+ }
20
+
21
+ @objc(serviceExtensionTimeWillExpire)
22
+ public func serviceExtensionTimeWillExpire() {
23
+ MessagingPush.shared.serviceExtensionTimeWillExpire()
24
+ }
25
+ }
@@ -1,6 +1,5 @@
1
1
  import Foundation
2
2
  import CioMessagingPushAPN
3
- import CioTracking
4
3
  import UserNotifications
5
4
  import UIKit
6
5
 
@@ -11,6 +10,16 @@ public class CIOAppPushNotificationsHandler : NSObject {
11
10
 
12
11
  {{REGISTER_SNIPPET}}
13
12
 
13
+ @objc(initializeCioSdk)
14
+ public func initializeCioSdk() {
15
+ MessagingPushAPN.initialize(
16
+ withConfig: MessagingPushConfigBuilder()
17
+ .showPushAppInForeground({{SHOW_PUSH_APP_IN_FOREGROUND}})
18
+ .autoTrackPushEvents({{AUTO_TRACK_PUSH_EVENTS}})
19
+ .build()
20
+ )
21
+ }
22
+
14
23
  @objc(application:deviceToken:)
15
24
  public func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
16
25
  MessagingPush.shared.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
@@ -20,16 +29,4 @@ public class CIOAppPushNotificationsHandler : NSObject {
20
29
  public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
21
30
  MessagingPush.shared.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
22
31
  }
23
-
24
- @objc(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)
25
- public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
26
- let handled = MessagingPush.shared.userNotificationCenter(center, didReceive: response,
27
- withCompletionHandler: completionHandler)
28
-
29
- // If the Customer.io SDK does not handle the push, it's up to you to handle it and call the
30
- // completion handler. If the SDK did handle it, it called the completion handler for you.
31
- if !handled {
32
- completionHandler()
33
- }
34
- }
35
32
  }
@@ -22,6 +22,14 @@ export function injectCodeByMultiLineRegex(
22
22
  return fileContent.replace(lineRegex, `$&\n${snippet}`);
23
23
  }
24
24
 
25
+ export function injectCodeBeforeMultiLineRegex(
26
+ fileContent: string,
27
+ lineRegex: RegExp,
28
+ snippet: string
29
+ ) {
30
+ return fileContent.replace(lineRegex, `${snippet}\n$&`);
31
+ }
32
+
25
33
  export function replaceCodeByRegex(
26
34
  fileContent: string,
27
35
  lineRegex: RegExp,
@@ -30,6 +38,9 @@ export function replaceCodeByRegex(
30
38
  return fileContent.replace(lineRegex, snippet);
31
39
  }
32
40
 
41
+ export function matchRegexExists(fileContent: string, regex: RegExp) {
42
+ return regex.test(fileContent);
43
+ }
33
44
  export function injectCodeByMultiLineRegexAndReplaceLine(
34
45
  fileContent: string,
35
46
  lineRegex: RegExp,
@@ -50,5 +61,5 @@ export function injectCodeByLineNumber(
50
61
  content = [...lines.slice(0, index), snippet, ...lines.slice(index)];
51
62
  }
52
63
 
53
- return content;
64
+ return content.join('\n');
54
65
  }
@@ -0,0 +1,67 @@
1
+ import type { CustomerIOPluginOptionsIOS } from '../../types/cio-types';
2
+ import { getRelativePathToRNSDK } from '../constants/ios';
3
+ import { injectCodeByRegex } from './codeInjection';
4
+ import { FileManagement } from './fileManagement';
5
+
6
+ export async function injectCIOPodfileCode(iosPath: string) {
7
+ const blockStart = '# --- CustomerIO Host App START ---';
8
+ const blockEnd = '# --- CustomerIO Host App END ---';
9
+
10
+ const filename = `${iosPath}/Podfile`;
11
+ const podfile = await FileManagement.read(filename);
12
+ const matches = podfile.match(new RegExp(blockStart));
13
+
14
+ if (!matches) {
15
+ // We need to decide what line of code in the Podfile to insert our native code.
16
+ // The "post_install" line is always present in an Expo project Podfile so it's reliable.
17
+ // Find that line in the Podfile and then we will insert our code above that line.
18
+ const lineInPodfileToInjectSnippetBefore = /post_install do \|installer\|/;
19
+
20
+ const snippetToInjectInPodfile = `
21
+ ${blockStart}
22
+ pod 'customerio-reactnative/apn', :path => '${getRelativePathToRNSDK(
23
+ iosPath
24
+ )}'
25
+ ${blockEnd}
26
+ `.trim();
27
+
28
+ FileManagement.write(
29
+ filename,
30
+ injectCodeByRegex(
31
+ podfile,
32
+ lineInPodfileToInjectSnippetBefore,
33
+ snippetToInjectInPodfile
34
+ ).join('\n')
35
+ );
36
+ } else {
37
+ console.log('CustomerIO Podfile snippets already exists. Skipping...');
38
+ }
39
+ }
40
+
41
+ export async function injectCIONotificationPodfileCode(
42
+ iosPath: string,
43
+ useFrameworks: CustomerIOPluginOptionsIOS['useFrameworks']
44
+ ) {
45
+ const filename = `${iosPath}/Podfile`;
46
+ const podfile = await FileManagement.read(filename);
47
+
48
+ const blockStart = '# --- CustomerIO Notification START ---';
49
+ const blockEnd = '# --- CustomerIO Notification END ---';
50
+
51
+ const matches = podfile.match(new RegExp(blockStart));
52
+
53
+ if (!matches) {
54
+ const snippetToInjectInPodfile = `
55
+ ${blockStart}
56
+ target 'NotificationService' do
57
+ ${useFrameworks === 'static' ? 'use_frameworks! :linkage => :static' : ''}
58
+ pod 'customerio-reactnative-richpush/apn', :path => '${getRelativePathToRNSDK(
59
+ iosPath
60
+ )}'
61
+ end
62
+ ${blockEnd}
63
+ `.trim();
64
+
65
+ FileManagement.append(filename, snippetToInjectInPodfile);
66
+ }
67
+ }
@@ -0,0 +1,22 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * Reads the version of the plugin from its `package.json` and returns it as a string.
6
+ */
7
+ export const getPluginVersion = (): string => {
8
+ // Always resolves relative to the utility file's location
9
+ const packageJsonPath = path.resolve(__dirname, '../../../../../package.json');
10
+
11
+ if (!fs.existsSync(packageJsonPath)) {
12
+ throw new Error(`package.json not found at ${packageJsonPath}`);
13
+ }
14
+
15
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
16
+
17
+ if (!packageJson.version) {
18
+ throw new Error(`"version" field is missing in ${packageJsonPath}`);
19
+ }
20
+
21
+ return packageJson.version;
22
+ };
@@ -3,36 +3,35 @@ import { getAppDelegateHeaderFilePath } from '@expo/config-plugins/build/ios/Pat
3
3
 
4
4
  import {
5
5
  CIO_APPDELEGATEDECLARATION_REGEX,
6
+ CIO_APPDELEGATEHEADER_IMPORT_SNIPPET,
6
7
  CIO_APPDELEGATEHEADER_REGEX,
7
- CIO_APPDELEGATEHEADER_SNIPPET,
8
+ CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET,
8
9
  CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET,
9
- CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
10
+ CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET,
11
+ CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX,
10
12
  CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX,
11
13
  CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET,
12
14
  CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
13
- CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
14
15
  CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX,
15
16
  CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET,
17
+ CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX,
16
18
  CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET,
17
- CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
19
+ CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET,
20
+ CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET,
21
+ CIO_DEEPLINK_COMMENT_REGEX,
22
+ CIO_INITIALIZECIOSDK_SNIPPET,
18
23
  } from '../helpers/constants/ios';
19
24
  import {
25
+ injectCodeBeforeMultiLineRegex,
20
26
  injectCodeByLineNumber,
21
27
  injectCodeByMultiLineRegex,
22
28
  injectCodeByMultiLineRegexAndReplaceLine,
29
+ replaceCodeByRegex,
30
+ matchRegexExists,
23
31
  } from '../helpers/utils/codeInjection';
24
32
  import { FileManagement } from '../helpers/utils/fileManagement';
25
33
  import type { CustomerIOPluginOptionsIOS } from '../types/cio-types';
26
34
 
27
- const pushCodeSnippets = [
28
- CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
29
- CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
30
- ];
31
-
32
- const additionalMethodsForPushNotifications = `${pushCodeSnippets.join(
33
- '\n'
34
- )}\n`; // Join newlines and ensure a newline at the end.
35
-
36
35
  const addImport = (stringContents: string, appName: string) => {
37
36
  const importRegex = /^(#import .*)\n/gm;
38
37
  const addedImport = getImportSnippet(appName);
@@ -51,7 +50,7 @@ const addImport = (stringContents: string, appName: string) => {
51
50
  stringContents,
52
51
  endOfMatchIndex,
53
52
  addedImport
54
- ).join('\n');
53
+ );
55
54
 
56
55
  return stringContents;
57
56
  };
@@ -67,7 +66,7 @@ const addNotificationHandlerDeclaration = (stringContents: string) => {
67
66
  };
68
67
 
69
68
  const addNotificationConfiguration = (stringContents: string) => {
70
- stringContents = injectCodeByMultiLineRegex(
69
+ stringContents = injectCodeBeforeMultiLineRegex(
71
70
  stringContents,
72
71
  CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
73
72
  CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET
@@ -76,6 +75,29 @@ const addNotificationConfiguration = (stringContents: string) => {
76
75
  return stringContents;
77
76
  };
78
77
 
78
+ const addInitializeNativeCioSdk = (stringContents: string) => {
79
+ stringContents = injectCodeBeforeMultiLineRegex(
80
+ stringContents,
81
+ CIO_DIDFINISHLAUNCHINGMETHOD_REGEX,
82
+ CIO_INITIALIZECIOSDK_SNIPPET
83
+ );
84
+
85
+ return stringContents;
86
+ };
87
+
88
+ const addHandleDeeplinkInKilledStateConfiguration = (
89
+ stringContents: string,
90
+ regex: RegExp
91
+ ) => {
92
+ stringContents = injectCodeBeforeMultiLineRegex(
93
+ stringContents,
94
+ regex,
95
+ CIO_CONFIGUREDEEPLINK_KILLEDSTATE_SNIPPET
96
+ );
97
+
98
+ return stringContents;
99
+ };
100
+
79
101
  const addDidFailToRegisterForRemoteNotificationsWithError = (
80
102
  stringContents: string
81
103
  ) => {
@@ -100,26 +122,88 @@ const addDidRegisterForRemoteNotificationsWithDeviceToken = (
100
122
  return stringContents;
101
123
  };
102
124
 
103
- const addAdditionalMethodsForPushNotifications = (stringContents: string) => {
104
- stringContents = injectCodeByMultiLineRegex(
125
+ // Adds required import for Expo Notifications package in AppDelegate.
126
+ // Required to call functions from the package.
127
+ const addExpoNotificationsHeaderModification = (stringContents: string) => {
128
+ stringContents = injectCodeByLineNumber(
105
129
  stringContents,
106
- CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX,
107
- additionalMethodsForPushNotifications
130
+ 0,
131
+ `
132
+ #if __has_include(<EXNotifications/EXNotificationCenterDelegate.h>)
133
+ #import <EXNotifications/EXNotificationCenterDelegate.h>
134
+ #endif
135
+ `
108
136
  );
109
137
 
110
138
  return stringContents;
111
139
  };
112
140
 
113
141
  const addAppdelegateHeaderModification = (stringContents: string) => {
114
- stringContents = injectCodeByMultiLineRegexAndReplaceLine(
115
- stringContents,
142
+ // Add UNUserNotificationCenterDelegate if needed
143
+ stringContents = stringContents.replace(
116
144
  CIO_APPDELEGATEHEADER_REGEX,
117
- CIO_APPDELEGATEHEADER_SNIPPET
145
+ (match, interfaceDeclaration, _groupedDelegates, existingDelegates) => {
146
+ if (
147
+ existingDelegates &&
148
+ existingDelegates.includes(
149
+ CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET
150
+ )
151
+ ) {
152
+ // The AppDelegate declaration already includes UNUserNotificationCenterDelegate, so we don't need to modify it
153
+ return match;
154
+ } else if (existingDelegates) {
155
+ // Other delegates exist, append ours
156
+ return `${CIO_APPDELEGATEHEADER_IMPORT_SNIPPET}
157
+ ${interfaceDeclaration}<${existingDelegates}, ${CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET}>
158
+ `;
159
+ } else {
160
+ // No delegates exist, add ours
161
+ return `${CIO_APPDELEGATEHEADER_IMPORT_SNIPPET}
162
+ ${interfaceDeclaration.trim()} <${CIO_APPDELEGATEHEADER_USER_NOTIFICATION_CENTER_SNIPPET}>
163
+ `;
164
+ }
165
+ }
118
166
  );
119
167
 
120
168
  return stringContents;
121
169
  };
122
170
 
171
+ const addHandleDeeplinkInKilledState = (stringContents: string) => {
172
+ // Find if the deep link code snippet is already present
173
+ if (matchRegexExists(stringContents, CIO_DEEPLINK_COMMENT_REGEX)) {
174
+ return stringContents;
175
+ }
176
+
177
+ // Check if the app delegate is using RCTBridge or LaunchOptions
178
+ let snippet = undefined;
179
+ let regex = CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX;
180
+ if (
181
+ matchRegexExists(
182
+ stringContents,
183
+ CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX
184
+ )
185
+ ) {
186
+ snippet = CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_SNIPPET;
187
+ regex = CIO_RCTBRIDGE_DEEPLINK_MODIFIEDOPTIONS_REGEX;
188
+ } else if (
189
+ matchRegexExists(
190
+ stringContents,
191
+ CIO_LAUNCHOPTIONS_DEEPLINK_MODIFIEDOPTIONS_REGEX
192
+ )
193
+ ) {
194
+ snippet = CIO_LAUNCHOPTIONS_MODIFIEDOPTIONS_SNIPPET;
195
+ }
196
+ // Add code only if the app delegate is using RCTBridge or LaunchOptions
197
+ if (snippet !== undefined) {
198
+ stringContents = addHandleDeeplinkInKilledStateConfiguration(
199
+ stringContents,
200
+ regex
201
+ );
202
+ stringContents = replaceCodeByRegex(stringContents, regex, snippet);
203
+ }
204
+ return stringContents;
205
+ };
206
+
123
207
  export const withAppDelegateModifications: ConfigPlugin<
124
208
  CustomerIOPluginOptionsIOS
125
209
  > = (configOuter, props) => {
@@ -151,12 +235,23 @@ export const withAppDelegateModifications: ConfigPlugin<
151
235
  ) {
152
236
  stringContents = addNotificationConfiguration(stringContents);
153
237
  }
154
- stringContents = addAdditionalMethodsForPushNotifications(stringContents);
238
+
239
+ stringContents = addInitializeNativeCioSdk(stringContents);
240
+
241
+ if (
242
+ props.handleDeeplinkInKilledState !== undefined &&
243
+ props.handleDeeplinkInKilledState === true
244
+ ) {
245
+ stringContents = addHandleDeeplinkInKilledState(stringContents);
246
+ }
247
+
155
248
  stringContents =
156
249
  addDidFailToRegisterForRemoteNotificationsWithError(stringContents);
157
250
  stringContents =
158
251
  addDidRegisterForRemoteNotificationsWithDeviceToken(stringContents);
159
252
 
253
+ stringContents = addExpoNotificationsHeaderModification(stringContents);
254
+
160
255
  config.modResults.contents = stringContents;
161
256
  } else {
162
257
  console.log('Customerio AppDelegate changes already exist. Skipping...');