onesignal-expo-plugin 1.0.0-beta7 → 1.0.0-beta8
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/README.md +33 -7
- package/build/onesignal/withOneSignalIos.js +102 -3
- package/build/support/ReaderManager.js +40 -0
- package/build/support/iosConstants.js +11 -0
- package/build/support/serviceExtensionFiles/NotificationService.h +8 -0
- package/build/support/serviceExtensionFiles/NotificationService.m +29 -0
- package/build/support/serviceExtensionFiles/OneSignalNotificationServiceExtension-Info.plist +31 -0
- package/build/support/serviceExtensionFiles/OneSignalNotificationServiceExtension.entitlements +10 -0
- package/build/support/updateNSEEntitlements.js +20 -0
- package/build/support/updatePodfile.js +24 -0
- package/build/testRuniOS.js +14 -0
- package/onesignal/withOneSignal.ts +1 -0
- package/onesignal/withOneSignalIos.ts +144 -3
- package/package.json +4 -3
- package/support/ReaderManager.ts +18 -0
- package/support/iosConstants.ts +11 -0
- package/support/serviceExtensionFiles/NotificationService.h +8 -0
- package/support/serviceExtensionFiles/NotificationService.m +29 -0
- package/support/serviceExtensionFiles/OneSignalNotificationServiceExtension-Info.plist +31 -0
- package/support/serviceExtensionFiles/OneSignalNotificationServiceExtension.entitlements +10 -0
- package/support/updateNSEEntitlements.ts +16 -0
- package/support/updatePodfile.ts +18 -0
- package/testRuniOS.ts +20 -0
- package/types/xcode.d.ts +8 -0
- package/build/examples/RNOneSignalExpoExample/App.js +0 -25
- package/build/examples/RNOneSignalExpoExample/integrations/OneSignal/OneSignal.js +0 -33
- package/build/examples/RNOneSignalExpoExample/integrations/OneSignal/index.js +0 -13
- package/build/examples/my-app/App.js +0 -23
package/README.md
CHANGED
|
@@ -7,9 +7,6 @@
|
|
|
7
7
|
<a href="https://github.com/OneSignal/onesignal-expo-plugin/graphs/commit-activity" target="_blank">
|
|
8
8
|
<img alt="Maintenance" src="https://img.shields.io/badge/Maintained%3F-yes-green.svg" />
|
|
9
9
|
</a>
|
|
10
|
-
<a href="https://github.com/OneSignal/onesignal-expo-plugin/blob/main/LICENSE" target="_blank">
|
|
11
|
-
<img alt="License: MIT" src="https://img.shields.io/github/license/OneSignal/onesignal-expo-plugin" />
|
|
12
|
-
</a>
|
|
13
10
|
<a href="https://twitter.com/onesignal" target="_blank">
|
|
14
11
|
<img alt="Twitter: onesignal" src="https://img.shields.io/twitter/follow/onesignal.svg?style=social" />
|
|
15
12
|
</a>
|
|
@@ -17,10 +14,19 @@
|
|
|
17
14
|
|
|
18
15
|
> The OneSignal Expo plugin allows you to use OneSignal without leaving the managed workflow. Developed in collaboration with SweetGreen.
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
* 🏠 [Homepage](https://github.com/OneSignal/onesignal-expo-plugin#readme)
|
|
18
|
+
* 🖤 [npm](https://www.npmjs.com/package/onesignal-expo-plugin)
|
|
22
19
|
|
|
23
20
|
## 🚧 In Beta 🚧
|
|
21
|
+
## Overview
|
|
22
|
+
This plugin is an [Expo Config Plugin](https://docs.expo.dev/guides/config-plugins/). It extends the Expo config to allow customizing the prebuild phase of managed workflow builds (no need to eject to a bare workflow). For the purposes of OneSignal integration, the plugin facilitates automatically generating/configuring the necessary native code files needed to get the [OneSignal React-Native SDK](https://github.com/OneSignal/react-native-onesignal) to work. You can think of adding a plugin as adding custom native code.
|
|
23
|
+
|
|
24
|
+
## Supported environments:
|
|
25
|
+
* [The Expo run commands](https://docs.expo.dev/workflow/customizing/) (`expo run:[android|ios]`)
|
|
26
|
+
* [Custom clients](https://blog.expo.dev/introducing-custom-development-clients-5a2c79a9ddf8)
|
|
27
|
+
* [EAS Build](https://docs.expo.dev/build/introduction/)
|
|
28
|
+
|
|
29
|
+
---
|
|
24
30
|
|
|
25
31
|
## Install
|
|
26
32
|
|
|
@@ -39,7 +45,8 @@ Add the plugin to the [plugin array](https://docs.expo.dev/versions/latest/confi
|
|
|
39
45
|
[
|
|
40
46
|
"onesignal-expo-plugin",
|
|
41
47
|
{
|
|
42
|
-
"mode": "development"
|
|
48
|
+
"mode": "development",
|
|
49
|
+
"devTeam": "91SW8A37CR"
|
|
43
50
|
}
|
|
44
51
|
]
|
|
45
52
|
]
|
|
@@ -56,7 +63,8 @@ export default {
|
|
|
56
63
|
[
|
|
57
64
|
"onesignal-expo-plugin",
|
|
58
65
|
{
|
|
59
|
-
mode: process.env.NODE_ENV || "development"
|
|
66
|
+
mode: process.env.NODE_ENV || "development",
|
|
67
|
+
devTeam: "91SW8A37CR"
|
|
60
68
|
}
|
|
61
69
|
]
|
|
62
70
|
]
|
|
@@ -67,6 +75,7 @@ export default {
|
|
|
67
75
|
* `mode`: used to configure [APNs environment](https://developer.apple.com/documentation/bundleresources/entitlements/aps-environment) entitlement.
|
|
68
76
|
- `"development"`
|
|
69
77
|
- `"production"`
|
|
78
|
+
* `devTeam`: *optional* - used to configure Apple Team ID. You can find your Apple Team ID by running `expo credentials:manager`.
|
|
70
79
|
|
|
71
80
|
### OneSignal App ID
|
|
72
81
|
Add your OneSignal App ID to your [Expo constants via the `extra` param](https://docs.expo.dev/versions/latest/config/app/):
|
|
@@ -88,6 +97,23 @@ import Constants from "expo-constants";
|
|
|
88
97
|
OneSignal.setAppId(Constants.manifest.extra.oneSignalAppId);
|
|
89
98
|
```
|
|
90
99
|
|
|
100
|
+
Alternatively, pass the app ID directly to the function:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
OneSignal.setAppId("YOUR-ONESIGNAL-APP-ID");
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Run
|
|
107
|
+
```sh
|
|
108
|
+
$ expo prebuild
|
|
109
|
+
|
|
110
|
+
# Build your native iOS project
|
|
111
|
+
$ expo run:ios
|
|
112
|
+
|
|
113
|
+
# Build your native Android project
|
|
114
|
+
$ expo run:android
|
|
115
|
+
```
|
|
116
|
+
|
|
91
117
|
---
|
|
92
118
|
|
|
93
119
|
## 🤝 Contributing
|
|
@@ -3,17 +3,31 @@
|
|
|
3
3
|
* Expo config plugin for One Signal (iOS)
|
|
4
4
|
* @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
|
|
5
5
|
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
6
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.withOneSignalIos = void 0;
|
|
10
|
+
exports.xcodeProjectAddNse = exports.withOneSignalIos = void 0;
|
|
8
11
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const xcode_1 = __importDefault(require("xcode"));
|
|
14
|
+
const iosConstants_1 = require("../support/iosConstants");
|
|
15
|
+
const updatePodfile_1 = require("../support/updatePodfile");
|
|
16
|
+
const updateNSEEntitlements_1 = require("../support/updateNSEEntitlements");
|
|
9
17
|
// ---------- ---------- ---------- ----------
|
|
10
18
|
/**
|
|
11
19
|
* Add 'app-environment' record with current environment to '<project-name>.entitlements' file
|
|
12
20
|
* @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
|
|
13
21
|
*/
|
|
14
|
-
const withAppEnvironment = (config,
|
|
22
|
+
const withAppEnvironment = (config, onesignalProps) => {
|
|
15
23
|
return (0, config_plugins_1.withEntitlementsPlist)(config, (newConfig) => {
|
|
16
|
-
|
|
24
|
+
if ((onesignalProps === null || onesignalProps === void 0 ? void 0 : onesignalProps.mode) == null) {
|
|
25
|
+
throw new Error(`
|
|
26
|
+
Missing required "mode" key in your app.json or app.config.js file for "onesignal-expo-plugin".
|
|
27
|
+
"mode" can be either "development" or "production".
|
|
28
|
+
Please see onesignal-expo-plugin's README.md for more details.`);
|
|
29
|
+
}
|
|
30
|
+
newConfig.modResults["aps-environment"] = onesignalProps.mode;
|
|
17
31
|
return newConfig;
|
|
18
32
|
});
|
|
19
33
|
};
|
|
@@ -50,11 +64,96 @@ const withAppGroupPermissions = (config) => {
|
|
|
50
64
|
return newConfig;
|
|
51
65
|
});
|
|
52
66
|
};
|
|
67
|
+
const withOneSignalNSE = (config, onesignalProps) => {
|
|
68
|
+
return (0, config_plugins_1.withXcodeProject)(config, async (props) => {
|
|
69
|
+
var _a;
|
|
70
|
+
xcodeProjectAddNse(props.modRequest.projectName || "", props.modRequest.platformProjectRoot, ((_a = props.ios) === null || _a === void 0 ? void 0 : _a.bundleIdentifier) || "", onesignalProps === null || onesignalProps === void 0 ? void 0 : onesignalProps.devTeam, "node_modules/onesignal-expo-plugin/build/support/serviceExtensionFiles/");
|
|
71
|
+
return props;
|
|
72
|
+
});
|
|
73
|
+
};
|
|
53
74
|
// ---------- ---------- ---------- ----------
|
|
54
75
|
const withOneSignalIos = (config, props) => {
|
|
55
76
|
withAppEnvironment(config, props);
|
|
56
77
|
withRemoteNotificationsPermissions(config, props);
|
|
57
78
|
withAppGroupPermissions(config, props);
|
|
79
|
+
withOneSignalNSE(config, props);
|
|
58
80
|
return config;
|
|
59
81
|
};
|
|
60
82
|
exports.withOneSignalIos = withOneSignalIos;
|
|
83
|
+
function xcodeProjectAddNse(appName, iosPath, bundleIdentifier, devTeam, sourceDir) {
|
|
84
|
+
(0, updatePodfile_1.updatePodfile)(iosPath);
|
|
85
|
+
(0, updateNSEEntitlements_1.updateNSEEntitlements)(`group.${bundleIdentifier}.onesignal`);
|
|
86
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
87
|
+
const targetName = "OneSignalNotificationServiceExtension";
|
|
88
|
+
const extFiles = [
|
|
89
|
+
"NotificationService.h",
|
|
90
|
+
"NotificationService.m",
|
|
91
|
+
`${targetName}.entitlements`,
|
|
92
|
+
`${targetName}-Info.plist`
|
|
93
|
+
];
|
|
94
|
+
const xcodeProject = xcode_1.default.project(projPath);
|
|
95
|
+
xcodeProject.parse(function (err) {
|
|
96
|
+
if (err) {
|
|
97
|
+
console.log(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Copy in the extension files
|
|
101
|
+
fs_1.default.mkdirSync(`${iosPath}/${targetName}`, { recursive: true });
|
|
102
|
+
extFiles.forEach(function (extFile) {
|
|
103
|
+
let targetFile = `${iosPath}/${targetName}/${extFile}`;
|
|
104
|
+
try {
|
|
105
|
+
fs_1.default.createReadStream(`${sourceDir}${extFile}`).pipe(fs_1.default.createWriteStream(targetFile));
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.log(err);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const projObjects = xcodeProject.hash.project.objects;
|
|
112
|
+
// Create new PBXGroup for the extension
|
|
113
|
+
let extGroup = xcodeProject.addPbxGroup(extFiles, targetName, targetName);
|
|
114
|
+
// Add the new PBXGroup to the top level group. This makes the
|
|
115
|
+
// files / folder appear in the file explorer in Xcode.
|
|
116
|
+
let groups = xcodeProject.hash.project.objects["PBXGroup"];
|
|
117
|
+
Object.keys(groups).forEach(function (key) {
|
|
118
|
+
if (groups[key].name === undefined) {
|
|
119
|
+
xcodeProject.addToPbxGroup(extGroup.uuid, key);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
// WORK AROUND for codeProject.addTarget BUG
|
|
123
|
+
// Xcode projects don't contain these if there is only one target
|
|
124
|
+
// An upstream fix should be made to the code referenced in this link:
|
|
125
|
+
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
|
|
126
|
+
projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {};
|
|
127
|
+
projObjects['PBXContainerItemProxy'] = projObjects['PBXTargetDependency'] || {};
|
|
128
|
+
if (!!xcodeProject.pbxTargetByName(targetName)) {
|
|
129
|
+
console.log(targetName, "already exists in project. Skipping...");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Add the NSE target
|
|
133
|
+
// This adds PBXTargetDependency and PBXContainerItemProxy for you
|
|
134
|
+
const nseTarget = xcodeProject.addTarget(targetName, "app_extension", targetName, `${bundleIdentifier}.${targetName}`);
|
|
135
|
+
// Add build phases to the new target
|
|
136
|
+
xcodeProject.addBuildPhase(["NotificationService.m"], "PBXSourcesBuildPhase", "Sources", nseTarget.uuid);
|
|
137
|
+
xcodeProject.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", nseTarget.uuid);
|
|
138
|
+
xcodeProject.addBuildPhase([], "PBXFrameworksBuildPhase", "Frameworks", nseTarget.uuid);
|
|
139
|
+
// Edit the Deployment info of the new Target, only IphoneOS and Targeted Device Family
|
|
140
|
+
// However, can be more
|
|
141
|
+
let configurations = xcodeProject.pbxXCBuildConfigurationSection();
|
|
142
|
+
for (let key in configurations) {
|
|
143
|
+
if (typeof configurations[key].buildSettings !== "undefined" &&
|
|
144
|
+
configurations[key].buildSettings.PRODUCT_NAME == `"${targetName}"`) {
|
|
145
|
+
let buildSettingsObj = configurations[key].buildSettings;
|
|
146
|
+
buildSettingsObj.DEVELOPMENT_TEAM = devTeam;
|
|
147
|
+
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = iosConstants_1.IPHONEOS_DEPLOYMENT_TARGET;
|
|
148
|
+
buildSettingsObj.TARGETED_DEVICE_FAMILY = iosConstants_1.TARGETED_DEVICE_FAMILY;
|
|
149
|
+
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${targetName}/${targetName}.entitlements`;
|
|
150
|
+
buildSettingsObj.CODE_SIGN_STYLE = "Automatic";
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Add development teams to both your target and the original project
|
|
154
|
+
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam, nseTarget);
|
|
155
|
+
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam);
|
|
156
|
+
fs_1.default.writeFileSync(projPath, xcodeProject.writeSync());
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
exports.xcodeProjectAddNse = xcodeProjectAddNse;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.ReaderManager = void 0;
|
|
23
|
+
const fs = __importStar(require("fs"));
|
|
24
|
+
class ReaderManager {
|
|
25
|
+
static async readFile(path, replace) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
fs.readFile(path, 'utf8', (err, data) => {
|
|
28
|
+
if (err) {
|
|
29
|
+
reject(err);
|
|
30
|
+
}
|
|
31
|
+
if (!data) {
|
|
32
|
+
console.error("Couldn't read file:", path);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
resolve(data);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ReaderManager = ReaderManager;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = exports.NSE_PODFILE_REGEX = exports.NSE_PODFILE_SNIPPET = exports.TARGETED_DEVICE_FAMILY = exports.IPHONEOS_DEPLOYMENT_TARGET = void 0;
|
|
4
|
+
exports.IPHONEOS_DEPLOYMENT_TARGET = "10.0";
|
|
5
|
+
exports.TARGETED_DEVICE_FAMILY = `\"1,2\"`;
|
|
6
|
+
exports.NSE_PODFILE_SNIPPET = `
|
|
7
|
+
target 'OneSignalNotificationServiceExtension' do
|
|
8
|
+
pod 'OneSignalXCFramework', '>= 3.0', '< 4.0'
|
|
9
|
+
end`;
|
|
10
|
+
exports.NSE_PODFILE_REGEX = /target 'OneSignalNotificationServiceExtension'/;
|
|
11
|
+
exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#import <OneSignal/OneSignal.h>
|
|
2
|
+
|
|
3
|
+
#import "NotificationService.h"
|
|
4
|
+
|
|
5
|
+
@interface NotificationService ()
|
|
6
|
+
|
|
7
|
+
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
|
|
8
|
+
@property (nonatomic, strong) UNNotificationRequest *receivedRequest;
|
|
9
|
+
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@implementation NotificationService
|
|
14
|
+
|
|
15
|
+
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
|
|
16
|
+
self.receivedRequest = request;
|
|
17
|
+
self.contentHandler = contentHandler;
|
|
18
|
+
self.bestAttemptContent = [request.content mutableCopy];
|
|
19
|
+
[OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
|
|
20
|
+
withMutableNotificationContent:self.bestAttemptContent
|
|
21
|
+
withContentHandler:self.contentHandler];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (void)serviceExtensionTimeWillExpire {
|
|
25
|
+
[OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent];
|
|
26
|
+
self.contentHandler(self.bestAttemptContent);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@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>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleDisplayName</key>
|
|
8
|
+
<string>OneSignalNotificationServiceExtension</string>
|
|
9
|
+
<key>CFBundleExecutable</key>
|
|
10
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
11
|
+
<key>CFBundleIdentifier</key>
|
|
12
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
13
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
14
|
+
<string>6.0</string>
|
|
15
|
+
<key>CFBundleName</key>
|
|
16
|
+
<string>$(PRODUCT_NAME)</string>
|
|
17
|
+
<key>CFBundlePackageType</key>
|
|
18
|
+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
|
19
|
+
<key>CFBundleShortVersionString</key>
|
|
20
|
+
<string>1.0</string>
|
|
21
|
+
<key>CFBundleVersion</key>
|
|
22
|
+
<string>1</string>
|
|
23
|
+
<key>NSExtension</key>
|
|
24
|
+
<dict>
|
|
25
|
+
<key>NSExtensionPointIdentifier</key>
|
|
26
|
+
<string>com.apple.usernotifications.service</string>
|
|
27
|
+
<key>NSExtensionPrincipalClass</key>
|
|
28
|
+
<string>NotificationService</string>
|
|
29
|
+
</dict>
|
|
30
|
+
</dict>
|
|
31
|
+
</plist>
|
package/build/support/serviceExtensionFiles/OneSignalNotificationServiceExtension.entitlements
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
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>com.apple.security.application-groups</key>
|
|
6
|
+
<array>
|
|
7
|
+
<string>{{GROUP_IDENTIFIER}}</string>
|
|
8
|
+
</array>
|
|
9
|
+
</dict>
|
|
10
|
+
</plist>
|
|
@@ -0,0 +1,20 @@
|
|
|
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.updateNSEEntitlements = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const iosConstants_1 = require("./iosConstants");
|
|
9
|
+
const ReaderManager_1 = require("./ReaderManager");
|
|
10
|
+
const fileToEdit = `${__dirname}/serviceExtensionFiles/OneSignalNotificationServiceExtension.entitlements`;
|
|
11
|
+
async function updateNSEEntitlements(groupIdentifier) {
|
|
12
|
+
let entitlementsFile = await ReaderManager_1.ReaderManager.readFile(fileToEdit);
|
|
13
|
+
entitlementsFile = entitlementsFile.replace(iosConstants_1.GROUP_IDENTIFIER_TEMPLATE_REGEX, groupIdentifier);
|
|
14
|
+
fs_1.default.writeFile(fileToEdit, entitlementsFile, 'utf-8', (err) => {
|
|
15
|
+
if (err) {
|
|
16
|
+
console.error("Error updating OneSignal NSE Entitlement File.");
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
exports.updateNSEEntitlements = updateNSEEntitlements;
|
|
@@ -0,0 +1,24 @@
|
|
|
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.updatePodfile = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const iosConstants_1 = require("./iosConstants");
|
|
9
|
+
const ReaderManager_1 = require("./ReaderManager");
|
|
10
|
+
async function updatePodfile(iosPath) {
|
|
11
|
+
const podfile = await ReaderManager_1.ReaderManager.readFile(`${iosPath}/Podfile`);
|
|
12
|
+
const matches = podfile.match(iosConstants_1.NSE_PODFILE_REGEX);
|
|
13
|
+
if (matches) {
|
|
14
|
+
console.info("OneSignalNotificationServiceExtension target already added to Podfile. Skipping...");
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
fs_1.default.appendFile(`${iosPath}/Podfile`, iosConstants_1.NSE_PODFILE_SNIPPET, (err) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
console.error("Error writing to Podfile");
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.updatePodfile = updatePodfile;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const withOneSignalIos_1 = require("./onesignal/withOneSignalIos");
|
|
4
|
+
// Quick testing on any Xcode project
|
|
5
|
+
// 1. Update values for your project
|
|
6
|
+
// 2. Run `yarn build` from here
|
|
7
|
+
// 3. Open a terminal to the root of your Xcode project
|
|
8
|
+
// 4. Run `node ~/WHERE_YOU_CLONED_ME/onesignal-expo-plugin/build/testRuniOS.js`
|
|
9
|
+
// 5. Run `pod init`, if you haven't already.
|
|
10
|
+
// - Make sure you are testing with 2 targets in your Podfile, your main target AND your NSE
|
|
11
|
+
// - If you forget your main target in your Podfile you will get the
|
|
12
|
+
// "Please add the host targets for the embedded targets to the Podfile." error
|
|
13
|
+
// even if your .xcodeproj is correct.
|
|
14
|
+
(0, withOneSignalIos_1.xcodeProjectAddNse)("XcodeTestProj", ".", "com.onesignal.XcodeTestProj", "99SW8E36CT", "../../repos/onesignal-expo-plugin/support/serviceExtensionFiles/");
|
|
@@ -7,8 +7,14 @@ import {
|
|
|
7
7
|
ConfigPlugin,
|
|
8
8
|
withEntitlementsPlist,
|
|
9
9
|
withInfoPlist,
|
|
10
|
+
withXcodeProject,
|
|
10
11
|
} from "@expo/config-plugins";
|
|
11
12
|
import { OneSignalPluginProps } from "./withOneSignal";
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import xcode from 'xcode';
|
|
15
|
+
import { IPHONEOS_DEPLOYMENT_TARGET, TARGETED_DEVICE_FAMILY } from "../support/iosConstants";
|
|
16
|
+
import { updatePodfile } from "../support/updatePodfile";
|
|
17
|
+
import { updateNSEEntitlements } from "../support/updateNSEEntitlements";
|
|
12
18
|
|
|
13
19
|
// ---------- ---------- ---------- ----------
|
|
14
20
|
|
|
@@ -18,10 +24,17 @@ import { OneSignalPluginProps } from "./withOneSignal";
|
|
|
18
24
|
*/
|
|
19
25
|
const withAppEnvironment: ConfigPlugin<OneSignalPluginProps> = (
|
|
20
26
|
config,
|
|
21
|
-
|
|
27
|
+
onesignalProps
|
|
22
28
|
) => {
|
|
23
29
|
return withEntitlementsPlist(config, (newConfig) => {
|
|
24
|
-
|
|
30
|
+
if (onesignalProps?.mode == null) {
|
|
31
|
+
throw new Error(`
|
|
32
|
+
Missing required "mode" key in your app.json or app.config.js file for "onesignal-expo-plugin".
|
|
33
|
+
"mode" can be either "development" or "production".
|
|
34
|
+
Please see onesignal-expo-plugin's README.md for more details.`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
newConfig.modResults["aps-environment"] = onesignalProps.mode;
|
|
25
38
|
return newConfig;
|
|
26
39
|
});
|
|
27
40
|
};
|
|
@@ -68,6 +81,20 @@ const withAppGroupPermissions: ConfigPlugin<OneSignalPluginProps> = (
|
|
|
68
81
|
});
|
|
69
82
|
};
|
|
70
83
|
|
|
84
|
+
const withOneSignalNSE: ConfigPlugin<OneSignalPluginProps> = (config, onesignalProps) => {
|
|
85
|
+
return withXcodeProject(config, async props => {
|
|
86
|
+
xcodeProjectAddNse(
|
|
87
|
+
props.modRequest.projectName || "",
|
|
88
|
+
props.modRequest.platformProjectRoot,
|
|
89
|
+
props.ios?.bundleIdentifier || "",
|
|
90
|
+
onesignalProps?.devTeam,
|
|
91
|
+
"node_modules/onesignal-expo-plugin/build/support/serviceExtensionFiles/"
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return props;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
71
98
|
// ---------- ---------- ---------- ----------
|
|
72
99
|
export const withOneSignalIos: ConfigPlugin<OneSignalPluginProps> = (
|
|
73
100
|
config,
|
|
@@ -76,6 +103,120 @@ export const withOneSignalIos: ConfigPlugin<OneSignalPluginProps> = (
|
|
|
76
103
|
withAppEnvironment(config, props);
|
|
77
104
|
withRemoteNotificationsPermissions(config, props);
|
|
78
105
|
withAppGroupPermissions(config, props);
|
|
79
|
-
|
|
106
|
+
withOneSignalNSE(config, props);
|
|
80
107
|
return config;
|
|
81
108
|
};
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
export function xcodeProjectAddNse(
|
|
112
|
+
appName: string,
|
|
113
|
+
iosPath: string,
|
|
114
|
+
bundleIdentifier: string,
|
|
115
|
+
devTeam: string | undefined,
|
|
116
|
+
sourceDir: string
|
|
117
|
+
): void {
|
|
118
|
+
updatePodfile(iosPath);
|
|
119
|
+
updateNSEEntitlements(`group.${bundleIdentifier}.onesignal`)
|
|
120
|
+
|
|
121
|
+
const projPath = `${iosPath}/${appName}.xcodeproj/project.pbxproj`;
|
|
122
|
+
const targetName = "OneSignalNotificationServiceExtension";
|
|
123
|
+
|
|
124
|
+
const extFiles = [
|
|
125
|
+
"NotificationService.h",
|
|
126
|
+
"NotificationService.m",
|
|
127
|
+
`${targetName}.entitlements`,
|
|
128
|
+
`${targetName}-Info.plist`
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
const xcodeProject = xcode.project(projPath);
|
|
132
|
+
|
|
133
|
+
xcodeProject.parse(function(err: Error) {
|
|
134
|
+
if (err) {
|
|
135
|
+
console.log(`Error parsing iOS project: ${JSON.stringify(err)}`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Copy in the extension files
|
|
140
|
+
fs.mkdirSync(`${iosPath}/${targetName}`, { recursive: true });
|
|
141
|
+
extFiles.forEach(function (extFile) {
|
|
142
|
+
let targetFile = `${iosPath}/${targetName}/${extFile}`;
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
fs.createReadStream(`${sourceDir}${extFile}`).pipe(
|
|
146
|
+
fs.createWriteStream(targetFile)
|
|
147
|
+
);
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.log(err);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const projObjects = xcodeProject.hash.project.objects;
|
|
154
|
+
|
|
155
|
+
// Create new PBXGroup for the extension
|
|
156
|
+
let extGroup = xcodeProject.addPbxGroup(extFiles, targetName, targetName);
|
|
157
|
+
|
|
158
|
+
// Add the new PBXGroup to the top level group. This makes the
|
|
159
|
+
// files / folder appear in the file explorer in Xcode.
|
|
160
|
+
let groups = xcodeProject.hash.project.objects["PBXGroup"];
|
|
161
|
+
Object.keys(groups).forEach(function (key) {
|
|
162
|
+
if (groups[key].name === undefined) {
|
|
163
|
+
xcodeProject.addToPbxGroup(extGroup.uuid, key);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// WORK AROUND for codeProject.addTarget BUG
|
|
168
|
+
// Xcode projects don't contain these if there is only one target
|
|
169
|
+
// An upstream fix should be made to the code referenced in this link:
|
|
170
|
+
// - https://github.com/apache/cordova-node-xcode/blob/8b98cabc5978359db88dc9ff2d4c015cba40f150/lib/pbxProject.js#L860
|
|
171
|
+
projObjects['PBXTargetDependency'] = projObjects['PBXTargetDependency'] || {};
|
|
172
|
+
projObjects['PBXContainerItemProxy'] = projObjects['PBXTargetDependency'] || {};
|
|
173
|
+
|
|
174
|
+
if (!!xcodeProject.pbxTargetByName(targetName)) {
|
|
175
|
+
console.log(targetName, "already exists in project. Skipping...");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Add the NSE target
|
|
180
|
+
// This adds PBXTargetDependency and PBXContainerItemProxy for you
|
|
181
|
+
const nseTarget = xcodeProject.addTarget(targetName, "app_extension", targetName, `${bundleIdentifier}.${targetName}`);
|
|
182
|
+
|
|
183
|
+
// Add build phases to the new target
|
|
184
|
+
xcodeProject.addBuildPhase(
|
|
185
|
+
["NotificationService.m"],
|
|
186
|
+
"PBXSourcesBuildPhase",
|
|
187
|
+
"Sources",
|
|
188
|
+
nseTarget.uuid
|
|
189
|
+
);
|
|
190
|
+
xcodeProject.addBuildPhase([], "PBXResourcesBuildPhase", "Resources", nseTarget.uuid);
|
|
191
|
+
|
|
192
|
+
xcodeProject.addBuildPhase(
|
|
193
|
+
[],
|
|
194
|
+
"PBXFrameworksBuildPhase",
|
|
195
|
+
"Frameworks",
|
|
196
|
+
nseTarget.uuid
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
// Edit the Deployment info of the new Target, only IphoneOS and Targeted Device Family
|
|
200
|
+
// However, can be more
|
|
201
|
+
let configurations = xcodeProject.pbxXCBuildConfigurationSection();
|
|
202
|
+
for (let key in configurations) {
|
|
203
|
+
if (
|
|
204
|
+
typeof configurations[key].buildSettings !== "undefined" &&
|
|
205
|
+
configurations[key].buildSettings.PRODUCT_NAME == `"${targetName}"`
|
|
206
|
+
) {
|
|
207
|
+
let buildSettingsObj = configurations[key].buildSettings;
|
|
208
|
+
buildSettingsObj.DEVELOPMENT_TEAM = devTeam;
|
|
209
|
+
buildSettingsObj.IPHONEOS_DEPLOYMENT_TARGET = IPHONEOS_DEPLOYMENT_TARGET;
|
|
210
|
+
buildSettingsObj.TARGETED_DEVICE_FAMILY = TARGETED_DEVICE_FAMILY;
|
|
211
|
+
buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `${targetName}/${targetName}.entitlements`;
|
|
212
|
+
buildSettingsObj.CODE_SIGN_STYLE = "Automatic";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Add development teams to both your target and the original project
|
|
217
|
+
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam, nseTarget);
|
|
218
|
+
xcodeProject.addTargetAttribute("DevelopmentTeam", devTeam);
|
|
219
|
+
|
|
220
|
+
fs.writeFileSync(projPath, xcodeProject.writeSync());
|
|
221
|
+
})
|
|
222
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onesignal-expo-plugin",
|
|
3
|
-
"version": "1.0.0-
|
|
3
|
+
"version": "1.0.0-beta8",
|
|
4
4
|
"description": "The OneSignal Expo plugin allows you to use OneSignal without leaving the managed workflow. Developed in collaboration with SweetGreen.",
|
|
5
5
|
"main": "./app.plugin.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
-
"build": "tsc",
|
|
8
|
+
"build": "rm -rf build && tsc && cp -a support/serviceExtensionFiles build/support/",
|
|
9
9
|
"prepare": "yarn run build"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"readme-md-generator": "^1.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"react-native-onesignal": "^4.3.1"
|
|
38
|
+
"react-native-onesignal": "^4.3.1",
|
|
39
|
+
"xcode": "^3.0.1"
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
|
|
3
|
+
export class ReaderManager {
|
|
4
|
+
static async readFile(path: string, replace?: string): Promise<string> {
|
|
5
|
+
return new Promise<string>((resolve, reject) => {
|
|
6
|
+
fs.readFile(path, 'utf8', (err, data) => {
|
|
7
|
+
if (err) {
|
|
8
|
+
reject(err);
|
|
9
|
+
}
|
|
10
|
+
if (!data) {
|
|
11
|
+
console.error("Couldn't read file:", path);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
resolve(data);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const IPHONEOS_DEPLOYMENT_TARGET = "10.0";
|
|
2
|
+
export const TARGETED_DEVICE_FAMILY = `\"1,2\"`;
|
|
3
|
+
|
|
4
|
+
export const NSE_PODFILE_SNIPPET = `
|
|
5
|
+
target 'OneSignalNotificationServiceExtension' do
|
|
6
|
+
pod 'OneSignalXCFramework', '>= 3.0', '< 4.0'
|
|
7
|
+
end`;
|
|
8
|
+
|
|
9
|
+
export const NSE_PODFILE_REGEX = /target 'OneSignalNotificationServiceExtension'/;
|
|
10
|
+
|
|
11
|
+
export const GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#import <OneSignal/OneSignal.h>
|
|
2
|
+
|
|
3
|
+
#import "NotificationService.h"
|
|
4
|
+
|
|
5
|
+
@interface NotificationService ()
|
|
6
|
+
|
|
7
|
+
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
|
|
8
|
+
@property (nonatomic, strong) UNNotificationRequest *receivedRequest;
|
|
9
|
+
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
@implementation NotificationService
|
|
14
|
+
|
|
15
|
+
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
|
|
16
|
+
self.receivedRequest = request;
|
|
17
|
+
self.contentHandler = contentHandler;
|
|
18
|
+
self.bestAttemptContent = [request.content mutableCopy];
|
|
19
|
+
[OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
|
|
20
|
+
withMutableNotificationContent:self.bestAttemptContent
|
|
21
|
+
withContentHandler:self.contentHandler];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (void)serviceExtensionTimeWillExpire {
|
|
25
|
+
[OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest withMutableNotificationContent:self.bestAttemptContent];
|
|
26
|
+
self.contentHandler(self.bestAttemptContent);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@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>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleDisplayName</key>
|
|
8
|
+
<string>OneSignalNotificationServiceExtension</string>
|
|
9
|
+
<key>CFBundleExecutable</key>
|
|
10
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
11
|
+
<key>CFBundleIdentifier</key>
|
|
12
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
13
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
14
|
+
<string>6.0</string>
|
|
15
|
+
<key>CFBundleName</key>
|
|
16
|
+
<string>$(PRODUCT_NAME)</string>
|
|
17
|
+
<key>CFBundlePackageType</key>
|
|
18
|
+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
|
19
|
+
<key>CFBundleShortVersionString</key>
|
|
20
|
+
<string>1.0</string>
|
|
21
|
+
<key>CFBundleVersion</key>
|
|
22
|
+
<string>1</string>
|
|
23
|
+
<key>NSExtension</key>
|
|
24
|
+
<dict>
|
|
25
|
+
<key>NSExtensionPointIdentifier</key>
|
|
26
|
+
<string>com.apple.usernotifications.service</string>
|
|
27
|
+
<key>NSExtensionPrincipalClass</key>
|
|
28
|
+
<string>NotificationService</string>
|
|
29
|
+
</dict>
|
|
30
|
+
</dict>
|
|
31
|
+
</plist>
|
|
@@ -0,0 +1,10 @@
|
|
|
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>com.apple.security.application-groups</key>
|
|
6
|
+
<array>
|
|
7
|
+
<string>{{GROUP_IDENTIFIER}}</string>
|
|
8
|
+
</array>
|
|
9
|
+
</dict>
|
|
10
|
+
</plist>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { GROUP_IDENTIFIER_TEMPLATE_REGEX } from './iosConstants';
|
|
3
|
+
import { ReaderManager } from './ReaderManager';
|
|
4
|
+
|
|
5
|
+
const fileToEdit =`${__dirname}/serviceExtensionFiles/OneSignalNotificationServiceExtension.entitlements`;
|
|
6
|
+
|
|
7
|
+
export async function updateNSEEntitlements(groupIdentifier: string) {
|
|
8
|
+
let entitlementsFile = await ReaderManager.readFile(fileToEdit);
|
|
9
|
+
entitlementsFile = entitlementsFile.replace(GROUP_IDENTIFIER_TEMPLATE_REGEX, groupIdentifier);
|
|
10
|
+
|
|
11
|
+
fs.writeFile(fileToEdit, entitlementsFile, 'utf-8', (err) => {
|
|
12
|
+
if (err) {
|
|
13
|
+
console.error("Error updating OneSignal NSE Entitlement File.");
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { NSE_PODFILE_REGEX, NSE_PODFILE_SNIPPET } from './iosConstants';
|
|
3
|
+
import { ReaderManager } from './ReaderManager';
|
|
4
|
+
|
|
5
|
+
export async function updatePodfile(iosPath: string) {
|
|
6
|
+
const podfile = await ReaderManager.readFile(`${iosPath}/Podfile`);
|
|
7
|
+
const matches = podfile.match(NSE_PODFILE_REGEX);
|
|
8
|
+
|
|
9
|
+
if (matches) {
|
|
10
|
+
console.info("OneSignalNotificationServiceExtension target already added to Podfile. Skipping...");
|
|
11
|
+
} else {
|
|
12
|
+
fs.appendFile(`${iosPath}/Podfile`, NSE_PODFILE_SNIPPET, (err) => {
|
|
13
|
+
if (err) {
|
|
14
|
+
console.error("Error writing to Podfile");
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
}
|
package/testRuniOS.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { xcodeProjectAddNse } from "./onesignal/withOneSignalIos";
|
|
2
|
+
|
|
3
|
+
// Quick testing on any Xcode project
|
|
4
|
+
|
|
5
|
+
// 1. Update values for your project
|
|
6
|
+
// 2. Run `yarn build` from here
|
|
7
|
+
// 3. Open a terminal to the root of your Xcode project
|
|
8
|
+
// 4. Run `node ~/WHERE_YOU_CLONED_ME/onesignal-expo-plugin/build/testRuniOS.js`
|
|
9
|
+
// 5. Run `pod init`, if you haven't already.
|
|
10
|
+
// - Make sure you are testing with 2 targets in your Podfile, your main target AND your NSE
|
|
11
|
+
// - If you forget your main target in your Podfile you will get the
|
|
12
|
+
// "Please add the host targets for the embedded targets to the Podfile." error
|
|
13
|
+
// even if your .xcodeproj is correct.
|
|
14
|
+
xcodeProjectAddNse(
|
|
15
|
+
"XcodeTestProj",
|
|
16
|
+
".",
|
|
17
|
+
"com.onesignal.XcodeTestProj",
|
|
18
|
+
"99SW8E36CT",
|
|
19
|
+
"../../repos/onesignal-expo-plugin/support/serviceExtensionFiles/"
|
|
20
|
+
);
|
package/types/xcode.d.ts
ADDED
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
const react_1 = __importDefault(require("react"));
|
|
7
|
-
const expo_status_bar_1 = require("expo-status-bar");
|
|
8
|
-
const react_native_1 = require("react-native");
|
|
9
|
-
const OneSignal_1 = require("./integrations/OneSignal");
|
|
10
|
-
(0, OneSignal_1.initOneSignalClient)();
|
|
11
|
-
function App() {
|
|
12
|
-
return (<react_native_1.View style={styles.container}>
|
|
13
|
-
<react_native_1.Text>Open up App.tsx to start working on your app!</react_native_1.Text>
|
|
14
|
-
<expo_status_bar_1.StatusBar style="auto"/>
|
|
15
|
-
</react_native_1.View>);
|
|
16
|
-
}
|
|
17
|
-
exports.default = App;
|
|
18
|
-
const styles = react_native_1.StyleSheet.create({
|
|
19
|
-
container: {
|
|
20
|
-
flex: 1,
|
|
21
|
-
backgroundColor: '#fff',
|
|
22
|
-
alignItems: 'center',
|
|
23
|
-
justifyContent: 'center',
|
|
24
|
-
},
|
|
25
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
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.initOneSignalClient = void 0;
|
|
7
|
-
const expo_constants_1 = __importDefault(require("expo-constants"));
|
|
8
|
-
const react_native_onesignal_1 = __importDefault(require("react-native-onesignal"));
|
|
9
|
-
function initOneSignalClient() {
|
|
10
|
-
var _a, _b;
|
|
11
|
-
//OneSignal Init Code
|
|
12
|
-
react_native_onesignal_1.default.setLogLevel(6, 0);
|
|
13
|
-
react_native_onesignal_1.default.setAppId((_b = (_a = expo_constants_1.default.manifest) === null || _a === void 0 ? void 0 : _a.extra) === null || _b === void 0 ? void 0 : _b.oneSignalAppId);
|
|
14
|
-
//Prompt for push on iOS
|
|
15
|
-
react_native_onesignal_1.default.promptForPushNotificationsWithUserResponse((response) => {
|
|
16
|
-
console.log("Prompt response:", response);
|
|
17
|
-
});
|
|
18
|
-
//Method for handling notifications received while app in foreground
|
|
19
|
-
react_native_onesignal_1.default.setNotificationWillShowInForegroundHandler((notificationReceivedEvent) => {
|
|
20
|
-
console.log("OneSignal: notification will show in foreground:", notificationReceivedEvent);
|
|
21
|
-
let notification = notificationReceivedEvent.getNotification();
|
|
22
|
-
console.log("notification: ", notification);
|
|
23
|
-
const data = notification.additionalData;
|
|
24
|
-
console.log("additionalData: ", data);
|
|
25
|
-
// Complete with null means don't show a notification.
|
|
26
|
-
notificationReceivedEvent.complete(notification);
|
|
27
|
-
});
|
|
28
|
-
//Method for handling notifications opened
|
|
29
|
-
react_native_onesignal_1.default.setNotificationOpenedHandler((notification) => {
|
|
30
|
-
console.log("OneSignal: notification opened:", notification);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
exports.initOneSignalClient = initOneSignalClient;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
-
};
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
__exportStar(require("./OneSignal"), exports);
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
const expo_status_bar_1 = require("expo-status-bar");
|
|
7
|
-
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const react_native_1 = require("react-native");
|
|
9
|
-
function App() {
|
|
10
|
-
return (<react_native_1.View style={styles.container}>
|
|
11
|
-
<react_native_1.Text>Open up App.tsx to start working on your app!</react_native_1.Text>
|
|
12
|
-
<expo_status_bar_1.StatusBar style="auto"/>
|
|
13
|
-
</react_native_1.View>);
|
|
14
|
-
}
|
|
15
|
-
exports.default = App;
|
|
16
|
-
const styles = react_native_1.StyleSheet.create({
|
|
17
|
-
container: {
|
|
18
|
-
flex: 1,
|
|
19
|
-
backgroundColor: '#fff',
|
|
20
|
-
alignItems: 'center',
|
|
21
|
-
justifyContent: 'center',
|
|
22
|
-
},
|
|
23
|
-
});
|