onesignal-expo-plugin 2.1.0 → 2.3.0
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 +1 -0
- package/build/onesignal/withOneSignal.d.ts +8 -0
- package/build/onesignal/withOneSignalAndroid.d.ts +7 -0
- package/build/onesignal/withOneSignalAndroid.js +28 -10
- package/build/onesignal/withOneSignalIos.d.ts +7 -0
- package/build/onesignal/withOneSignalIos.js +27 -25
- package/build/support/FileManager.d.ts +9 -0
- package/build/support/NseUpdaterManager.d.ts +8 -0
- package/build/support/NseUpdaterManager.js +3 -4
- package/build/support/OneSignalLog.d.ts +4 -0
- package/build/support/eas/getEasManagedCredentialsConfigExtra.d.ts +4 -0
- package/build/support/eas/getEasManagedCredentialsConfigExtra.js +5 -4
- package/build/support/helpers.d.ts +2 -0
- package/build/support/helpers.js +11 -0
- package/build/support/iosConstants.d.ts +12 -0
- package/build/support/iosConstants.js +7 -11
- package/build/support/serviceExtensionFiles/NotificationService.m +17 -12
- package/build/support/updatePodfile.d.ts +1 -0
- package/build/support/updatePodfile.js +5 -9
- package/build/types/types.d.ts +55 -0
- package/build/types/types.js +3 -6
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -88,6 +88,7 @@ You can pass props to the plugin config object to configure:
|
|
|
88
88
|
| `smallIconAccentColor` | optional | The accent color to use for notification icons on Android. Must be a valid hex value, e.g: `"#FF0000"` |
|
|
89
89
|
| `iosNSEFilePath` | optional | The local path to a custom Notification Service Extension (NSE), written in Objective-C. The NSE will typically start as a copy of the [default NSE](https://github.com/OneSignal/onesignal-expo-plugin/blob/main/support/serviceExtensionFiles/NotificationService.m), then altered to support any custom logic required. e.g: `"./assets/NotificationService.m"`. |
|
|
90
90
|
| `appGroupName` | optional | Used to configure a custom iOS [App Group](https://documentation.onesignal.com/docs/ios-sdk-setup#step-3-create-an-app-group) name. If not provided, defaults to `"group.{ios.bundleIdentifier}.onesignal"`. e.g: `"group.com.example.myapp.onesignal2"`. |
|
|
91
|
+
| `nseBundleIdentifier` | optional | Used to configure a custom bundle identifier suffix for the iOS Notification Service Extension. The full bundle identifier will be `"{ios.bundleIdentifier}.{nseBundleIdentifier}"`. If not provided, defaults to `"OneSignalNotificationServiceExtension"`. |
|
|
91
92
|
|
|
92
93
|
### OneSignal App ID
|
|
93
94
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expo config plugin for One Signal
|
|
3
|
+
* @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
6
|
+
import { OneSignalPluginProps } from '../types/types';
|
|
7
|
+
declare const withOneSignal: ConfigPlugin<OneSignalPluginProps>;
|
|
8
|
+
export default withOneSignal;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expo config plugin for OneSignal (Android)
|
|
3
|
+
* @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
6
|
+
import { OneSignalPluginProps } from '../types/types';
|
|
7
|
+
export declare const withOneSignalAndroid: ConfigPlugin<OneSignalPluginProps>;
|
|
@@ -23,34 +23,34 @@ const SMALL_ICON_DIRS_TO_SIZE = {
|
|
|
23
23
|
const LARGE_ICON_DIRS_TO_SIZE = {
|
|
24
24
|
'drawable-xxxhdpi': 256,
|
|
25
25
|
};
|
|
26
|
+
const SMALL_ICON_DEFAULT_NAME = 'ic_stat_onesignal_default';
|
|
26
27
|
const withSmallIcons = (config, onesignalProps) => {
|
|
27
28
|
if (!onesignalProps.smallIcons && !config.notification?.icon) {
|
|
28
29
|
return config;
|
|
29
30
|
}
|
|
30
|
-
// we are modifying the android build (adding files) without a base mod
|
|
31
31
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
32
32
|
'android',
|
|
33
33
|
async (config) => {
|
|
34
34
|
if (config.notification?.icon) {
|
|
35
|
-
await saveIconAsync(config.notification.icon, config.modRequest.projectRoot, SMALL_ICON_DIRS_TO_SIZE);
|
|
35
|
+
await saveIconAsync(config.notification.icon, config.modRequest.projectRoot, SMALL_ICON_DIRS_TO_SIZE, SMALL_ICON_DEFAULT_NAME);
|
|
36
36
|
}
|
|
37
37
|
if (onesignalProps.smallIcons) {
|
|
38
|
-
await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.smallIcons, SMALL_ICON_DIRS_TO_SIZE);
|
|
38
|
+
await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.smallIcons, SMALL_ICON_DIRS_TO_SIZE, SMALL_ICON_DEFAULT_NAME);
|
|
39
39
|
}
|
|
40
40
|
return config;
|
|
41
41
|
},
|
|
42
42
|
]);
|
|
43
43
|
};
|
|
44
|
+
const LARGE_ICON_DEFAULT_NAME = 'ic_onesignal_large_icon_default';
|
|
44
45
|
const withLargeIcons = (config, onesignalProps) => {
|
|
45
46
|
if (!onesignalProps.largeIcons) {
|
|
46
47
|
return config;
|
|
47
48
|
}
|
|
48
|
-
// we are modifying the android build (adding files) without a base mod
|
|
49
49
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
50
50
|
'android',
|
|
51
51
|
async (config) => {
|
|
52
52
|
if (onesignalProps.largeIcons) {
|
|
53
|
-
await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.largeIcons, LARGE_ICON_DIRS_TO_SIZE);
|
|
53
|
+
await saveIconsArrayAsync(config.modRequest.projectRoot, onesignalProps.largeIcons, LARGE_ICON_DIRS_TO_SIZE, LARGE_ICON_DEFAULT_NAME);
|
|
54
54
|
}
|
|
55
55
|
return config;
|
|
56
56
|
},
|
|
@@ -76,13 +76,15 @@ const withSmallIconAccentColor = (config, onesignalProps) => {
|
|
|
76
76
|
return config;
|
|
77
77
|
});
|
|
78
78
|
};
|
|
79
|
-
async function saveIconsArrayAsync(projectRoot, icons, dirsToSize) {
|
|
80
|
-
for (
|
|
81
|
-
|
|
79
|
+
async function saveIconsArrayAsync(projectRoot, icons, dirsToSize, defaultName) {
|
|
80
|
+
for (let i = 0; i < icons.length; i++) {
|
|
81
|
+
// the first icon should use OneSignal’s required default drawable name; others keep their file-derived names.
|
|
82
|
+
const outputName = i === 0 ? defaultName : undefined;
|
|
83
|
+
await saveIconAsync(icons[i], projectRoot, dirsToSize, outputName);
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
|
-
async function saveIconAsync(icon, projectRoot, dirsToSize) {
|
|
85
|
-
const name = (0, path_1.parse)(icon).name;
|
|
86
|
+
async function saveIconAsync(icon, projectRoot, dirsToSize, outputName) {
|
|
87
|
+
const name = outputName ?? (0, path_1.parse)(icon).name;
|
|
86
88
|
OneSignalLog_1.OneSignalLog.log('Saving icon ' + icon + ' as drawable resource ' + name);
|
|
87
89
|
for (const iconResourceDir in dirsToSize) {
|
|
88
90
|
const path = (0, path_1.resolve)(projectRoot, RESOURCE_ROOT_PATH, iconResourceDir);
|
|
@@ -99,10 +101,26 @@ async function saveIconAsync(icon, projectRoot, dirsToSize) {
|
|
|
99
101
|
(0, fs_1.writeFileSync)((0, path_1.resolve)(path, name + '.png'), resizedIcon);
|
|
100
102
|
}
|
|
101
103
|
}
|
|
104
|
+
const OKHTTP_FORCE_FIX = `
|
|
105
|
+
subprojects {
|
|
106
|
+
project.configurations.all {
|
|
107
|
+
resolutionStrategy.force 'com.squareup.okhttp3:okhttp:4.12.0'
|
|
108
|
+
}
|
|
109
|
+
}`;
|
|
110
|
+
const withOkHttpFix = (config) => {
|
|
111
|
+
return (0, config_plugins_1.withProjectBuildGradle)(config, (config) => {
|
|
112
|
+
if (config.modResults.contents.includes("force 'com.squareup.okhttp3:okhttp:4.12.0'")) {
|
|
113
|
+
return config;
|
|
114
|
+
}
|
|
115
|
+
config.modResults.contents += OKHTTP_FORCE_FIX;
|
|
116
|
+
return config;
|
|
117
|
+
});
|
|
118
|
+
};
|
|
102
119
|
const withOneSignalAndroid = (config, props) => {
|
|
103
120
|
config = withSmallIcons(config, props);
|
|
104
121
|
config = withLargeIcons(config, props);
|
|
105
122
|
config = withSmallIconAccentColor(config, props);
|
|
123
|
+
config = withOkHttpFix(config);
|
|
106
124
|
return config;
|
|
107
125
|
};
|
|
108
126
|
exports.withOneSignalAndroid = withOneSignalAndroid;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expo config plugin for One Signal (iOS)
|
|
3
|
+
* @see https://documentation.onesignal.com/docs/react-native-sdk-setup#step-4-install-for-ios-using-cocoapods-for-ios-apps
|
|
4
|
+
*/
|
|
5
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
6
|
+
import { OneSignalPluginProps } from '../types/types';
|
|
7
|
+
export declare const withOneSignalIos: ConfigPlugin<OneSignalPluginProps>;
|
|
@@ -45,11 +45,11 @@ const config_plugins_1 = require("@expo/config-plugins");
|
|
|
45
45
|
const fs = __importStar(require("fs"));
|
|
46
46
|
const path = __importStar(require("path"));
|
|
47
47
|
const iosConstants_1 = require("../support/iosConstants");
|
|
48
|
+
const helpers_1 = require("../support/helpers");
|
|
48
49
|
const updatePodfile_1 = require("../support/updatePodfile");
|
|
49
50
|
const NseUpdaterManager_1 = __importDefault(require("../support/NseUpdaterManager"));
|
|
50
51
|
const OneSignalLog_1 = require("../support/OneSignalLog");
|
|
51
52
|
const FileManager_1 = require("../support/FileManager");
|
|
52
|
-
const assert_1 = __importDefault(require("assert"));
|
|
53
53
|
const getEasManagedCredentialsConfigExtra_1 = __importDefault(require("../support/eas/getEasManagedCredentialsConfigExtra"));
|
|
54
54
|
/**
|
|
55
55
|
* Add 'aps-environment' record with current environment to '<project-name>.entitlements' file
|
|
@@ -96,7 +96,7 @@ const withAppGroupPermissions = (config, props) => {
|
|
|
96
96
|
newConfig.modResults[APP_GROUP_KEY] = [];
|
|
97
97
|
}
|
|
98
98
|
const modResultsArray = newConfig.modResults[APP_GROUP_KEY];
|
|
99
|
-
const entitlement = (0,
|
|
99
|
+
const entitlement = (0, helpers_1.getAppGroupIdentifier)(newConfig?.ios?.bundleIdentifier || '', props?.appGroupName);
|
|
100
100
|
if (modResultsArray.indexOf(entitlement) !== -1) {
|
|
101
101
|
return newConfig;
|
|
102
102
|
}
|
|
@@ -117,45 +117,44 @@ const withCustomAppGroupsKey = (config, props) => {
|
|
|
117
117
|
});
|
|
118
118
|
};
|
|
119
119
|
const withEasManagedCredentials = (config, props) => {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
if (!config.ios?.bundleIdentifier) {
|
|
121
|
+
return config;
|
|
122
|
+
}
|
|
123
|
+
config.extra = (0, getEasManagedCredentialsConfigExtra_1.default)(config, props?.appGroupName, props?.nseBundleIdentifier);
|
|
122
124
|
return config;
|
|
123
125
|
};
|
|
124
126
|
const withOneSignalPodfile = (config) => {
|
|
125
127
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
126
128
|
'ios',
|
|
127
129
|
async (config) => {
|
|
128
|
-
// not awaiting in order to not block main thread
|
|
129
130
|
const iosRoot = path.join(config.modRequest.projectRoot, 'ios');
|
|
130
|
-
(0, updatePodfile_1.updatePodfile)(iosRoot)
|
|
131
|
-
OneSignalLog_1.OneSignalLog.error(err);
|
|
132
|
-
});
|
|
131
|
+
await (0, updatePodfile_1.updatePodfile)(iosRoot);
|
|
133
132
|
return config;
|
|
134
133
|
},
|
|
135
134
|
]);
|
|
136
135
|
};
|
|
137
136
|
const withOneSignalNSE = (config, props) => {
|
|
138
|
-
// support for monorepos where node_modules can be above the project directory.
|
|
139
|
-
const pluginDir = require.resolve('onesignal-expo-plugin/package.json');
|
|
140
|
-
const sourceDir = path.join(pluginDir, '../build/support/serviceExtensionFiles/');
|
|
141
137
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
142
138
|
'ios',
|
|
143
139
|
async (config) => {
|
|
140
|
+
// support for monorepos where node_modules can be above the project directory.
|
|
141
|
+
const pluginDir = require.resolve('onesignal-expo-plugin/package.json');
|
|
142
|
+
const sourceDir = path.join(pluginDir, '../build/support/serviceExtensionFiles/');
|
|
144
143
|
const iosPath = path.join(config.modRequest.projectRoot, 'ios');
|
|
145
144
|
/* COPY OVER EXTENSION FILES */
|
|
146
|
-
fs.mkdirSync(`${iosPath}/${iosConstants_1.NSE_TARGET_NAME}`, {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
fs.mkdirSync(`${iosPath}/${iosConstants_1.NSE_TARGET_NAME}`, {
|
|
146
|
+
recursive: true,
|
|
147
|
+
});
|
|
148
|
+
for (const file of iosConstants_1.NSE_EXT_FILES) {
|
|
149
|
+
const targetFile = `${iosPath}/${iosConstants_1.NSE_TARGET_NAME}/${file}`;
|
|
150
|
+
await FileManager_1.FileManager.copyFile(`${sourceDir}${file}`, targetFile);
|
|
151
151
|
}
|
|
152
|
-
// Copy NSE source file either from configuration-provided location, falling back to the default one.
|
|
153
152
|
const sourcePath = props.iosNSEFilePath ?? `${sourceDir}${iosConstants_1.NSE_SOURCE_FILE}`;
|
|
154
153
|
const targetFile = `${iosPath}/${iosConstants_1.NSE_TARGET_NAME}/${iosConstants_1.NSE_SOURCE_FILE}`;
|
|
155
154
|
await FileManager_1.FileManager.copyFile(`${sourcePath}`, targetFile);
|
|
156
155
|
/* MODIFY COPIED EXTENSION FILES */
|
|
157
156
|
const nseUpdater = new NseUpdaterManager_1.default(iosPath);
|
|
158
|
-
const appGroupId = (0,
|
|
157
|
+
const appGroupId = (0, helpers_1.getAppGroupIdentifier)(config.ios?.bundleIdentifier ?? '', props.appGroupName);
|
|
159
158
|
await nseUpdater.updateNSEEntitlements(appGroupId);
|
|
160
159
|
if (props.appGroupName) {
|
|
161
160
|
await nseUpdater.updateNSEInfoPlistAppGroupKey(props.appGroupName);
|
|
@@ -169,6 +168,7 @@ const withOneSignalNSE = (config, props) => {
|
|
|
169
168
|
const withOneSignalXcodeProject = (config, props) => {
|
|
170
169
|
return (0, config_plugins_1.withXcodeProject)(config, (newConfig) => {
|
|
171
170
|
const xcodeProject = newConfig.modResults;
|
|
171
|
+
const nseBundleId = `${config.ios?.bundleIdentifier}.${props.nseBundleIdentifier ?? iosConstants_1.NSE_TARGET_NAME}`;
|
|
172
172
|
if (xcodeProject.pbxTargetByName(iosConstants_1.NSE_TARGET_NAME)) {
|
|
173
173
|
OneSignalLog_1.OneSignalLog.log(`${iosConstants_1.NSE_TARGET_NAME} already exists in project. Skipping...`);
|
|
174
174
|
return newConfig;
|
|
@@ -196,7 +196,7 @@ const withOneSignalXcodeProject = (config, props) => {
|
|
|
196
196
|
projObjects['PBXTargetDependency'] || {};
|
|
197
197
|
// Add the NSE target
|
|
198
198
|
// This adds PBXTargetDependency and PBXContainerItemProxy for you
|
|
199
|
-
const nseTarget = xcodeProject.addTarget(iosConstants_1.NSE_TARGET_NAME, 'app_extension', iosConstants_1.NSE_TARGET_NAME,
|
|
199
|
+
const nseTarget = xcodeProject.addTarget(iosConstants_1.NSE_TARGET_NAME, 'app_extension', iosConstants_1.NSE_TARGET_NAME, nseBundleId);
|
|
200
200
|
// Add build phases to the new target
|
|
201
201
|
xcodeProject.addBuildPhase(['NotificationService.m'], 'PBXSourcesBuildPhase', 'Sources', nseTarget.uuid);
|
|
202
202
|
xcodeProject.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', nseTarget.uuid);
|
|
@@ -225,12 +225,14 @@ const withOneSignalXcodeProject = (config, props) => {
|
|
|
225
225
|
const withOneSignalIos = (config, props) => {
|
|
226
226
|
config = withAppEnvironment(config, props);
|
|
227
227
|
config = withRemoteNotificationsPermissions(config, props);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
228
|
+
if (!props.disableNSE) {
|
|
229
|
+
config = withCustomAppGroupsKey(config, props);
|
|
230
|
+
config = withAppGroupPermissions(config, props);
|
|
231
|
+
config = withOneSignalPodfile(config, props);
|
|
232
|
+
config = withOneSignalNSE(config, props);
|
|
233
|
+
config = withOneSignalXcodeProject(config, props);
|
|
234
|
+
config = withEasManagedCredentials(config, props);
|
|
235
|
+
}
|
|
234
236
|
return config;
|
|
235
237
|
};
|
|
236
238
|
exports.withOneSignalIos = withOneSignalIos;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FileManager contains static *awaitable* file-system functions
|
|
3
|
+
*/
|
|
4
|
+
export declare class FileManager {
|
|
5
|
+
static readFile(path: string): Promise<string>;
|
|
6
|
+
static writeFile(path: string, contents: string): Promise<void>;
|
|
7
|
+
static copyFile(path1: string, path2: string): Promise<void>;
|
|
8
|
+
static dirExists(path: string): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default class NseUpdaterManager {
|
|
2
|
+
private nsePath;
|
|
3
|
+
constructor(iosPath: string);
|
|
4
|
+
updateNSEEntitlements(groupIdentifier: string): Promise<void>;
|
|
5
|
+
updateNSEBundleVersion(version: string): Promise<void>;
|
|
6
|
+
updateNSEBundleShortVersion(version: string): Promise<void>;
|
|
7
|
+
updateNSEInfoPlistAppGroupKey(appGroupName: string): Promise<void>;
|
|
8
|
+
}
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const FileManager_1 = require("./FileManager");
|
|
4
4
|
const iosConstants_1 = require("./iosConstants");
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const plistFileName = `OneSignalNotificationServiceExtension-Info.plist`;
|
|
5
|
+
const entitlementsFileName = `${iosConstants_1.NSE_TARGET_NAME}.entitlements`;
|
|
6
|
+
const plistFileName = `${iosConstants_1.NSE_TARGET_NAME}-Info.plist`;
|
|
8
7
|
class NseUpdaterManager {
|
|
9
|
-
nsePath
|
|
8
|
+
nsePath;
|
|
10
9
|
constructor(iosPath) {
|
|
11
10
|
this.nsePath = `${iosPath}/${iosConstants_1.NSE_TARGET_NAME}`;
|
|
12
11
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = getEasManagedCredentialsConfigExtra;
|
|
4
4
|
const iosConstants_1 = require("../iosConstants");
|
|
5
|
-
|
|
5
|
+
const helpers_1 = require("../helpers");
|
|
6
|
+
function getEasManagedCredentialsConfigExtra(config, appGroupName, nseBundleIdentifier) {
|
|
7
|
+
const bundleId = `${config?.ios?.bundleIdentifier}.${nseBundleIdentifier ?? iosConstants_1.NSE_TARGET_NAME}`;
|
|
6
8
|
return {
|
|
7
9
|
...config.extra,
|
|
8
10
|
eas: {
|
|
@@ -17,12 +19,11 @@ function getEasManagedCredentialsConfigExtra(config, appGroupName) {
|
|
|
17
19
|
...(config.extra?.eas?.build?.experimental?.ios?.appExtensions ??
|
|
18
20
|
[]),
|
|
19
21
|
{
|
|
20
|
-
// keep in sync with native changes in NSE
|
|
21
22
|
targetName: iosConstants_1.NSE_TARGET_NAME,
|
|
22
|
-
bundleIdentifier:
|
|
23
|
+
bundleIdentifier: bundleId,
|
|
23
24
|
entitlements: {
|
|
24
25
|
'com.apple.security.application-groups': [
|
|
25
|
-
(0,
|
|
26
|
+
(0, helpers_1.getAppGroupIdentifier)(config?.ios?.bundleIdentifier ?? '', appGroupName),
|
|
26
27
|
],
|
|
27
28
|
},
|
|
28
29
|
},
|
package/build/support/helpers.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validatePluginProps = validatePluginProps;
|
|
4
|
+
exports.getAppGroupIdentifier = getAppGroupIdentifier;
|
|
4
5
|
const types_1 = require("../types/types");
|
|
5
6
|
function validatePluginProps(props) {
|
|
6
7
|
// check the type of each property
|
|
@@ -30,6 +31,13 @@ function validatePluginProps(props) {
|
|
|
30
31
|
if (props.appGroupName && typeof props.appGroupName !== 'string') {
|
|
31
32
|
throw new Error("OneSignal Expo Plugin: 'appGroupName' must be a string.");
|
|
32
33
|
}
|
|
34
|
+
if (props.nseBundleIdentifier &&
|
|
35
|
+
typeof props.nseBundleIdentifier !== 'string') {
|
|
36
|
+
throw new Error("OneSignal Expo Plugin: 'nseBundleIdentifier' must be a string.");
|
|
37
|
+
}
|
|
38
|
+
if (props.disableNSE !== undefined && typeof props.disableNSE !== 'boolean') {
|
|
39
|
+
throw new Error("OneSignal Expo Plugin: 'disableNSE' must be a boolean.");
|
|
40
|
+
}
|
|
33
41
|
// check for extra properties
|
|
34
42
|
const inputProps = Object.keys(props);
|
|
35
43
|
for (const prop of inputProps) {
|
|
@@ -38,3 +46,6 @@ function validatePluginProps(props) {
|
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
}
|
|
49
|
+
function getAppGroupIdentifier(bundleIdentifier, customAppGroupName) {
|
|
50
|
+
return customAppGroupName ?? `group.${bundleIdentifier}.onesignal`;
|
|
51
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const IPHONEOS_DEPLOYMENT_TARGET = "11.0";
|
|
2
|
+
export declare const TARGETED_DEVICE_FAMILY = "\"1,2\"";
|
|
3
|
+
export declare const GROUP_IDENTIFIER_TEMPLATE_REGEX: RegExp;
|
|
4
|
+
export declare const BUNDLE_SHORT_VERSION_TEMPLATE_REGEX: RegExp;
|
|
5
|
+
export declare const BUNDLE_VERSION_TEMPLATE_REGEX: RegExp;
|
|
6
|
+
export declare const DEFAULT_BUNDLE_VERSION = "1";
|
|
7
|
+
export declare const DEFAULT_BUNDLE_SHORT_VERSION = "1.0";
|
|
8
|
+
export declare const NSE_TARGET_NAME = "OneSignalNotificationServiceExtension";
|
|
9
|
+
export declare const NSE_SOURCE_FILE = "NotificationService.m";
|
|
10
|
+
export declare const NSE_PODFILE_SNIPPET = "\ntarget 'OneSignalNotificationServiceExtension' do\n pod 'OneSignalXCFramework', '>= 5.0', '< 6.0'\n use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']\nend";
|
|
11
|
+
export declare const NSE_PODFILE_REGEX: RegExp;
|
|
12
|
+
export declare const NSE_EXT_FILES: string[];
|
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NSE_EXT_FILES = exports.
|
|
4
|
-
exports.getAppGroupIdentifier = getAppGroupIdentifier;
|
|
3
|
+
exports.NSE_EXT_FILES = exports.NSE_PODFILE_REGEX = exports.NSE_PODFILE_SNIPPET = exports.NSE_SOURCE_FILE = exports.NSE_TARGET_NAME = exports.DEFAULT_BUNDLE_SHORT_VERSION = exports.DEFAULT_BUNDLE_VERSION = exports.BUNDLE_VERSION_TEMPLATE_REGEX = exports.BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = exports.TARGETED_DEVICE_FAMILY = exports.IPHONEOS_DEPLOYMENT_TARGET = void 0;
|
|
5
4
|
exports.IPHONEOS_DEPLOYMENT_TARGET = '11.0';
|
|
6
5
|
exports.TARGETED_DEVICE_FAMILY = `"1,2"`;
|
|
7
|
-
exports.NSE_PODFILE_SNIPPET = `
|
|
8
|
-
target 'OneSignalNotificationServiceExtension' do
|
|
9
|
-
pod 'OneSignalXCFramework', '>= 5.0', '< 6.0'
|
|
10
|
-
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
|
11
|
-
end`;
|
|
12
|
-
exports.NSE_PODFILE_REGEX = /target 'OneSignalNotificationServiceExtension'/;
|
|
13
6
|
exports.GROUP_IDENTIFIER_TEMPLATE_REGEX = /{{GROUP_IDENTIFIER}}/gm;
|
|
14
7
|
exports.BUNDLE_SHORT_VERSION_TEMPLATE_REGEX = /{{BUNDLE_SHORT_VERSION}}/gm;
|
|
15
8
|
exports.BUNDLE_VERSION_TEMPLATE_REGEX = /{{BUNDLE_VERSION}}/gm;
|
|
16
9
|
exports.DEFAULT_BUNDLE_VERSION = '1';
|
|
17
10
|
exports.DEFAULT_BUNDLE_SHORT_VERSION = '1.0';
|
|
18
11
|
exports.NSE_TARGET_NAME = 'OneSignalNotificationServiceExtension';
|
|
19
|
-
function getAppGroupIdentifier(bundleIdentifier, customAppGroupName) {
|
|
20
|
-
return customAppGroupName ?? `group.${bundleIdentifier}.onesignal`;
|
|
21
|
-
}
|
|
22
12
|
exports.NSE_SOURCE_FILE = 'NotificationService.m';
|
|
13
|
+
exports.NSE_PODFILE_SNIPPET = `
|
|
14
|
+
target '${exports.NSE_TARGET_NAME}' do
|
|
15
|
+
pod 'OneSignalXCFramework', '>= 5.0', '< 6.0'
|
|
16
|
+
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
|
17
|
+
end`;
|
|
18
|
+
exports.NSE_PODFILE_REGEX = new RegExp(`target '${exports.NSE_TARGET_NAME}'`);
|
|
23
19
|
exports.NSE_EXT_FILES = [
|
|
24
20
|
'NotificationService.h',
|
|
25
21
|
`${exports.NSE_TARGET_NAME}.entitlements`,
|
|
@@ -4,26 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
@interface NotificationService ()
|
|
6
6
|
|
|
7
|
-
@property
|
|
8
|
-
|
|
9
|
-
@property
|
|
7
|
+
@property(nonatomic, strong) void (^contentHandler)
|
|
8
|
+
(UNNotificationContent *contentToDeliver);
|
|
9
|
+
@property(nonatomic, strong) UNNotificationRequest *receivedRequest;
|
|
10
|
+
@property(nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
|
|
10
11
|
|
|
11
12
|
@end
|
|
12
13
|
|
|
13
14
|
@implementation NotificationService
|
|
14
15
|
|
|
15
|
-
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
|
|
17
|
+
withContentHandler:
|
|
18
|
+
(void (^)(UNNotificationContent *_Nonnull))
|
|
19
|
+
contentHandler {
|
|
20
|
+
self.receivedRequest = request;
|
|
21
|
+
self.contentHandler = contentHandler;
|
|
22
|
+
self.bestAttemptContent = [request.content mutableCopy];
|
|
23
|
+
[OneSignal didReceiveNotificationExtensionRequest:self.receivedRequest
|
|
24
|
+
withMutableNotificationContent:self.bestAttemptContent
|
|
25
|
+
withContentHandler:self.contentHandler];
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
- (void)serviceExtensionTimeWillExpire {
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
[OneSignal serviceExtensionTimeWillExpireRequest:self.receivedRequest
|
|
30
|
+
withMutableNotificationContent:self.bestAttemptContent];
|
|
31
|
+
self.contentHandler(self.bestAttemptContent);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
@end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function updatePodfile(iosPath: string): Promise<void>;
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.updatePodfile = updatePodfile;
|
|
7
|
-
const
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
8
|
const iosConstants_1 = require("./iosConstants");
|
|
9
9
|
const OneSignalLog_1 = require("./OneSignalLog");
|
|
10
10
|
const FileManager_1 = require("./FileManager");
|
|
@@ -12,13 +12,9 @@ async function updatePodfile(iosPath) {
|
|
|
12
12
|
const podfile = await FileManager_1.FileManager.readFile(`${iosPath}/Podfile`);
|
|
13
13
|
const matches = podfile.match(iosConstants_1.NSE_PODFILE_REGEX);
|
|
14
14
|
if (matches) {
|
|
15
|
-
OneSignalLog_1.OneSignalLog.log(
|
|
16
|
-
|
|
17
|
-
else {
|
|
18
|
-
fs_1.default.appendFile(`${iosPath}/Podfile`, iosConstants_1.NSE_PODFILE_SNIPPET, (err) => {
|
|
19
|
-
if (err) {
|
|
20
|
-
OneSignalLog_1.OneSignalLog.error('Error writing to Podfile');
|
|
21
|
-
}
|
|
22
|
-
});
|
|
15
|
+
OneSignalLog_1.OneSignalLog.log(`${iosConstants_1.NSE_TARGET_NAME} target already added to Podfile. Skipping...`);
|
|
16
|
+
return;
|
|
23
17
|
}
|
|
18
|
+
await promises_1.default.appendFile(`${iosPath}/Podfile`, iosConstants_1.NSE_PODFILE_SNIPPET);
|
|
19
|
+
OneSignalLog_1.OneSignalLog.log(`${iosConstants_1.NSE_TARGET_NAME} target added to Podfile.`);
|
|
24
20
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OneSignalPluginProps refer to the properties set by the user in their app config file (e.g: app.json)
|
|
3
|
+
*/
|
|
4
|
+
export type OneSignalPluginProps = {
|
|
5
|
+
/**
|
|
6
|
+
* (required) Used to configure APNs environment entitlement. "development" or "production"
|
|
7
|
+
*/
|
|
8
|
+
mode: 'development' | 'production';
|
|
9
|
+
/**
|
|
10
|
+
* (optional) Used to configure Apple Team ID. You can find your Apple Team ID by running expo credentials:manager e.g: "91SW8A37CR"
|
|
11
|
+
*/
|
|
12
|
+
devTeam?: string;
|
|
13
|
+
/**
|
|
14
|
+
* (optional) Target IPHONEOS_DEPLOYMENT_TARGET value to be used when adding the iOS NSE. A deployment target is nothing more than
|
|
15
|
+
* the minimum version of the operating system the application can run on. This value should match the value in your Podfile e.g: "12.0".
|
|
16
|
+
*/
|
|
17
|
+
iPhoneDeploymentTarget?: string;
|
|
18
|
+
/**
|
|
19
|
+
* (optional) The small notification icons for Android. Images will be automatically scaled up/down, the recommended size
|
|
20
|
+
* is 96x96 to always scale down.
|
|
21
|
+
*/
|
|
22
|
+
smallIcons?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* (optional) The accent color to use for notification icons on Android. Must be a valid Android color resource, for example: "#FF0000"
|
|
25
|
+
*/
|
|
26
|
+
smallIconAccentColor?: string;
|
|
27
|
+
/**
|
|
28
|
+
* (optional) The large notification icons for Android. Images will be automatically scaled up/down to 256x256.
|
|
29
|
+
*/
|
|
30
|
+
largeIcons?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* (optional) The local path to a custom Notification Service Extension (NSE), written in Objective-C. The NSE will typically start as a copy
|
|
33
|
+
* of the default NSE found at (support/serviceExtensionFiles/NotificationService.m, then altered to support any custom
|
|
34
|
+
* logic required.
|
|
35
|
+
*/
|
|
36
|
+
iosNSEFilePath?: string;
|
|
37
|
+
/**
|
|
38
|
+
* (optional) Used to configure a custom iOS app group name. If not provided, defaults to "group.{ios.bundleIdentifier}.onesignal".
|
|
39
|
+
* @see https://documentation.onesignal.com/docs/ios-sdk-setup#step-3-create-an-app-group
|
|
40
|
+
*/
|
|
41
|
+
appGroupName?: string;
|
|
42
|
+
/**
|
|
43
|
+
* (optional) Used to configure a custom bundle identifier suffix for the iOS Notification Service Extension.
|
|
44
|
+
* The full bundle identifier will be "{ios.bundleIdentifier}.{nseBundleIdentifier}".
|
|
45
|
+
* If not provided, defaults to "OneSignalNotificationServiceExtension".
|
|
46
|
+
*/
|
|
47
|
+
nseBundleIdentifier?: string;
|
|
48
|
+
/**
|
|
49
|
+
* (optional) If true, the iOS Notification Service Extension (NSE) will not be added to the project.
|
|
50
|
+
* The NSE is required for badges, confirmed delivery, media attachments, and action buttons.
|
|
51
|
+
* Only disable if you only need basic push notifications.
|
|
52
|
+
*/
|
|
53
|
+
disableNSE?: boolean;
|
|
54
|
+
};
|
|
55
|
+
export declare const ONESIGNAL_PLUGIN_PROPS: string[];
|
package/build/types/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ONESIGNAL_PLUGIN_PROPS = void 0;
|
|
4
4
|
exports.ONESIGNAL_PLUGIN_PROPS = [
|
|
5
5
|
'mode',
|
|
6
6
|
'devTeam',
|
|
@@ -10,9 +10,6 @@ exports.ONESIGNAL_PLUGIN_PROPS = [
|
|
|
10
10
|
'iosNSEFilePath',
|
|
11
11
|
'smallIconAccentColor',
|
|
12
12
|
'appGroupName',
|
|
13
|
+
'nseBundleIdentifier',
|
|
14
|
+
'disableNSE',
|
|
13
15
|
];
|
|
14
|
-
var Mode;
|
|
15
|
-
(function (Mode) {
|
|
16
|
-
Mode["Dev"] = "development";
|
|
17
|
-
Mode["Prod"] = "production";
|
|
18
|
-
})(Mode || (exports.Mode = Mode = {}));
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "onesignal-expo-plugin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Some Changez",
|
|
5
5
|
"main": "./app.plugin.js",
|
|
6
|
+
"types": "./build/types/types.d.ts",
|
|
6
7
|
"files": [
|
|
7
8
|
"build",
|
|
8
9
|
"app.plugin.js"
|
|
@@ -10,11 +11,15 @@
|
|
|
10
11
|
"scripts": {
|
|
11
12
|
"test": "bun test",
|
|
12
13
|
"test:coverage": "bun test --coverage",
|
|
13
|
-
"build": "
|
|
14
|
-
"format:
|
|
15
|
-
"format:
|
|
14
|
+
"build": "rm -rf build && tsc && cp -a src/support/serviceExtensionFiles build/support/",
|
|
15
|
+
"format:spotless": "./examples/demo/android/gradlew spotlessApply",
|
|
16
|
+
"format:prettier": "prettier --write \"**/*.{ts,tsx}\" --ignore-path .gitignore",
|
|
17
|
+
"format": "concurrently \"bun run format:spotless\" \"bun run format:prettier\"",
|
|
18
|
+
"format:check:spotless": "./examples/demo/android/gradlew spotlessCheck",
|
|
19
|
+
"format:check:prettier": "prettier --check \"**/*.{ts,tsx}\" --ignore-path .gitignore",
|
|
20
|
+
"format:check": "concurrently \"bun run format:check:spotless\" \"bun run format:check:prettier\"",
|
|
16
21
|
"lint": "oxlint src examples && bun run format:check",
|
|
17
|
-
"lint:fix": "oxlint src examples --fix && bun run format
|
|
22
|
+
"lint:fix": "oxlint src examples --fix && bun run format"
|
|
18
23
|
},
|
|
19
24
|
"repository": {
|
|
20
25
|
"type": "git",
|
|
@@ -42,11 +47,15 @@
|
|
|
42
47
|
"homepage": "https://github.com/OneSignal/onesignal-expo-plugin#readme",
|
|
43
48
|
"devDependencies": {
|
|
44
49
|
"@types/bun": "^1.3.9",
|
|
50
|
+
"concurrently": "^9.2.1",
|
|
45
51
|
"expo-module-scripts": "^5.0.8",
|
|
46
52
|
"oxlint": "^1.43.0",
|
|
47
53
|
"prettier": "^3.8.1",
|
|
48
54
|
"typescript": "^5.9.3"
|
|
49
55
|
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"react-native-onesignal": ">=5.0.0"
|
|
58
|
+
},
|
|
50
59
|
"dependencies": {
|
|
51
60
|
"@expo/image-utils": "^0.8.8"
|
|
52
61
|
}
|