customerio-expo-plugin 0.0.1 → 0.0.2
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.
- package/build/helpers/.DS_Store +0 -0
- package/build/helpers/ios/.DS_Store +0 -0
- package/build/helpers/ios/CIONotificationService-Info.plist +31 -0
- package/build/helpers/ios/CIONotificationService.h +5 -0
- package/build/helpers/ios/CIONotificationService.m +30 -0
- package/build/helpers/ios/CIONotificationService.swift +21 -0
- package/build/helpers/ios/PushNotification.swift +56 -0
- package/build/src/android/withAppGoogleServices.js +12 -0
- package/build/src/android/withCIOAndroid.js +15 -0
- package/build/src/android/withGistMavenRepository.js +12 -0
- package/build/src/android/withGoogleServicesJSON.js +24 -0
- package/build/src/android/withProjectGoogleServices.js +12 -0
- package/build/src/helpers/constants/android.js +9 -0
- package/build/src/helpers/constants/ios.js +100 -0
- package/build/src/helpers/utils/codeInjection.js +30 -0
- package/build/src/helpers/utils/fileManagement.js +40 -0
- package/build/src/helpers/utils/injectCIOPodfileCode.js +37 -0
- package/build/src/ios/withAppDelegateModifications.js +77 -0
- package/build/src/ios/withAppDelegateXcodeProject.js +81 -0
- package/build/src/ios/withCIOIos.js +15 -0
- package/build/src/ios/withNotificationsXcodeProject.js +136 -0
- package/build/src/ios/withXcodeProject.js +22 -0
- package/build/src/types/cio-types.js +8 -0
- package/package.json +2 -2
|
Binary file
|
|
Binary file
|
|
@@ -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,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,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withAppGoogleServices = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const android_1 = require("../helpers/constants/android");
|
|
6
|
+
const withAppGoogleServices = (configOuter) => {
|
|
7
|
+
return (0, config_plugins_1.withAppBuildGradle)(configOuter, (props) => {
|
|
8
|
+
props.modResults.contents = props.modResults.contents.replace(android_1.CIO_APP_APPLY_REGEX, `$1\n${android_1.CIO_APP_GOOGLE_SNIPPET}`);
|
|
9
|
+
return props;
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.withAppGoogleServices = withAppGoogleServices;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withCIOAndroid = void 0;
|
|
4
|
+
const withAppGoogleServices_1 = require("./withAppGoogleServices");
|
|
5
|
+
const withGistMavenRepository_1 = require("./withGistMavenRepository");
|
|
6
|
+
const withGoogleServicesJSON_1 = require("./withGoogleServicesJSON");
|
|
7
|
+
const withProjectGoogleServices_1 = require("./withProjectGoogleServices");
|
|
8
|
+
function withCIOAndroid(config, props) {
|
|
9
|
+
config = (0, withGistMavenRepository_1.withGistMavenRepository)(config, props);
|
|
10
|
+
config = (0, withProjectGoogleServices_1.withProjectGoogleServices)(config, props);
|
|
11
|
+
config = (0, withAppGoogleServices_1.withAppGoogleServices)(config, props);
|
|
12
|
+
config = (0, withGoogleServicesJSON_1.withGoogleServicesJSON)(config, props);
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
exports.withCIOAndroid = withCIOAndroid;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withGistMavenRepository = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const android_1 = require("../helpers/constants/android");
|
|
6
|
+
const withGistMavenRepository = (configOuter) => {
|
|
7
|
+
return (0, config_plugins_1.withProjectBuildGradle)(configOuter, (props) => {
|
|
8
|
+
props.modResults.contents = props.modResults.contents.replace(android_1.CIO_PROJECT_ALLPROJECTS_REGEX, `$1\n${android_1.CIO_PROJECT_GIST_MAVEN_SNIPPET}`);
|
|
9
|
+
return props;
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.withGistMavenRepository = withGistMavenRepository;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withGoogleServicesJSON = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const withGoogleServicesJSON = (configOuter, cioProps) => {
|
|
7
|
+
return (0, config_plugins_1.withProjectBuildGradle)(configOuter, (props) => {
|
|
8
|
+
const options = {
|
|
9
|
+
androidPath: props.modRequest.platformProjectRoot,
|
|
10
|
+
googleServicesFilePath: cioProps === null || cioProps === void 0 ? void 0 : cioProps.googleServicesFilePath,
|
|
11
|
+
};
|
|
12
|
+
const { androidPath, googleServicesFilePath } = options;
|
|
13
|
+
if (googleServicesFilePath) {
|
|
14
|
+
try {
|
|
15
|
+
(0, fs_1.copyFileSync)(`${googleServicesFilePath}google-services.json`, `${androidPath}/app/google-services.json`);
|
|
16
|
+
}
|
|
17
|
+
catch (e) {
|
|
18
|
+
console.log('There was an error copying your google-services.json file.');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return props;
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
exports.withGoogleServicesJSON = withGoogleServicesJSON;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withProjectGoogleServices = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const android_1 = require("./../helpers/constants/android");
|
|
6
|
+
const withProjectGoogleServices = (configOuter) => {
|
|
7
|
+
return (0, config_plugins_1.withProjectBuildGradle)(configOuter, (props) => {
|
|
8
|
+
props.modResults.contents = props.modResults.contents.replace(android_1.CIO_PROJECT_BUILDSCRIPTS_REGEX, `$1\n${android_1.CIO_PROJECT_GOOGLE_SNIPPET}`);
|
|
9
|
+
return props;
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
exports.withProjectGoogleServices = withProjectGoogleServices;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CIO_PROJECT_GOOGLE_SNIPPET = exports.CIO_APP_GOOGLE_SNIPPET = exports.CIO_PROJECT_GIST_MAVEN_SNIPPET = exports.CIO_PROJECT_ALLPROJECTS_REGEX = exports.CIO_APP_APPLY_REGEX = exports.CIO_PROJECT_BUILDSCRIPTS_REGEX = void 0;
|
|
4
|
+
exports.CIO_PROJECT_BUILDSCRIPTS_REGEX = /(buildscript\s*\{(.|\n)*dependencies\s*\{)/;
|
|
5
|
+
exports.CIO_APP_APPLY_REGEX = /(apply plugin: "com.android.application")/;
|
|
6
|
+
exports.CIO_PROJECT_ALLPROJECTS_REGEX = /(allprojects\s*\{(.|\n)*repositories\s*\{)/;
|
|
7
|
+
exports.CIO_PROJECT_GIST_MAVEN_SNIPPET = ' maven { url "https://maven.gist.build" }';
|
|
8
|
+
exports.CIO_APP_GOOGLE_SNIPPET = 'apply plugin: "com.google.gms.google-services" // Google Services plugin';
|
|
9
|
+
exports.CIO_PROJECT_GOOGLE_SNIPPET = ' classpath "com.google.gms:google-services:4.3.13" // Google Services plugin';
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET = exports.CIO_PODFILE_POST_INSTALL_SNIPPET = exports.CIO_PODFILE_TARGET_NAMES_SNIPPET = exports.CIO_PODFILE_SNIPPET = exports.CIO_PODFILE_NOTIFICATION_SNIPPET = exports.CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET = exports.CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET = exports.CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = exports.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = exports.CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = exports.CIO_APPDELEGATEHEADER_SNIPPET = exports.CIO_NOTIFICATION_TARGET_NAME = exports.CIO_TARGET_NAME = exports.DEFAULT_BUNDLE_SHORT_VERSION = exports.DEFAULT_BUNDLE_VERSION = exports.CIO_APPDELEGATEHEADER_REGEX = exports.CIO_APPDELEGATEDECLARATION_REGEX = exports.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX = exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX = exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX = exports.CIO_DIDFINISHLAUNCHINGMETHOD_REGEX = exports.CIO_PODFILE_POST_INSTALL_REGEX = exports.BUNDLE_VERSION_TEMPLATE_REGEX = exports.BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = exports.CIO_PODFILE_NOTIFICATION_REGEX = exports.CIO_PODFILE_REGEX = exports.IOS_DEPLOYMENT_TARGET = void 0;
|
|
4
|
+
exports.IOS_DEPLOYMENT_TARGET = '13.0';
|
|
5
|
+
exports.CIO_PODFILE_REGEX = /pod 'RCT-Folly'/;
|
|
6
|
+
exports.CIO_PODFILE_NOTIFICATION_REGEX = /target 'CIONotificationService' do/;
|
|
7
|
+
exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
|
|
8
|
+
exports.BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;
|
|
9
|
+
exports.BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;
|
|
10
|
+
exports.CIO_PODFILE_POST_INSTALL_REGEX = /post_install do \|installer\|/;
|
|
11
|
+
exports.CIO_DIDFINISHLAUNCHINGMETHOD_REGEX = /(- \(BOOL\)application:\(UIApplication \*\)application didFinishLaunchingWithOptions:\(NSDictionary \*\)launchOptions(\s|\n)*?\{)((.|\n)*)\[super(\s)application:application(\s)didFinishLaunchingWithOptions:launchOptions\];/;
|
|
12
|
+
exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX = /return \[super application:application didFailToRegisterForRemoteNotificationsWithError:error\];/;
|
|
13
|
+
exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX = /(- \(void\)application:\(UIApplication \*\)application didFailToRegisterForRemoteNotificationsWithError:\(NSError \*\)error(\s|\n)*?\{)(.|\n){2}.*\n\}/;
|
|
14
|
+
exports.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX = /return \[super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken\];/;
|
|
15
|
+
exports.CIO_APPDELEGATEDECLARATION_REGEX = /@implementation AppDelegate(.|\n)/;
|
|
16
|
+
exports.CIO_APPDELEGATEHEADER_REGEX = /@interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate>/;
|
|
17
|
+
exports.DEFAULT_BUNDLE_VERSION = '1';
|
|
18
|
+
exports.DEFAULT_BUNDLE_SHORT_VERSION = '1.0';
|
|
19
|
+
exports.CIO_TARGET_NAME = 'CustomerIOSDK';
|
|
20
|
+
exports.CIO_NOTIFICATION_TARGET_NAME = 'CIONotificationService';
|
|
21
|
+
exports.CIO_APPDELEGATEHEADER_SNIPPET = `
|
|
22
|
+
#import <UserNotifications/UserNotifications.h>
|
|
23
|
+
|
|
24
|
+
@interface AppDelegate : EXAppDelegateWrapper <RCTBridgeDelegate, UNUserNotificationCenterDelegate>
|
|
25
|
+
`;
|
|
26
|
+
exports.CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET = `
|
|
27
|
+
CIOAppPushNotificationsHandler* pnHandlerObj = [[CIOAppPushNotificationsHandler alloc] init];
|
|
28
|
+
`;
|
|
29
|
+
exports.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET = `
|
|
30
|
+
[pnHandlerObj application:application error:error];
|
|
31
|
+
`;
|
|
32
|
+
exports.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET = `
|
|
33
|
+
return [pnHandlerObj application:application deviceToken:deviceToken];
|
|
34
|
+
`;
|
|
35
|
+
// Configure Customerio push notifications SDK by adding to application:didFinishLaunchingWithOptions: delegate method
|
|
36
|
+
// From Braze docs: https://www.customer.io/docs/sdk/react-native/push/#obj-c-push
|
|
37
|
+
exports.CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET = `
|
|
38
|
+
// Register for push notifications
|
|
39
|
+
[pnHandlerObj registerPushNotification:self];
|
|
40
|
+
`;
|
|
41
|
+
// Enable push handling - notification response
|
|
42
|
+
exports.CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET = `
|
|
43
|
+
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
|
|
44
|
+
[pnHandlerObj userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:completionHandler];
|
|
45
|
+
}`;
|
|
46
|
+
// Foreground push handling
|
|
47
|
+
exports.CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET = `
|
|
48
|
+
// show push when the app is in foreground
|
|
49
|
+
- (void)userNotificationCenter:(UNUserNotificationCenter* )center willPresentNotification:(UNNotification* )notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
|
|
50
|
+
completionHandler( UNNotificationPresentationOptionAlert + UNNotificationPresentationOptionSound);
|
|
51
|
+
}`;
|
|
52
|
+
exports.CIO_PODFILE_NOTIFICATION_SNIPPET = `
|
|
53
|
+
target '${exports.CIO_NOTIFICATION_TARGET_NAME}' do
|
|
54
|
+
pod 'CustomerIO/MessagingPushAPN', '~> 1.2.0-alpha.3'
|
|
55
|
+
end`;
|
|
56
|
+
exports.CIO_PODFILE_SNIPPET = `
|
|
57
|
+
pod 'RCT-Folly', :podspec => '../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec'
|
|
58
|
+
pod 'boost', :podspec => '../node_modules/react-native/third-party-podspecs/boost.podspec'
|
|
59
|
+
pod 'CustomerIO/MessagingPushAPN', '~> 1.2.0-alpha.3'`;
|
|
60
|
+
exports.CIO_PODFILE_TARGET_NAMES_SNIPPET = `
|
|
61
|
+
cio_target_names = [
|
|
62
|
+
'CustomerIOTracking',
|
|
63
|
+
'CustomerIOCommon',
|
|
64
|
+
'CustomerIOMessagingPushAPN',
|
|
65
|
+
'CustomerIOMessagingPush'
|
|
66
|
+
]`;
|
|
67
|
+
exports.CIO_PODFILE_POST_INSTALL_SNIPPET = `
|
|
68
|
+
installer.pods_project.targets.each do |target|
|
|
69
|
+
if cio_target_names.include? target.name
|
|
70
|
+
puts "Modifying target #{target.name}"
|
|
71
|
+
|
|
72
|
+
target.build_configurations.each do |config|
|
|
73
|
+
puts "Setting build config settings for #{target.name}"
|
|
74
|
+
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end`;
|
|
78
|
+
exports.CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET = `
|
|
79
|
+
cio_target_names = [
|
|
80
|
+
'CustomerIOTracking',
|
|
81
|
+
'CustomerIOCommon',
|
|
82
|
+
'CustomerIOMessagingPushAPN',
|
|
83
|
+
'CustomerIOMessagingPush'
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
post_install do |installer|
|
|
87
|
+
|
|
88
|
+
installer.pods_project.targets.each do |target|
|
|
89
|
+
if cio_target_names.include? target.name
|
|
90
|
+
puts "Modifying target #{target.name}"
|
|
91
|
+
|
|
92
|
+
target.build_configurations.each do |config|
|
|
93
|
+
puts "Setting build config settings for #{target.name}"
|
|
94
|
+
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] ||= 'NO'
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
react_native_post_install(installer)
|
|
99
|
+
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
|
100
|
+
end`;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.injectCodeByLineNumber = exports.injectCodeByMultiLineRegexAndReplaceLine = exports.injectCodeByMultiLineRegex = exports.injectCodeByRegex = void 0;
|
|
4
|
+
function injectCodeByRegex(fileContent, lineRegex, snippet) {
|
|
5
|
+
const lines = fileContent.split('\n');
|
|
6
|
+
const index = lines.findIndex((line) => lineRegex.test(line));
|
|
7
|
+
let content = lines;
|
|
8
|
+
if (index > -1) {
|
|
9
|
+
content = [...lines.slice(0, index), snippet, ...lines.slice(index)];
|
|
10
|
+
}
|
|
11
|
+
return content;
|
|
12
|
+
}
|
|
13
|
+
exports.injectCodeByRegex = injectCodeByRegex;
|
|
14
|
+
function injectCodeByMultiLineRegex(fileContent, lineRegex, snippet) {
|
|
15
|
+
return fileContent.replace(lineRegex, `$&\n${snippet}`);
|
|
16
|
+
}
|
|
17
|
+
exports.injectCodeByMultiLineRegex = injectCodeByMultiLineRegex;
|
|
18
|
+
function injectCodeByMultiLineRegexAndReplaceLine(fileContent, lineRegex, snippet) {
|
|
19
|
+
return fileContent.replace(lineRegex, `${snippet}`);
|
|
20
|
+
}
|
|
21
|
+
exports.injectCodeByMultiLineRegexAndReplaceLine = injectCodeByMultiLineRegexAndReplaceLine;
|
|
22
|
+
function injectCodeByLineNumber(fileContent, index, snippet) {
|
|
23
|
+
const lines = fileContent.split('\n');
|
|
24
|
+
let content = lines;
|
|
25
|
+
if (index > -1) {
|
|
26
|
+
content = [...lines.slice(0, index), snippet, ...lines.slice(index)];
|
|
27
|
+
}
|
|
28
|
+
return content;
|
|
29
|
+
}
|
|
30
|
+
exports.injectCodeByLineNumber = injectCodeByLineNumber;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileManagement = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
class FileManagement {
|
|
6
|
+
static async read(path) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
(0, fs_1.readFile)(path, 'utf8', (err, data) => {
|
|
9
|
+
if (err || !data) {
|
|
10
|
+
reject(err);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
resolve(data);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
static async write(path, contents) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
(0, fs_1.writeFile)(path, contents, 'utf8', (err) => {
|
|
20
|
+
if (err) {
|
|
21
|
+
reject(err);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
resolve();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
static async append(path, contents) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
(0, fs_1.appendFile)(path, contents, 'utf8', (err) => {
|
|
31
|
+
if (err) {
|
|
32
|
+
reject(err);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
resolve();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.FileManagement = FileManagement;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.injectCIONotificationPodfileCode = exports.injectCIOPodfileCode = void 0;
|
|
4
|
+
const ios_1 = require("../constants/ios");
|
|
5
|
+
const fileManagement_1 = require("./fileManagement");
|
|
6
|
+
async function injectCIOPodfileCode(iosPath) {
|
|
7
|
+
const filename = `${iosPath}/Podfile`;
|
|
8
|
+
const podfile = await fileManagement_1.FileManagement.read(filename);
|
|
9
|
+
const matches = podfile.match(ios_1.CIO_PODFILE_REGEX);
|
|
10
|
+
const lines = podfile.split('\n');
|
|
11
|
+
const index = lines.findIndex((line) => ios_1.CIO_PODFILE_POST_INSTALL_REGEX.test(line));
|
|
12
|
+
let content = lines;
|
|
13
|
+
if (index > -1) {
|
|
14
|
+
content = [
|
|
15
|
+
...lines.slice(0, index - 1),
|
|
16
|
+
!matches ? ios_1.CIO_PODFILE_SNIPPET : '',
|
|
17
|
+
ios_1.CIO_PODFILE_TARGET_NAMES_SNIPPET,
|
|
18
|
+
...lines.slice(index - 1, index + 1),
|
|
19
|
+
ios_1.CIO_PODFILE_POST_INSTALL_SNIPPET,
|
|
20
|
+
...lines.slice(index + 1),
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
content.push(ios_1.CIO_PODFILE_POST_INSTALL_FALLBACK_SNIPPET);
|
|
25
|
+
}
|
|
26
|
+
fileManagement_1.FileManagement.write(filename, content.join('\n'));
|
|
27
|
+
}
|
|
28
|
+
exports.injectCIOPodfileCode = injectCIOPodfileCode;
|
|
29
|
+
async function injectCIONotificationPodfileCode(iosPath) {
|
|
30
|
+
const filename = `${iosPath}/Podfile`;
|
|
31
|
+
const podfile = await fileManagement_1.FileManagement.read(filename);
|
|
32
|
+
const matches = podfile.match(ios_1.CIO_PODFILE_NOTIFICATION_REGEX);
|
|
33
|
+
if (!matches) {
|
|
34
|
+
fileManagement_1.FileManagement.append(filename, ios_1.CIO_PODFILE_NOTIFICATION_SNIPPET);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.injectCIONotificationPodfileCode = injectCIONotificationPodfileCode;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withAppDelegateModifications = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const Paths_1 = require("@expo/config-plugins/build/ios/Paths");
|
|
6
|
+
const ios_1 = require("../helpers/constants/ios");
|
|
7
|
+
const codeInjection_1 = require("../helpers/utils/codeInjection");
|
|
8
|
+
const fileManagement_1 = require("../helpers/utils/fileManagement");
|
|
9
|
+
const pushCodeSnippets = [
|
|
10
|
+
ios_1.CIO_DIDRECEIVENOTIFICATIONRESPONSEHANDLER_SNIPPET,
|
|
11
|
+
ios_1.CIO_WILLPRESENTNOTIFICATIONHANDLER_SNIPPET,
|
|
12
|
+
];
|
|
13
|
+
const additionalMethodsForPushNotifications = `${pushCodeSnippets.join('\n')}\n`; // Join w/ newlines and ensure a newline at the end.
|
|
14
|
+
const addImport = (stringContents) => {
|
|
15
|
+
const importRegex = /^(#import .*)\n/gm;
|
|
16
|
+
const addedImport = `
|
|
17
|
+
// Add swift bridge imports
|
|
18
|
+
#import <ExpoModulesCore-Swift.h>
|
|
19
|
+
#import <testiosapp-Swift.h>
|
|
20
|
+
`;
|
|
21
|
+
const match = stringContents.match(importRegex);
|
|
22
|
+
let endOfMatchIndex;
|
|
23
|
+
if (!match || match.index === undefined) {
|
|
24
|
+
// No imports found, just add to start of file:
|
|
25
|
+
endOfMatchIndex = 0;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// Add after first import:
|
|
29
|
+
endOfMatchIndex = match.index + match[0].length;
|
|
30
|
+
}
|
|
31
|
+
stringContents = (0, codeInjection_1.injectCodeByLineNumber)(stringContents, endOfMatchIndex, addedImport).join('\n');
|
|
32
|
+
return stringContents;
|
|
33
|
+
};
|
|
34
|
+
const addNotificationHandlerDeclaration = (stringContents) => {
|
|
35
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegex)(stringContents, ios_1.CIO_APPDELEGATEDECLARATION_REGEX, ios_1.CIO_PUSHNOTIFICATIONHANDLERDECLARATION_SNIPPET);
|
|
36
|
+
return stringContents;
|
|
37
|
+
};
|
|
38
|
+
const addNotificationConfiguration = (stringContents) => {
|
|
39
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegex)(stringContents, ios_1.CIO_DIDFINISHLAUNCHINGMETHOD_REGEX, ios_1.CIO_CONFIGURECIOSDKPUSHNOTIFICATION_SNIPPET);
|
|
40
|
+
return stringContents;
|
|
41
|
+
};
|
|
42
|
+
const addDidFailToRegisterForRemoteNotificationsWithError = (stringContents) => {
|
|
43
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegexAndReplaceLine)(stringContents, ios_1.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_REGEX, ios_1.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERROR_SNIPPET);
|
|
44
|
+
return stringContents;
|
|
45
|
+
};
|
|
46
|
+
const AddDidRegisterForRemoteNotificationsWithDeviceToken = (stringContents) => {
|
|
47
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegexAndReplaceLine)(stringContents, ios_1.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_REGEX, ios_1.CIO_DIDREGISTERFORREMOTENOTIFICATIONSWITHDEVICETOKEN_SNIPPET);
|
|
48
|
+
return stringContents;
|
|
49
|
+
};
|
|
50
|
+
const addAdditionalMethodsForPushNotifications = (stringContents) => {
|
|
51
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegex)(stringContents, ios_1.CIO_DIDFAILTOREGISTERFORREMOTENOTIFICATIONSWITHERRORFULL_REGEX, additionalMethodsForPushNotifications);
|
|
52
|
+
return stringContents;
|
|
53
|
+
};
|
|
54
|
+
const addAppdelegateHeaderModification = (stringContents) => {
|
|
55
|
+
stringContents = (0, codeInjection_1.injectCodeByMultiLineRegexAndReplaceLine)(stringContents, ios_1.CIO_APPDELEGATEHEADER_REGEX, ios_1.CIO_APPDELEGATEHEADER_SNIPPET);
|
|
56
|
+
return stringContents;
|
|
57
|
+
};
|
|
58
|
+
const withAppDelegateModifications = (configOuter) => {
|
|
59
|
+
return (0, config_plugins_1.withAppDelegate)(configOuter, async (config) => {
|
|
60
|
+
let stringContents = config.modResults.contents;
|
|
61
|
+
const headerPath = (0, Paths_1.getAppDelegateHeaderFilePath)(config.modRequest.projectRoot);
|
|
62
|
+
let headerContent = await fileManagement_1.FileManagement.read(headerPath);
|
|
63
|
+
headerContent = addAppdelegateHeaderModification(headerContent);
|
|
64
|
+
fileManagement_1.FileManagement.write(headerPath, headerContent);
|
|
65
|
+
stringContents = addImport(stringContents);
|
|
66
|
+
stringContents = addNotificationHandlerDeclaration(stringContents);
|
|
67
|
+
stringContents = addNotificationConfiguration(stringContents);
|
|
68
|
+
stringContents = addAdditionalMethodsForPushNotifications(stringContents);
|
|
69
|
+
stringContents =
|
|
70
|
+
addDidFailToRegisterForRemoteNotificationsWithError(stringContents);
|
|
71
|
+
stringContents =
|
|
72
|
+
AddDidRegisterForRemoteNotificationsWithDeviceToken(stringContents);
|
|
73
|
+
config.modResults.contents = stringContents;
|
|
74
|
+
return config;
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
exports.withAppDelegateModifications = withAppDelegateModifications;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withCioAppdelegateXcodeProject = void 0;
|
|
7
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const xcode_1 = __importDefault(require("xcode"));
|
|
10
|
+
// import { name as thisPackageName } from '../../package.json';
|
|
11
|
+
const ios_1 = require("../helpers/constants/ios");
|
|
12
|
+
// const LOCAL_PATH_TO_NSE_FILES = `node_modules/${thisPackageName}/build/${appName}`;
|
|
13
|
+
const addNotificationServiceExtensionFile = async (options) => {
|
|
14
|
+
const { iosPath, appName } = options;
|
|
15
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
16
|
+
const xcodeProject = xcode_1.default.project(projPath);
|
|
17
|
+
xcodeProject.parse(async function (err) {
|
|
18
|
+
if (err) {
|
|
19
|
+
throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
20
|
+
}
|
|
21
|
+
fs_1.default.mkdirSync(`${iosPath}/${appName}`, {
|
|
22
|
+
recursive: true,
|
|
23
|
+
});
|
|
24
|
+
const file = 'PushNotification.swift';
|
|
25
|
+
const getTargetFile = (filename) => `${iosPath}/${appName}/${filename}`;
|
|
26
|
+
const sourceDir = 'plugin/helpers/ios';
|
|
27
|
+
const targetFile = getTargetFile(file);
|
|
28
|
+
fs_1.default.copyFileSync(`${sourceDir}/${file}`, targetFile);
|
|
29
|
+
// Create new PBXGroup for the extension
|
|
30
|
+
const extGroup = xcodeProject.addPbxGroup([file], appName, appName);
|
|
31
|
+
// Add the new PBXGroup to the top level group. This makes the
|
|
32
|
+
// files / folder appear in the file explorer in Xcode.
|
|
33
|
+
const groups = xcodeProject.hash.project.objects['PBXGroup'];
|
|
34
|
+
Object.keys(groups).forEach((key) => {
|
|
35
|
+
if (groups[key].name === undefined) {
|
|
36
|
+
xcodeProject.addToPbxGroup(extGroup.uuid, key);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// WORK AROUND for codeProject.addTarget BUG
|
|
40
|
+
// Xcode projects don't contain these if there is only one target
|
|
41
|
+
// An upstream fix should be made to the code referenced in this link:
|
|
42
|
+
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
|
|
43
|
+
const projObjects = xcodeProject.hash.project.objects;
|
|
44
|
+
projObjects['PBXTargetDependency'] =
|
|
45
|
+
projObjects['PBXTargetDependency'] || {};
|
|
46
|
+
projObjects['PBXContainerItemProxy'] =
|
|
47
|
+
projObjects['PBXTargetDependency'] || {};
|
|
48
|
+
fs_1.default.writeFileSync(projPath, xcodeProject.writeSync());
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const withCioAppdelegateXcodeProject = (configOuter, props) => {
|
|
52
|
+
return (0, config_plugins_1.withXcodeProject)(configOuter, async (config) => {
|
|
53
|
+
const { modRequest, ios, version: bundleShortVersion } = config;
|
|
54
|
+
const { appleTeamId, iosDeploymentTarget } = props;
|
|
55
|
+
if (ios === undefined)
|
|
56
|
+
throw new Error('Adding NotificationServiceExtension failed: ios config missing from app.config.js.');
|
|
57
|
+
const { projectName, platformProjectRoot } = modRequest;
|
|
58
|
+
const { bundleIdentifier, buildNumber } = ios;
|
|
59
|
+
if (bundleShortVersion === undefined) {
|
|
60
|
+
throw new Error('Adding NotificationServiceExtension failed: version missing from app.config.js');
|
|
61
|
+
}
|
|
62
|
+
if (bundleIdentifier === undefined) {
|
|
63
|
+
throw new Error('Adding NotificationServiceExtension failed: ios.bundleIdentifier missing from app.config.js');
|
|
64
|
+
}
|
|
65
|
+
if (projectName === undefined) {
|
|
66
|
+
throw new Error('Adding NotificationServiceExtension failed: name missing from app.config.js');
|
|
67
|
+
}
|
|
68
|
+
const options = {
|
|
69
|
+
appleTeamId,
|
|
70
|
+
bundleIdentifier,
|
|
71
|
+
bundleShortVersion,
|
|
72
|
+
bundleVersion: buildNumber !== null && buildNumber !== void 0 ? buildNumber : ios_1.DEFAULT_BUNDLE_VERSION,
|
|
73
|
+
iosPath: platformProjectRoot,
|
|
74
|
+
appName: projectName,
|
|
75
|
+
iosDeploymentTarget,
|
|
76
|
+
};
|
|
77
|
+
await addNotificationServiceExtensionFile(options);
|
|
78
|
+
return config;
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
exports.withCioAppdelegateXcodeProject = withCioAppdelegateXcodeProject;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withCIOIos = void 0;
|
|
4
|
+
const withAppDelegateModifications_1 = require("./withAppDelegateModifications");
|
|
5
|
+
const withAppDelegateXcodeProject_1 = require("./withAppDelegateXcodeProject");
|
|
6
|
+
const withNotificationsXcodeProject_1 = require("./withNotificationsXcodeProject");
|
|
7
|
+
const withXcodeProject_1 = require("./withXcodeProject");
|
|
8
|
+
function withCIOIos(config, props) {
|
|
9
|
+
config = (0, withNotificationsXcodeProject_1.withCioNotificationsXcodeProject)(config, props);
|
|
10
|
+
config = (0, withAppDelegateModifications_1.withAppDelegateModifications)(config, props);
|
|
11
|
+
config = (0, withXcodeProject_1.withCioXcodeProject)(config, props);
|
|
12
|
+
config = (0, withAppDelegateXcodeProject_1.withCioAppdelegateXcodeProject)(config, props);
|
|
13
|
+
return config;
|
|
14
|
+
}
|
|
15
|
+
exports.withCIOIos = withCIOIos;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.withCioNotificationsXcodeProject = void 0;
|
|
7
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const xcode_1 = __importDefault(require("xcode"));
|
|
10
|
+
// import { name as thisPackageName } from '../../package.json';
|
|
11
|
+
const ios_1 = require("../helpers/constants/ios");
|
|
12
|
+
const injectCIOPodfileCode_1 = require("../helpers/utils/injectCIOPodfileCode");
|
|
13
|
+
const PLIST_FILENAME = `${ios_1.CIO_NOTIFICATION_TARGET_NAME}-Info.plist`;
|
|
14
|
+
// const LOCAL_PATH_TO_NSE_FILES = `node_modules/${thisPackageName}/build/${CIO_NOTIFICATION_TARGET_NAME}`;
|
|
15
|
+
const TARGETED_DEVICE_FAMILY = `"1,2"`;
|
|
16
|
+
const addNotificationServiceExtension = async (options) => {
|
|
17
|
+
const { appleTeamId, bundleIdentifier, bundleShortVersion, bundleVersion, iosPath, appName, iosDeploymentTarget, } = options;
|
|
18
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
19
|
+
const xcodeProject = xcode_1.default.project(projPath);
|
|
20
|
+
xcodeProject.parse(async function (err) {
|
|
21
|
+
if (err) {
|
|
22
|
+
throw new Error(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
23
|
+
}
|
|
24
|
+
await (0, injectCIOPodfileCode_1.injectCIONotificationPodfileCode)(iosPath);
|
|
25
|
+
fs_1.default.mkdirSync(`${iosPath}/${ios_1.CIO_NOTIFICATION_TARGET_NAME}`, {
|
|
26
|
+
recursive: true,
|
|
27
|
+
});
|
|
28
|
+
const files = [
|
|
29
|
+
PLIST_FILENAME,
|
|
30
|
+
'CIONotificationService.h',
|
|
31
|
+
'CIONotificationService.swift',
|
|
32
|
+
'CIONotificationService.m',
|
|
33
|
+
];
|
|
34
|
+
const getTargetFile = (filename) => `${iosPath}/${ios_1.CIO_NOTIFICATION_TARGET_NAME}/${filename}`;
|
|
35
|
+
const sourceDir = 'plugin/helpers/ios';
|
|
36
|
+
files.forEach((filename) => {
|
|
37
|
+
const targetFile = getTargetFile(filename);
|
|
38
|
+
fs_1.default.copyFileSync(`${sourceDir}/${filename}`, targetFile);
|
|
39
|
+
});
|
|
40
|
+
/* MODIFY COPIED EXTENSION FILES */
|
|
41
|
+
const infoPlistTargetFile = getTargetFile(PLIST_FILENAME);
|
|
42
|
+
updateNseInfoPlist({
|
|
43
|
+
bundleVersion,
|
|
44
|
+
bundleShortVersion,
|
|
45
|
+
infoPlistTargetFile,
|
|
46
|
+
});
|
|
47
|
+
// Create new PBXGroup for the extension
|
|
48
|
+
const extGroup = xcodeProject.addPbxGroup(files, ios_1.CIO_NOTIFICATION_TARGET_NAME, ios_1.CIO_NOTIFICATION_TARGET_NAME);
|
|
49
|
+
// Add the new PBXGroup to the top level group. This makes the
|
|
50
|
+
// files / folder appear in the file explorer in Xcode.
|
|
51
|
+
const groups = xcodeProject.hash.project.objects['PBXGroup'];
|
|
52
|
+
Object.keys(groups).forEach((key) => {
|
|
53
|
+
if (groups[key].name === undefined) {
|
|
54
|
+
xcodeProject.addToPbxGroup(extGroup.uuid, key);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
// WORK AROUND for codeProject.addTarget BUG
|
|
58
|
+
// Xcode projects don't contain these if there is only one target
|
|
59
|
+
// An upstream fix should be made to the code referenced in this link:
|
|
60
|
+
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
|
|
61
|
+
const projObjects = xcodeProject.hash.project.objects;
|
|
62
|
+
projObjects['PBXTargetDependency'] =
|
|
63
|
+
projObjects['PBXTargetDependency'] || {};
|
|
64
|
+
projObjects['PBXContainerItemProxy'] =
|
|
65
|
+
projObjects['PBXTargetDependency'] || {};
|
|
66
|
+
if (xcodeProject.pbxTargetByName(ios_1.CIO_NOTIFICATION_TARGET_NAME)) {
|
|
67
|
+
console.warn(`${ios_1.CIO_NOTIFICATION_TARGET_NAME} already exists in project. Skipping...`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// Add the NSE target
|
|
71
|
+
// This also adds PBXTargetDependency and PBXContainerItemProxy
|
|
72
|
+
const nseTarget = xcodeProject.addTarget(ios_1.CIO_NOTIFICATION_TARGET_NAME, 'app_extension', ios_1.CIO_NOTIFICATION_TARGET_NAME, `${bundleIdentifier}.richpush`);
|
|
73
|
+
// Add build phases to the new target
|
|
74
|
+
xcodeProject.addBuildPhase(['CIONotificationService.m', 'CIONotificationService.swift'], 'PBXSourcesBuildPhase', 'Sources', nseTarget.uuid);
|
|
75
|
+
xcodeProject.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', nseTarget.uuid);
|
|
76
|
+
xcodeProject.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', nseTarget.uuid);
|
|
77
|
+
// Edit the Deployment info of the target
|
|
78
|
+
const configurations = xcodeProject.pbxXCBuildConfigurationSection();
|
|
79
|
+
for (const key in configurations) {
|
|
80
|
+
if (typeof configurations[key].buildSettings !== 'undefined' &&
|
|
81
|
+
configurations[key].buildSettings.PRODUCT_NAME ===
|
|
82
|
+
`"${ios_1.CIO_NOTIFICATION_TARGET_NAME}"`) {
|
|
83
|
+
const buildSettingsObj = configurations[key].buildSettings;
|
|
84
|
+
buildSettingsObj.DEVELOPMENT_TEAM = appleTeamId;
|
|
85
|
+
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET =
|
|
86
|
+
iosDeploymentTarget !== null && iosDeploymentTarget !== void 0 ? iosDeploymentTarget : '13.0';
|
|
87
|
+
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
|
|
88
|
+
buildSettingsObj.CODE_SIGN_STYLE = 'Automatic';
|
|
89
|
+
buildSettingsObj.SWIFT_VERSION = 4.2;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Add development team to the target & the main
|
|
93
|
+
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId, nseTarget);
|
|
94
|
+
xcodeProject.addTargetAttribute('DevelopmentTeam', appleTeamId);
|
|
95
|
+
fs_1.default.writeFileSync(projPath, xcodeProject.writeSync());
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const withCioNotificationsXcodeProject = (configOuter, props) => {
|
|
99
|
+
return (0, config_plugins_1.withXcodeProject)(configOuter, async (config) => {
|
|
100
|
+
const { modRequest, ios, version: bundleShortVersion } = config;
|
|
101
|
+
const { appleTeamId, iosDeploymentTarget } = props;
|
|
102
|
+
if (ios === undefined)
|
|
103
|
+
throw new Error('Adding NotificationServiceExtension failed: ios config missing from app.config.js.');
|
|
104
|
+
const { projectName, platformProjectRoot } = modRequest;
|
|
105
|
+
const { bundleIdentifier, buildNumber } = ios;
|
|
106
|
+
if (bundleShortVersion === undefined) {
|
|
107
|
+
throw new Error('Adding NotificationServiceExtension failed: version missing from app.config.js');
|
|
108
|
+
}
|
|
109
|
+
if (bundleIdentifier === undefined) {
|
|
110
|
+
throw new Error('Adding NotificationServiceExtension failed: ios.bundleIdentifier missing from app.config.js');
|
|
111
|
+
}
|
|
112
|
+
if (projectName === undefined) {
|
|
113
|
+
throw new Error('Adding NotificationServiceExtension failed: name missing from app.config.js');
|
|
114
|
+
}
|
|
115
|
+
const options = {
|
|
116
|
+
appleTeamId,
|
|
117
|
+
bundleIdentifier,
|
|
118
|
+
bundleShortVersion,
|
|
119
|
+
bundleVersion: buildNumber !== null && buildNumber !== void 0 ? buildNumber : ios_1.DEFAULT_BUNDLE_VERSION,
|
|
120
|
+
iosPath: platformProjectRoot,
|
|
121
|
+
appName: projectName,
|
|
122
|
+
iosDeploymentTarget,
|
|
123
|
+
};
|
|
124
|
+
await addNotificationServiceExtension(options);
|
|
125
|
+
return config;
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
exports.withCioNotificationsXcodeProject = withCioNotificationsXcodeProject;
|
|
129
|
+
const updateNseInfoPlist = ({ bundleVersion, bundleShortVersion, infoPlistTargetFile, }) => {
|
|
130
|
+
const BUNDLE_SHORT_VERSION_RE = /\{\{BUNDLE_SHORT_VERSION\}\}/;
|
|
131
|
+
const BUNDLE_VERSION_RE = /\{\{BUNDLE_VERSION\}\}/;
|
|
132
|
+
let plistFileString = fs_1.default.readFileSync(infoPlistTargetFile, 'utf-8');
|
|
133
|
+
plistFileString = plistFileString.replace(BUNDLE_VERSION_RE, bundleVersion);
|
|
134
|
+
plistFileString = plistFileString.replace(BUNDLE_SHORT_VERSION_RE, bundleShortVersion);
|
|
135
|
+
fs_1.default.writeFileSync(infoPlistTargetFile, plistFileString);
|
|
136
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withCioXcodeProject = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const injectCIOPodfileCode_1 = require("../helpers/utils/injectCIOPodfileCode");
|
|
6
|
+
const withCioXcodeProject = (config, cioProps) => {
|
|
7
|
+
return (0, config_plugins_1.withXcodeProject)(config, async (props) => {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
const options = {
|
|
10
|
+
iosPath: props.modRequest.platformProjectRoot,
|
|
11
|
+
bundleIdentifier: (_a = props.ios) === null || _a === void 0 ? void 0 : _a.bundleIdentifier,
|
|
12
|
+
devTeam: cioProps === null || cioProps === void 0 ? void 0 : cioProps.devTeam,
|
|
13
|
+
bundleVersion: (_b = props.ios) === null || _b === void 0 ? void 0 : _b.buildNumber,
|
|
14
|
+
bundleShortVersion: props === null || props === void 0 ? void 0 : props.version,
|
|
15
|
+
iosDeploymentTarget: cioProps === null || cioProps === void 0 ? void 0 : cioProps.iosDeploymentTarget,
|
|
16
|
+
};
|
|
17
|
+
const { iosPath } = options;
|
|
18
|
+
await (0, injectCIOPodfileCode_1.injectCIOPodfileCode)(iosPath);
|
|
19
|
+
return props;
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
exports.withCioXcodeProject = withCioXcodeProject;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "customerio-expo-plugin",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Expo config plugin for the Customer IO React Native SDK",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"files": [
|
|
9
|
-
"
|
|
9
|
+
"build/**/*"
|
|
10
10
|
],
|
|
11
11
|
"scripts": {
|
|
12
12
|
"copy-native-files": "cp -r src/helpers/native-files build/helpers/",
|