doopush-react-native-sdk 0.1.2 → 0.5.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/README.md +71 -34
- package/android/build.gradle +9 -7
- package/android/src/main/java/com/doopush/reactnative/DooPushReactNativeSDKModule.kt +188 -28
- package/build/DooPush.d.ts +44 -7
- package/build/DooPush.d.ts.map +1 -1
- package/build/DooPush.js +76 -1
- package/build/DooPush.js.map +1 -1
- package/build/events.d.ts +7 -4
- package/build/events.d.ts.map +1 -1
- package/build/events.js +5 -2
- package/build/events.js.map +1 -1
- package/build/hooks.d.ts +34 -0
- package/build/hooks.d.ts.map +1 -0
- package/build/hooks.js +138 -0
- package/build/hooks.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/types.d.ts +28 -1
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/ios/DooPushReactNativeSDK.podspec +1 -3
- package/ios/DooPushReactNativeSDKModule.swift +169 -4
- package/package.json +13 -8
- package/plugin/build/android/withAndroid.js +6 -0
- package/plugin/build/android/withAppBuildGradle.js +71 -30
- package/plugin/build/android/withGoogleServices.js +74 -12
- package/plugin/build/android/withGradleProperties.d.ts +3 -0
- package/plugin/build/android/withGradleProperties.js +26 -0
- package/plugin/build/android/withOppoManifest.d.ts +3 -0
- package/plugin/build/android/withOppoManifest.js +61 -0
- package/plugin/build/android/withRootBuildGradle.d.ts +2 -2
- package/plugin/build/android/withRootBuildGradle.js +65 -10
- package/plugin/build/android/withSettingsGradle.d.ts +8 -0
- package/plugin/build/android/withSettingsGradle.js +33 -0
- package/plugin/build/ios/withIOS.js +2 -0
- package/plugin/build/ios/withPodfile.d.ts +8 -0
- package/plugin/build/ios/withPodfile.js +48 -0
- package/plugin/build/schema.d.ts +327 -1
- package/plugin/build/schema.js +82 -1
|
@@ -4,10 +4,10 @@ import UserNotifications
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* DooPush React Native SDK — iOS bridge
|
|
7
|
-
* v0.
|
|
7
|
+
* v0.5.0
|
|
8
8
|
*
|
|
9
9
|
* Mode: ACTIVE (default) — DooPush owns UNUserNotificationCenterDelegate via the
|
|
10
|
-
* delegate-forwarding mechanism
|
|
10
|
+
* delegate-forwarding mechanism in DooPushSDK. Coexists with
|
|
11
11
|
* expo-notifications because both delegates forward to each other.
|
|
12
12
|
*/
|
|
13
13
|
public class DooPushReactNativeSDKModule: Module, DooPushDelegate {
|
|
@@ -15,7 +15,16 @@ public class DooPushReactNativeSDKModule: Module, DooPushDelegate {
|
|
|
15
15
|
public func definition() -> ModuleDefinition {
|
|
16
16
|
Name("DooPushReactNativeSDK")
|
|
17
17
|
|
|
18
|
-
Events(
|
|
18
|
+
Events(
|
|
19
|
+
"onRegister",
|
|
20
|
+
"onRegisterError",
|
|
21
|
+
"onMessage",
|
|
22
|
+
"onNotificationClick",
|
|
23
|
+
"onNotificationOpen",
|
|
24
|
+
"onGatewayOpen",
|
|
25
|
+
"onGatewayClosed",
|
|
26
|
+
"onGatewayError"
|
|
27
|
+
)
|
|
19
28
|
|
|
20
29
|
OnCreate {
|
|
21
30
|
// Wire DooPush's delegate to this module so we can forward events to JS.
|
|
@@ -61,7 +70,12 @@ public class DooPushReactNativeSDKModule: Module, DooPushDelegate {
|
|
|
61
70
|
|
|
62
71
|
// ── registerWithToken ───────────────────────────────────────────
|
|
63
72
|
AsyncFunction("registerWithToken") { (token: String, vendor: String, promise: Promise) in
|
|
64
|
-
|
|
73
|
+
let allowedVendors: Set<String> = ["apns", "fcm", "hms", "honor", "xiaomi", "oppo", "vivo", "meizu"]
|
|
74
|
+
guard allowedVendors.contains(vendor.lowercased()) else {
|
|
75
|
+
promise.reject("E_INVALID_VENDOR", "vendor must be one of: \(allowedVendors.sorted().joined(separator: ", "))")
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
DooPushManager.shared.registerDevice(withToken: token, vendor: vendor.lowercased()) { deviceId, error in
|
|
65
79
|
if let error = error {
|
|
66
80
|
promise.reject("E_REGISTER", error.localizedDescription)
|
|
67
81
|
return
|
|
@@ -78,6 +92,97 @@ public class DooPushReactNativeSDKModule: Module, DooPushDelegate {
|
|
|
78
92
|
AsyncFunction("getDeviceId") { () -> String? in
|
|
79
93
|
return DooPushManager.shared.getDeviceId()
|
|
80
94
|
}
|
|
95
|
+
|
|
96
|
+
AsyncFunction("getDeviceInfo") { () -> [String: Any] in
|
|
97
|
+
return normalizeDeviceInfo(DooPushManager.shared.getDeviceInfo())
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
AsyncFunction("updateDeviceInfo") { (promise: Promise) in
|
|
101
|
+
DooPushManager.shared.updateDeviceInfo()
|
|
102
|
+
promise.resolve(nil)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
AsyncFunction("reportStatistics") { (promise: Promise) in
|
|
106
|
+
DooPushManager.shared.reportStatistics()
|
|
107
|
+
promise.resolve(nil)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
AsyncFunction("checkPermissionStatus") { (promise: Promise) in
|
|
111
|
+
DooPushManager.shared.checkPushPermissionStatus { status in
|
|
112
|
+
promise.resolve(self.normalizePermissionStatus(status))
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
AsyncFunction("setBadge") { (count: Int, promise: Promise) in
|
|
117
|
+
guard count >= 0 else {
|
|
118
|
+
promise.reject("E_BADGE", "badge count must be >= 0")
|
|
119
|
+
return
|
|
120
|
+
}
|
|
121
|
+
DooPushManager.shared.setBadgeNumber(count) { error in
|
|
122
|
+
if let error = error {
|
|
123
|
+
promise.reject("E_BADGE", error.localizedDescription)
|
|
124
|
+
} else {
|
|
125
|
+
promise.resolve(true)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
AsyncFunction("clearBadge") { (promise: Promise) in
|
|
131
|
+
DooPushManager.shared.clearBadge { error in
|
|
132
|
+
if let error = error {
|
|
133
|
+
promise.reject("E_BADGE", error.localizedDescription)
|
|
134
|
+
} else {
|
|
135
|
+
promise.resolve(true)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
AsyncFunction("getBadge") { () -> Int in
|
|
141
|
+
return DooPushManager.shared.getCurrentBadgeNumber()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ── notification management / coexistence ───────────────────────
|
|
145
|
+
Function("setNotificationManagementMode") { (mode: String) in
|
|
146
|
+
switch mode.lowercased() {
|
|
147
|
+
case "active":
|
|
148
|
+
DooPushManager.shared.setNotificationManagementMode(.active)
|
|
149
|
+
DooPushManager.shared.enableAutomaticNotificationTracking()
|
|
150
|
+
case "passive":
|
|
151
|
+
DooPushManager.shared.setNotificationManagementMode(.passive)
|
|
152
|
+
DooPushManager.shared.disableAutomaticNotificationTracking()
|
|
153
|
+
default:
|
|
154
|
+
throw NSError(
|
|
155
|
+
domain: "DooPushReactNativeSDK",
|
|
156
|
+
code: -2,
|
|
157
|
+
userInfo: [NSLocalizedDescriptionKey: "mode must be 'active' or 'passive'"]
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Function("setExpoNotificationRelayEnabled") { (_ enabled: Bool) in
|
|
163
|
+
// iOS uses UNUserNotificationCenter delegate forwarding; no explicit relay flag is needed.
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
Function("setNotificationDisplayEnabled") { (enabled: Bool) in
|
|
167
|
+
// iOS notification presentation is controlled by UNUserNotificationCenter and APNs.
|
|
168
|
+
// Keep this API as a no-op for cross-platform compatibility; use
|
|
169
|
+
// setNotificationManagementMode('passive') to disable DooPush delegate tracking.
|
|
170
|
+
NSLog("[DooPushReactNativeSDK] setNotificationDisplayEnabled(\(enabled)) is a no-op on iOS")
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
AsyncFunction("connectGateway") { (promise: Promise) in
|
|
174
|
+
guard DooPushManager.shared.getDeviceToken()?.isEmpty == false else {
|
|
175
|
+
promise.reject("E_GATEWAY", "device token is required before connecting gateway")
|
|
176
|
+
return
|
|
177
|
+
}
|
|
178
|
+
DooPushManager.shared.connectWebSocket()
|
|
179
|
+
promise.resolve(nil)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
AsyncFunction("disconnectGateway") { (promise: Promise) in
|
|
183
|
+
DooPushManager.shared.disconnectWebSocket()
|
|
184
|
+
promise.resolve(nil)
|
|
185
|
+
}
|
|
81
186
|
}
|
|
82
187
|
|
|
83
188
|
// MARK: - DooPushDelegate
|
|
@@ -101,8 +206,68 @@ public class DooPushReactNativeSDKModule: Module, DooPushDelegate {
|
|
|
101
206
|
])
|
|
102
207
|
}
|
|
103
208
|
|
|
209
|
+
public func dooPush(_ manager: DooPushManager, didClickNotification userInfo: [AnyHashable: Any]) {
|
|
210
|
+
sendEvent("onNotificationClick", normalizeMessage(userInfo))
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public func dooPush(_ manager: DooPushManager, didOpenNotification userInfo: [AnyHashable: Any]) {
|
|
214
|
+
sendEvent("onNotificationOpen", normalizeMessage(userInfo))
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public func dooPushGatewayDidOpen(_ manager: DooPushManager) {
|
|
218
|
+
sendEvent("onGatewayOpen", ["connected": true])
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public func dooPush(_ manager: DooPushManager, gatewayDidCloseWithCode code: Int, reason: String?) {
|
|
222
|
+
var payload: [String: Any] = ["code": code]
|
|
223
|
+
if let reason = reason {
|
|
224
|
+
payload["reason"] = reason
|
|
225
|
+
}
|
|
226
|
+
sendEvent("onGatewayClosed", payload)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public func dooPush(_ manager: DooPushManager, gatewayDidFailWithError error: Error) {
|
|
230
|
+
sendEvent("onGatewayError", [
|
|
231
|
+
"code": "E_GATEWAY",
|
|
232
|
+
"message": error.localizedDescription
|
|
233
|
+
])
|
|
234
|
+
}
|
|
235
|
+
|
|
104
236
|
// MARK: - Helpers
|
|
105
237
|
|
|
238
|
+
|
|
239
|
+
private func normalizeDeviceInfo(_ deviceInfo: DeviceInfo) -> [String: Any] {
|
|
240
|
+
return [
|
|
241
|
+
"platform": deviceInfo.platform,
|
|
242
|
+
"channel": deviceInfo.channel,
|
|
243
|
+
"bundleId": deviceInfo.bundleId,
|
|
244
|
+
"brand": deviceInfo.brand,
|
|
245
|
+
"model": deviceInfo.model,
|
|
246
|
+
"systemVersion": deviceInfo.systemVersion,
|
|
247
|
+
"appVersion": deviceInfo.appVersion,
|
|
248
|
+
"userAgent": deviceInfo.userAgent
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private func normalizePermissionStatus(_ status: UNAuthorizationStatus) -> String {
|
|
253
|
+
if #available(iOS 14.0, *), status == .ephemeral {
|
|
254
|
+
return "ephemeral"
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
switch status {
|
|
258
|
+
case .authorized:
|
|
259
|
+
return "authorized"
|
|
260
|
+
case .denied:
|
|
261
|
+
return "denied"
|
|
262
|
+
case .notDetermined:
|
|
263
|
+
return "notDetermined"
|
|
264
|
+
case .provisional:
|
|
265
|
+
return "provisional"
|
|
266
|
+
@unknown default:
|
|
267
|
+
return "unknown"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
106
271
|
/// Convert APNs userInfo into the JS-side DooPushMessage shape.
|
|
107
272
|
private func normalizeMessage(_ userInfo: [AnyHashable: Any]) -> [String: Any] {
|
|
108
273
|
var data: [String: String] = [:]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doopush-react-native-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "React Native SDK for DooPush push notification service. Built with Expo Modules API; works in Expo (managed/prebuild) and bare RN.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -13,6 +13,14 @@
|
|
|
13
13
|
"app.plugin.js",
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc && pnpm --filter ./plugin build",
|
|
18
|
+
"build:plugin": "tsc -p plugin/tsconfig.json",
|
|
19
|
+
"test": "pnpm --filter ./plugin test",
|
|
20
|
+
"clean": "rm -rf build plugin/build",
|
|
21
|
+
"prepare": "pnpm build",
|
|
22
|
+
"prepublishOnly": "pnpm clean && pnpm build && pnpm test"
|
|
23
|
+
},
|
|
16
24
|
"keywords": [
|
|
17
25
|
"react-native",
|
|
18
26
|
"expo",
|
|
@@ -26,6 +34,9 @@
|
|
|
26
34
|
"url": "https://github.com/doopush/doopush-react-native-sdk"
|
|
27
35
|
},
|
|
28
36
|
"license": "MIT",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"zod": "^3.22.0"
|
|
39
|
+
},
|
|
29
40
|
"peerDependencies": {
|
|
30
41
|
"expo": "*",
|
|
31
42
|
"react": "*",
|
|
@@ -38,11 +49,5 @@
|
|
|
38
49
|
"react": "18.2.0",
|
|
39
50
|
"react-native": "0.73.0",
|
|
40
51
|
"typescript": "^5.3.0"
|
|
41
|
-
},
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsc && pnpm --filter ./plugin build",
|
|
44
|
-
"build:plugin": "tsc -p plugin/tsconfig.json",
|
|
45
|
-
"test": "pnpm --filter ./plugin test",
|
|
46
|
-
"clean": "rm -rf build plugin/build"
|
|
47
52
|
}
|
|
48
|
-
}
|
|
53
|
+
}
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withAndroid = void 0;
|
|
4
4
|
const withRootBuildGradle_1 = require("./withRootBuildGradle");
|
|
5
|
+
const withSettingsGradle_1 = require("./withSettingsGradle");
|
|
5
6
|
const withAppBuildGradle_1 = require("./withAppBuildGradle");
|
|
7
|
+
const withGradleProperties_1 = require("./withGradleProperties");
|
|
6
8
|
const withGoogleServices_1 = require("./withGoogleServices");
|
|
9
|
+
const withOppoManifest_1 = require("./withOppoManifest");
|
|
7
10
|
const withAndroid = (config, validated) => {
|
|
11
|
+
config = (0, withSettingsGradle_1.withDooPushSettingsGradle)(config, validated);
|
|
12
|
+
config = (0, withGradleProperties_1.withDooPushGradleProperties)(config, validated);
|
|
8
13
|
config = (0, withRootBuildGradle_1.withDooPushRootBuildGradle)(config, validated);
|
|
9
14
|
config = (0, withAppBuildGradle_1.withDooPushAppBuildGradle)(config, validated);
|
|
10
15
|
config = (0, withGoogleServices_1.withDooPushGoogleServices)(config, validated);
|
|
16
|
+
config = (0, withOppoManifest_1.withDooPushOppoManifest)(config, validated);
|
|
11
17
|
return config;
|
|
12
18
|
};
|
|
13
19
|
exports.withAndroid = withAndroid;
|
|
@@ -2,39 +2,80 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withDooPushAppBuildGradle = void 0;
|
|
4
4
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
-
|
|
6
|
-
'
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
function q(value) {
|
|
6
|
+
return `"${(value !== null && value !== void 0 ? value : '').replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
7
|
+
}
|
|
8
|
+
function addApplyPlugin(contents, pluginId) {
|
|
9
|
+
const line = `apply plugin: '${pluginId}'`;
|
|
10
|
+
if (contents.includes(line) || contents.includes(`id '${pluginId}'`) || contents.includes(`id("${pluginId}")`)) {
|
|
11
|
+
return contents;
|
|
12
|
+
}
|
|
13
|
+
return `${contents.trimEnd()}\n${line}\n`;
|
|
14
|
+
}
|
|
15
|
+
function addDependency(contents, dependency) {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
const artifact = (_b = (_a = dependency.match(/'([^:]+:[^:]+):/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : dependency;
|
|
18
|
+
if (contents.includes(artifact))
|
|
19
|
+
return contents;
|
|
20
|
+
return contents.replace(/dependencies\s*{/, `dependencies {\n ${dependency}`);
|
|
21
|
+
}
|
|
22
|
+
function mergeManifestPlaceholders(contents, placeholderValues) {
|
|
23
|
+
const entries = Object.entries(placeholderValues)
|
|
24
|
+
.map(([key, value]) => `${key}: ${q(value)}`);
|
|
25
|
+
if (entries.length === 0)
|
|
26
|
+
return contents;
|
|
27
|
+
const doopushMap = entries.join(', ');
|
|
28
|
+
const doopushLine = `manifestPlaceholders += [${doopushMap}]`;
|
|
29
|
+
// Idempotency: if all DooPush keys already exist somewhere, do not inject again.
|
|
30
|
+
if (entries.every((entry) => contents.includes(entry.split(':')[0]))) {
|
|
31
|
+
return contents;
|
|
32
|
+
}
|
|
33
|
+
const defaultConfigMatch = contents.match(/defaultConfig\s*{/);
|
|
34
|
+
if (!defaultConfigMatch || defaultConfigMatch.index === undefined) {
|
|
35
|
+
return contents;
|
|
36
|
+
}
|
|
37
|
+
const insertAt = defaultConfigMatch.index + defaultConfigMatch[0].length;
|
|
38
|
+
return `${contents.slice(0, insertAt)}\n ${doopushLine}${contents.slice(insertAt)}`;
|
|
39
|
+
}
|
|
17
40
|
const withDooPushAppBuildGradle = (config, validated) => {
|
|
18
41
|
return (0, config_plugins_1.withAppBuildGradle)(config, (cfg) => {
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
19
43
|
let contents = cfg.modResults.contents;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
const v = validated.android.vendors;
|
|
45
|
+
// 1. Apply vendor Gradle plugins where required by the upstream SDKs.
|
|
46
|
+
if (v.fcm)
|
|
47
|
+
contents = addApplyPlugin(contents, 'com.google.gms.google-services');
|
|
48
|
+
if (v.hms)
|
|
49
|
+
contents = addApplyPlugin(contents, 'com.huawei.agconnect');
|
|
50
|
+
if (v.honor)
|
|
51
|
+
contents = addApplyPlugin(contents, 'com.hihonor.mcs.asplugin');
|
|
52
|
+
// 2. Merge DooPush manifest placeholders into defaultConfig, even if the host
|
|
53
|
+
// project or another plugin already defines manifestPlaceholders.
|
|
54
|
+
contents = mergeManifestPlaceholders(contents, {
|
|
55
|
+
DOOPUSH_MI_APP_ID: (_a = v.xiaomi) === null || _a === void 0 ? void 0 : _a.appId,
|
|
56
|
+
DOOPUSH_MI_APP_KEY: (_b = v.xiaomi) === null || _b === void 0 ? void 0 : _b.appKey,
|
|
57
|
+
DOOPUSH_OPPO_APP_KEY: (_c = v.oppo) === null || _c === void 0 ? void 0 : _c.appKey,
|
|
58
|
+
DOOPUSH_OPPO_APP_SECRET: (_d = v.oppo) === null || _d === void 0 ? void 0 : _d.appSecret,
|
|
59
|
+
DOOPUSH_VIVO_APP_ID: (_e = v.vivo) === null || _e === void 0 ? void 0 : _e.appId,
|
|
60
|
+
DOOPUSH_VIVO_API_KEY: (_f = v.vivo) === null || _f === void 0 ? void 0 : _f.apiKey,
|
|
61
|
+
DOOPUSH_MEIZU_APP_ID: (_g = v.meizu) === null || _g === void 0 ? void 0 : _g.appId,
|
|
62
|
+
DOOPUSH_MEIZU_APP_KEY: (_h = v.meizu) === null || _h === void 0 ? void 0 : _h.appKey,
|
|
63
|
+
DOOPUSH_HONOR_APP_ID: (_j = v.honor) === null || _j === void 0 ? void 0 : _j.appId,
|
|
64
|
+
DOOPUSH_HONOR_DEVELOPER_ID: (_k = v.honor) === null || _k === void 0 ? void 0 : _k.developerId,
|
|
65
|
+
});
|
|
66
|
+
// 3. Inject DooPush Android SDK dependency if not present.
|
|
67
|
+
contents = addDependency(contents, "implementation 'com.doopush:android-sdk:1.2.0'");
|
|
68
|
+
const vendorDependencies = [
|
|
69
|
+
[!!v.hms, "implementation 'com.huawei.hms:push:6.11.0.300'"],
|
|
70
|
+
[!!v.honor, "implementation 'com.hihonor.mcs:push:8.0.12.307'"],
|
|
71
|
+
[!!v.xiaomi, "implementation 'com.umeng.umsdk:xiaomi-push:6.0.1'"],
|
|
72
|
+
[!!v.oppo, "implementation 'com.umeng.umsdk:oppo-push:3.5.3'"],
|
|
73
|
+
[!!v.vivo, "implementation 'com.umeng.umsdk:vivo-push:4.0.6.0'"],
|
|
74
|
+
[!!v.meizu, "implementation 'com.umeng.umsdk:meizu-push:5.0.3'"],
|
|
75
|
+
];
|
|
76
|
+
for (const [enabled, dependency] of vendorDependencies) {
|
|
77
|
+
if (enabled)
|
|
78
|
+
contents = addDependency(contents, dependency);
|
|
38
79
|
}
|
|
39
80
|
cfg.modResults.contents = contents;
|
|
40
81
|
return cfg;
|
|
@@ -37,25 +37,87 @@ exports.withDooPushGoogleServices = void 0;
|
|
|
37
37
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
|
+
function addCopy(jobs, source, destRelative, label) {
|
|
41
|
+
if (source)
|
|
42
|
+
jobs.push({ source, destRelative, label });
|
|
43
|
+
}
|
|
44
|
+
function addWrite(jobs, contents, destRelative, label) {
|
|
45
|
+
const filtered = Object.fromEntries(Object.entries(contents).filter(([, value]) => value !== undefined && value !== ''));
|
|
46
|
+
if (Object.keys(filtered).length > 0)
|
|
47
|
+
jobs.push({ contents: filtered, destRelative, label });
|
|
48
|
+
}
|
|
40
49
|
const withDooPushGoogleServices = (config, validated) => {
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
51
|
+
const vendors = validated.android.vendors;
|
|
52
|
+
const copyJobs = [];
|
|
53
|
+
const writeJobs = [];
|
|
54
|
+
addCopy(copyJobs, (_a = vendors.fcm) === null || _a === void 0 ? void 0 : _a.googleServicesFile, 'google-services.json', 'google-services.json');
|
|
55
|
+
if ((_b = vendors.hms) === null || _b === void 0 ? void 0 : _b.agconnectServicesFile) {
|
|
56
|
+
addCopy(copyJobs, vendors.hms.agconnectServicesFile, 'agconnect-services.json', 'agconnect-services.json');
|
|
57
|
+
addCopy(copyJobs, vendors.hms.agconnectServicesFile, path.join('src', 'main', 'assets', 'agconnect-services.json'), 'agconnect-services.json');
|
|
58
|
+
}
|
|
59
|
+
if ((_c = vendors.honor) === null || _c === void 0 ? void 0 : _c.mcsServicesFile) {
|
|
60
|
+
addCopy(copyJobs, vendors.honor.mcsServicesFile, 'mcs-services.json', 'mcs-services.json');
|
|
61
|
+
addCopy(copyJobs, vendors.honor.mcsServicesFile, path.join('src', 'main', 'assets', 'mcs-services.json'), 'mcs-services.json');
|
|
62
|
+
}
|
|
63
|
+
else if (vendors.honor) {
|
|
64
|
+
const honorJson = {
|
|
65
|
+
client_id: vendors.honor.clientId,
|
|
66
|
+
client_secret: vendors.honor.clientSecret,
|
|
67
|
+
app_id: vendors.honor.appId,
|
|
68
|
+
developer_id: vendors.honor.developerId,
|
|
69
|
+
};
|
|
70
|
+
addWrite(writeJobs, honorJson, 'mcs-services.json', 'mcs-services.json');
|
|
71
|
+
addWrite(writeJobs, honorJson, path.join('src', 'main', 'assets', 'mcs-services.json'), 'mcs-services.json');
|
|
72
|
+
}
|
|
73
|
+
if ((_d = vendors.xiaomi) === null || _d === void 0 ? void 0 : _d.servicesFile) {
|
|
74
|
+
addCopy(copyJobs, vendors.xiaomi.servicesFile, path.join('src', 'main', 'assets', 'xiaomi-services.json'), 'xiaomi-services.json');
|
|
75
|
+
}
|
|
76
|
+
else if (vendors.xiaomi) {
|
|
77
|
+
addWrite(writeJobs, { app_id: vendors.xiaomi.appId, app_key: vendors.xiaomi.appKey }, path.join('src', 'main', 'assets', 'xiaomi-services.json'), 'xiaomi-services.json');
|
|
78
|
+
}
|
|
79
|
+
if ((_e = vendors.oppo) === null || _e === void 0 ? void 0 : _e.servicesFile) {
|
|
80
|
+
addCopy(copyJobs, vendors.oppo.servicesFile, path.join('src', 'main', 'assets', 'oppo-services.json'), 'oppo-services.json');
|
|
81
|
+
}
|
|
82
|
+
else if (vendors.oppo) {
|
|
83
|
+
addWrite(writeJobs, { app_key: vendors.oppo.appKey, app_secret: vendors.oppo.appSecret }, path.join('src', 'main', 'assets', 'oppo-services.json'), 'oppo-services.json');
|
|
84
|
+
}
|
|
85
|
+
if ((_f = vendors.vivo) === null || _f === void 0 ? void 0 : _f.servicesFile) {
|
|
86
|
+
addCopy(copyJobs, vendors.vivo.servicesFile, path.join('src', 'main', 'assets', 'vivo-services.json'), 'vivo-services.json');
|
|
87
|
+
}
|
|
88
|
+
else if (vendors.vivo) {
|
|
89
|
+
addWrite(writeJobs, { app_id: vendors.vivo.appId, api_key: vendors.vivo.apiKey }, path.join('src', 'main', 'assets', 'vivo-services.json'), 'vivo-services.json');
|
|
90
|
+
}
|
|
91
|
+
if ((_g = vendors.meizu) === null || _g === void 0 ? void 0 : _g.servicesFile) {
|
|
92
|
+
addCopy(copyJobs, vendors.meizu.servicesFile, path.join('src', 'main', 'assets', 'meizu-services.json'), 'meizu-services.json');
|
|
93
|
+
}
|
|
94
|
+
else if (vendors.meizu) {
|
|
95
|
+
addWrite(writeJobs, { app_id: vendors.meizu.appId, app_key: vendors.meizu.appKey }, path.join('src', 'main', 'assets', 'meizu-services.json'), 'meizu-services.json');
|
|
96
|
+
}
|
|
97
|
+
if (copyJobs.length === 0 && writeJobs.length === 0) {
|
|
98
|
+
return config;
|
|
43
99
|
}
|
|
44
|
-
const sourcePath = validated.android.vendors.fcm.googleServicesFile;
|
|
45
100
|
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
46
101
|
'android',
|
|
47
102
|
async (cfg) => {
|
|
48
103
|
const projectRoot = cfg.modRequest.projectRoot;
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
const appDir = path.join(cfg.modRequest.platformProjectRoot, 'app');
|
|
105
|
+
for (const job of copyJobs) {
|
|
106
|
+
const absSource = path.isAbsolute(job.source)
|
|
107
|
+
? job.source
|
|
108
|
+
: path.resolve(projectRoot, job.source);
|
|
109
|
+
if (!fs.existsSync(absSource)) {
|
|
110
|
+
throw new Error(`[doopush-react-native-sdk] ${job.label} not found at: ${absSource}`);
|
|
111
|
+
}
|
|
112
|
+
const dest = path.join(appDir, job.destRelative);
|
|
113
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
114
|
+
fs.copyFileSync(absSource, dest);
|
|
115
|
+
}
|
|
116
|
+
for (const job of writeJobs) {
|
|
117
|
+
const dest = path.join(appDir, job.destRelative);
|
|
118
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
119
|
+
fs.writeFileSync(dest, `${JSON.stringify(job.contents, null, 2)}\n`);
|
|
54
120
|
}
|
|
55
|
-
const destDir = path.join(cfg.modRequest.platformProjectRoot, 'app');
|
|
56
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
57
|
-
const dest = path.join(destDir, 'google-services.json');
|
|
58
|
-
fs.copyFileSync(absSource, dest);
|
|
59
121
|
return cfg;
|
|
60
122
|
},
|
|
61
123
|
]);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withDooPushGradleProperties = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const MIN_SDK_KEY = 'android.minSdkVersion';
|
|
6
|
+
const DOOPUSH_MIN_SDK = 26;
|
|
7
|
+
const withDooPushGradleProperties = (config) => {
|
|
8
|
+
return (0, config_plugins_1.withGradleProperties)(config, (cfg) => {
|
|
9
|
+
const props = cfg.modResults;
|
|
10
|
+
const existing = props.find((item) => item.type === 'property' && item.key === MIN_SDK_KEY);
|
|
11
|
+
if ((existing === null || existing === void 0 ? void 0 : existing.type) === 'property') {
|
|
12
|
+
const parsed = Number.parseInt(existing.value, 10);
|
|
13
|
+
if (!Number.isNaN(parsed) && parsed >= DOOPUSH_MIN_SDK)
|
|
14
|
+
return cfg;
|
|
15
|
+
existing.value = String(DOOPUSH_MIN_SDK);
|
|
16
|
+
return cfg;
|
|
17
|
+
}
|
|
18
|
+
props.push({
|
|
19
|
+
type: 'property',
|
|
20
|
+
key: MIN_SDK_KEY,
|
|
21
|
+
value: String(DOOPUSH_MIN_SDK),
|
|
22
|
+
});
|
|
23
|
+
return cfg;
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
exports.withDooPushGradleProperties = withDooPushGradleProperties;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withDooPushOppoManifest = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
/**
|
|
6
|
+
* HeyTap MCS(OPPO/ColorOS 推送)要求在 AndroidManifest 声明的权限与回调 service。
|
|
7
|
+
*
|
|
8
|
+
* umeng `oppo-push` 的 aar 自带 manifest 为空(只声明 package),不会贡献这些节点;
|
|
9
|
+
* 其余 vendor 的 aar 自带完整 manifest,所以只有 OPPO 需要 plugin 主动补。缺这些节点时,
|
|
10
|
+
* 系统推送服务收到注册后无处回传 RegisterId,DooPush.register() 会静默超时、拿不到 token。
|
|
11
|
+
*/
|
|
12
|
+
const MCS_PERMISSIONS = [
|
|
13
|
+
'com.coloros.mcs.permission.RECIEVE_MCS_MESSAGE',
|
|
14
|
+
'com.heytap.mcs.permission.RECIEVE_MCS_MESSAGE',
|
|
15
|
+
];
|
|
16
|
+
const MCS_SERVICES = [
|
|
17
|
+
{
|
|
18
|
+
name: 'com.heytap.msp.push.service.CompatibleDataMessageCallbackService',
|
|
19
|
+
permission: 'com.coloros.mcs.permission.SEND_MCS_MESSAGE',
|
|
20
|
+
actions: ['com.coloros.mcs.action.RECEIVE_MCS_MESSAGE'],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'com.heytap.msp.push.service.DataMessageCallbackService',
|
|
24
|
+
permission: 'com.heytap.mcs.permission.SEND_PUSH_MESSAGE',
|
|
25
|
+
actions: [
|
|
26
|
+
'com.heytap.mcs.action.RECEIVE_MCS_MESSAGE',
|
|
27
|
+
'com.heytap.msp.push.RECEIVE_MCS_MESSAGE',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
const withDooPushOppoManifest = (config, validated) => {
|
|
32
|
+
// service 类来自 oppo-push 依赖,仅在启用 OPPO vendor 时注入。
|
|
33
|
+
if (!validated.android.vendors.oppo) {
|
|
34
|
+
return config;
|
|
35
|
+
}
|
|
36
|
+
return (0, config_plugins_1.withAndroidManifest)(config, (cfg) => {
|
|
37
|
+
var _a;
|
|
38
|
+
config_plugins_1.AndroidConfig.Permissions.ensurePermissions(cfg.modResults, MCS_PERMISSIONS);
|
|
39
|
+
const application = config_plugins_1.AndroidConfig.Manifest.getMainApplication(cfg.modResults);
|
|
40
|
+
if (!application)
|
|
41
|
+
return cfg;
|
|
42
|
+
application.service = (_a = application.service) !== null && _a !== void 0 ? _a : [];
|
|
43
|
+
for (const svc of MCS_SERVICES) {
|
|
44
|
+
const exists = application.service.some((s) => { var _a; return ((_a = s.$) === null || _a === void 0 ? void 0 : _a['android:name']) === svc.name; });
|
|
45
|
+
if (exists)
|
|
46
|
+
continue;
|
|
47
|
+
application.service.push({
|
|
48
|
+
$: {
|
|
49
|
+
'android:name': svc.name,
|
|
50
|
+
'android:permission': svc.permission,
|
|
51
|
+
'android:exported': 'true',
|
|
52
|
+
},
|
|
53
|
+
'intent-filter': [
|
|
54
|
+
{ action: svc.actions.map((a) => ({ $: { 'android:name': a } })) },
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return cfg;
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
exports.withDooPushOppoManifest = withDooPushOppoManifest;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
2
|
import type { PluginConfig } from '../schema';
|
|
3
3
|
/**
|
|
4
|
-
* Adds Maven repositories
|
|
5
|
-
* Idempotent.
|
|
4
|
+
* Adds Maven repositories and vendor Gradle plugin classpaths to root build.gradle.
|
|
5
|
+
* Idempotent. Supports the Groovy build.gradle generated by Expo prebuild.
|
|
6
6
|
*/
|
|
7
7
|
export declare const withDooPushRootBuildGradle: ConfigPlugin<PluginConfig>;
|