react-native-update 9.1.5 → 10.0.0-beta.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/android/build.gradle +23 -0
- package/android/src/main/AndroidManifest.xml +0 -1
- package/android/src/main/AndroidManifestNew.xml +14 -0
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +1 -1
- package/package.json +10 -5
- package/react-native-update.podspec +23 -1
- package/src/client.tsx +316 -0
- package/src/context.ts +30 -0
- package/src/core.ts +106 -0
- package/src/index.ts +3 -0
- package/src/index.web.js +17 -0
- package/src/provider.tsx +184 -0
- package/{lib/NativeUpdate.ts → src/turboModuleSpec.ts} +0 -2
- package/{lib → src}/type.ts +17 -5
- package/{lib → src}/utils.ts +2 -2
- package/lib/endpoint.ts +0 -53
- package/lib/index.ts +0 -2
- package/lib/index.web.js +0 -18
- package/lib/main.ts +0 -398
- package/lib/simpleUpdate.tsx +0 -135
package/android/build.gradle
CHANGED
|
@@ -9,6 +9,19 @@ def isNewArchitectureEnabled() {
|
|
|
9
9
|
return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
def supportsNamespace() {
|
|
13
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
14
|
+
def major = parsed[0].toInteger()
|
|
15
|
+
def minor = parsed[1].toInteger()
|
|
16
|
+
|
|
17
|
+
// Namespace support was added in 7.3.0
|
|
18
|
+
if (major == 7 && minor >= 3) {
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return major >= 8
|
|
23
|
+
}
|
|
24
|
+
|
|
12
25
|
apply plugin: 'com.android.library'
|
|
13
26
|
if (isNewArchitectureEnabled()) {
|
|
14
27
|
apply plugin: 'com.facebook.react'
|
|
@@ -16,6 +29,16 @@ if (isNewArchitectureEnabled()) {
|
|
|
16
29
|
|
|
17
30
|
|
|
18
31
|
android {
|
|
32
|
+
|
|
33
|
+
if (supportsNamespace()) {
|
|
34
|
+
namespace "cn.reactnative.modules.update"
|
|
35
|
+
|
|
36
|
+
sourceSets {
|
|
37
|
+
main {
|
|
38
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
19
42
|
compileSdkVersion safeExtGet('compileSdkVersion', 28)
|
|
20
43
|
buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
|
|
21
44
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<application>
|
|
3
|
+
<meta-data android:name="pushy_build_time" android:value="@string/pushy_build_time" />
|
|
4
|
+
<provider
|
|
5
|
+
android:name=".PushyFileProvider"
|
|
6
|
+
android:authorities="${applicationId}.pushy.fileprovider"
|
|
7
|
+
android:exported="false"
|
|
8
|
+
android:grantUriPermissions="true">
|
|
9
|
+
<meta-data
|
|
10
|
+
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
11
|
+
android:resource="@xml/pushy_file_paths" />
|
|
12
|
+
</provider>
|
|
13
|
+
</application>
|
|
14
|
+
</manifest>
|
|
@@ -57,7 +57,7 @@ public class UpdateModule extends NativeUpdateSpec {
|
|
|
57
57
|
|
|
58
58
|
@Override
|
|
59
59
|
public void downloadFullUpdate(ReadableMap options, final Promise promise) {
|
|
60
|
-
|
|
60
|
+
UpdateModuleImpl.downloadFullUpdate(this.updateContext,options,promise);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
@Override
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0-beta.0",
|
|
4
4
|
"description": "react-native hot update",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "src/index.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepublish": "yarn submodule",
|
|
8
8
|
"submodule": "git submodule update --init --recursive",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"url": "https://github.com/reactnativecn/react-native-pushy/issues"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
+
"react": ">=16.8.0",
|
|
42
43
|
"react-native": ">=0.57.0"
|
|
43
44
|
},
|
|
44
45
|
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
|
|
@@ -55,17 +56,21 @@
|
|
|
55
56
|
]
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
59
|
+
"@react-native/eslint-config": "^0.73.2",
|
|
58
60
|
"@types/fs-extra": "^9.0.13",
|
|
59
61
|
"@types/jest": "^29.2.1",
|
|
60
62
|
"@types/node": "^20.8.9",
|
|
61
|
-
"@types/react": "^18.2.
|
|
63
|
+
"@types/react": "^18.2.46",
|
|
62
64
|
"detox": "^20.5.0",
|
|
65
|
+
"eslint": "^8.56.0",
|
|
63
66
|
"firebase-tools": "^11.24.1",
|
|
64
67
|
"fs-extra": "^9.1.0",
|
|
65
68
|
"jest": "^29.2.1",
|
|
66
69
|
"pod-install": "^0.1.37",
|
|
67
|
-
"
|
|
70
|
+
"prettier": "^2",
|
|
71
|
+
"react": "18.2.0",
|
|
72
|
+
"react-native": "0.73",
|
|
68
73
|
"ts-jest": "^29.0.3",
|
|
69
|
-
"typescript": "^5.
|
|
74
|
+
"typescript": "^5.3.3"
|
|
70
75
|
}
|
|
71
76
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
|
|
3
|
+
new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
|
|
4
|
+
|
|
3
5
|
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
6
|
|
|
5
7
|
Pod::Spec.new do |s|
|
|
@@ -40,5 +42,25 @@ Pod::Spec.new do |s|
|
|
|
40
42
|
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
|
41
43
|
ss.private_header_files = 'ios/RCTPushy/HDiffPatch/**/*.h'
|
|
42
44
|
end
|
|
43
|
-
|
|
45
|
+
|
|
46
|
+
if defined?(install_modules_dependencies()) != nil
|
|
47
|
+
install_modules_dependencies(s);
|
|
48
|
+
else
|
|
49
|
+
if new_arch_enabled
|
|
50
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
51
|
+
|
|
52
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
53
|
+
|
|
54
|
+
s.pod_target_xcconfig = {
|
|
55
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
56
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
s.dependency "React-Codegen"
|
|
60
|
+
s.dependency "RCT-Folly"
|
|
61
|
+
s.dependency "RCTRequired"
|
|
62
|
+
s.dependency "RCTTypeSafety"
|
|
63
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
44
66
|
end
|
package/src/client.tsx
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { CheckResult, PushyOptions, ProgressData } from './type';
|
|
2
|
+
import { assertRelease, log } from './utils';
|
|
3
|
+
import {
|
|
4
|
+
EmitterSubscription,
|
|
5
|
+
PermissionsAndroid,
|
|
6
|
+
Platform,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
import {
|
|
9
|
+
PushyModule,
|
|
10
|
+
buildTime,
|
|
11
|
+
cInfo,
|
|
12
|
+
pushyNativeEventEmitter,
|
|
13
|
+
currentVersion,
|
|
14
|
+
packageVersion,
|
|
15
|
+
report,
|
|
16
|
+
rolledBackVersion,
|
|
17
|
+
setLocalHashInfo,
|
|
18
|
+
} from './core';
|
|
19
|
+
|
|
20
|
+
const defaultServer = {
|
|
21
|
+
main: 'https://update.react-native.cn/api',
|
|
22
|
+
backups: ['https://update.reactnative.cn/api'],
|
|
23
|
+
queryUrl:
|
|
24
|
+
'https://raw.githubusercontent.com/reactnativecn/react-native-pushy/master/endpoints.json',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const empty = {};
|
|
28
|
+
export class Pushy {
|
|
29
|
+
options: PushyOptions = {
|
|
30
|
+
appKey: '',
|
|
31
|
+
server: defaultServer,
|
|
32
|
+
autoMarkSuccess: true,
|
|
33
|
+
useAlert: true,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
lastChecking: number;
|
|
37
|
+
lastResult: CheckResult;
|
|
38
|
+
|
|
39
|
+
progressHandlers: Record<string, EmitterSubscription> = {};
|
|
40
|
+
downloadedHash: string;
|
|
41
|
+
|
|
42
|
+
marked = false;
|
|
43
|
+
applyingUpdate = false;
|
|
44
|
+
version = cInfo.pushy;
|
|
45
|
+
|
|
46
|
+
constructor(options: PushyOptions) {
|
|
47
|
+
if (!options.appKey) {
|
|
48
|
+
throw new Error('appKey is required');
|
|
49
|
+
}
|
|
50
|
+
this.setOptions(options);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setOptions = (options: Partial<PushyOptions>) => {
|
|
54
|
+
for (const [key, value] of Object.entries(options)) {
|
|
55
|
+
if (value !== undefined) {
|
|
56
|
+
this.options[key] = value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
getCheckUrl = (endpoint: string = this.options.server!.main) => {
|
|
62
|
+
return `${endpoint}/checkUpdate/${this.options.appKey}`;
|
|
63
|
+
};
|
|
64
|
+
assertHash = (hash: string) => {
|
|
65
|
+
if (!this.downloadedHash) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (hash !== this.downloadedHash) {
|
|
69
|
+
log(`use downloaded hash ${this.downloadedHash} first`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
markSuccess = () => {
|
|
75
|
+
assertRelease();
|
|
76
|
+
if (this.marked) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
this.marked = true;
|
|
80
|
+
PushyModule.markSuccess();
|
|
81
|
+
report({ type: 'markSuccess' });
|
|
82
|
+
};
|
|
83
|
+
switchVersion = (hash: string) => {
|
|
84
|
+
assertRelease();
|
|
85
|
+
if (this.assertHash(hash) && !this.applyingUpdate) {
|
|
86
|
+
log('switchVersion: ' + hash);
|
|
87
|
+
this.applyingUpdate = true;
|
|
88
|
+
PushyModule.reloadUpdate({ hash });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
switchVersionLater = (hash: string) => {
|
|
93
|
+
assertRelease();
|
|
94
|
+
if (this.assertHash(hash)) {
|
|
95
|
+
log('switchVersionLater: ' + hash);
|
|
96
|
+
PushyModule.setNeedUpdate({ hash });
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
checkUpdate = async () => {
|
|
100
|
+
assertRelease();
|
|
101
|
+
const now = Date.now();
|
|
102
|
+
if (
|
|
103
|
+
this.lastResult &&
|
|
104
|
+
this.lastChecking &&
|
|
105
|
+
now - this.lastChecking < 1000 * 5
|
|
106
|
+
) {
|
|
107
|
+
return this.lastResult;
|
|
108
|
+
}
|
|
109
|
+
this.lastChecking = now;
|
|
110
|
+
report({ type: 'checking' });
|
|
111
|
+
const fetchPayload = {
|
|
112
|
+
method: 'POST',
|
|
113
|
+
headers: {
|
|
114
|
+
Accept: 'application/json',
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
},
|
|
117
|
+
body: JSON.stringify({
|
|
118
|
+
packageVersion,
|
|
119
|
+
hash: currentVersion,
|
|
120
|
+
buildTime,
|
|
121
|
+
cInfo,
|
|
122
|
+
}),
|
|
123
|
+
};
|
|
124
|
+
let resp;
|
|
125
|
+
try {
|
|
126
|
+
resp = await fetch(this.getCheckUrl(), fetchPayload);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
report({
|
|
129
|
+
type: 'errorChecking',
|
|
130
|
+
message: 'Can not connect to update server. Trying backup endpoints.',
|
|
131
|
+
});
|
|
132
|
+
const backupEndpoints = await this.getBackupEndpoints();
|
|
133
|
+
if (backupEndpoints) {
|
|
134
|
+
try {
|
|
135
|
+
resp = await Promise.race(
|
|
136
|
+
backupEndpoints.map((endpoint) =>
|
|
137
|
+
fetch(this.getCheckUrl(endpoint), fetchPayload),
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
} catch {}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!resp) {
|
|
144
|
+
report({
|
|
145
|
+
type: 'errorChecking',
|
|
146
|
+
message: 'Can not connect to update server. Please check your network.',
|
|
147
|
+
});
|
|
148
|
+
return this.lastResult || empty;
|
|
149
|
+
}
|
|
150
|
+
const result: CheckResult = await resp.json();
|
|
151
|
+
|
|
152
|
+
this.lastResult = result;
|
|
153
|
+
|
|
154
|
+
if (resp.status !== 200) {
|
|
155
|
+
report({
|
|
156
|
+
type: 'errorChecking',
|
|
157
|
+
//@ts-ignore
|
|
158
|
+
message: result.message,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return result;
|
|
163
|
+
};
|
|
164
|
+
getBackupEndpoints = async () => {
|
|
165
|
+
const { server } = this.options;
|
|
166
|
+
if (!server) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
if (server.queryUrl) {
|
|
170
|
+
try {
|
|
171
|
+
const resp = await fetch(server.queryUrl);
|
|
172
|
+
const remoteEndpoints = await resp.json();
|
|
173
|
+
log('fetch endpoints:', remoteEndpoints);
|
|
174
|
+
if (Array.isArray(remoteEndpoints)) {
|
|
175
|
+
server.backups = Array.from(
|
|
176
|
+
new Set([...(server.backups || []), ...remoteEndpoints]),
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
log('failed to fetch endpoints from: ', server.queryUrl);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return server.backups;
|
|
184
|
+
};
|
|
185
|
+
downloadUpdate = async (
|
|
186
|
+
info: CheckResult,
|
|
187
|
+
onDownloadProgress?: (data: ProgressData) => void,
|
|
188
|
+
) => {
|
|
189
|
+
assertRelease();
|
|
190
|
+
if (!('update' in info)) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const { hash, diffUrl, pdiffUrl, updateUrl, name, description, metaInfo } =
|
|
194
|
+
info;
|
|
195
|
+
if (rolledBackVersion === hash) {
|
|
196
|
+
log(`rolledback hash ${rolledBackVersion}, ignored`);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (this.downloadedHash === hash) {
|
|
200
|
+
log(`duplicated downloaded hash ${this.downloadedHash}, ignored`);
|
|
201
|
+
return this.downloadedHash;
|
|
202
|
+
}
|
|
203
|
+
if (this.progressHandlers[hash]) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (onDownloadProgress) {
|
|
207
|
+
this.progressHandlers[hash] = pushyNativeEventEmitter.addListener(
|
|
208
|
+
'RCTPushyDownloadProgress',
|
|
209
|
+
(progressData) => {
|
|
210
|
+
if (progressData.hash === hash) {
|
|
211
|
+
onDownloadProgress(progressData);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
let succeeded = false;
|
|
217
|
+
report({ type: 'downloading' });
|
|
218
|
+
if (diffUrl) {
|
|
219
|
+
log('downloading diff');
|
|
220
|
+
try {
|
|
221
|
+
await PushyModule.downloadPatchFromPpk({
|
|
222
|
+
updateUrl: diffUrl,
|
|
223
|
+
hash,
|
|
224
|
+
originHash: currentVersion,
|
|
225
|
+
});
|
|
226
|
+
succeeded = true;
|
|
227
|
+
} catch (e) {
|
|
228
|
+
log(`diff error: ${e.message}, try pdiff`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!succeeded && pdiffUrl) {
|
|
232
|
+
log('downloading pdiff');
|
|
233
|
+
try {
|
|
234
|
+
await PushyModule.downloadPatchFromPackage({
|
|
235
|
+
updateUrl: pdiffUrl,
|
|
236
|
+
hash,
|
|
237
|
+
});
|
|
238
|
+
succeeded = true;
|
|
239
|
+
} catch (e) {
|
|
240
|
+
log(`pdiff error: ${e.message}, try full patch`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!succeeded && updateUrl) {
|
|
244
|
+
log('downloading full patch');
|
|
245
|
+
try {
|
|
246
|
+
await PushyModule.downloadFullUpdate({
|
|
247
|
+
updateUrl: updateUrl,
|
|
248
|
+
hash,
|
|
249
|
+
});
|
|
250
|
+
succeeded = true;
|
|
251
|
+
} catch (e) {
|
|
252
|
+
log(`full patch error: ${e.message}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (this.progressHandlers[hash]) {
|
|
256
|
+
this.progressHandlers[hash].remove();
|
|
257
|
+
delete this.progressHandlers[hash];
|
|
258
|
+
}
|
|
259
|
+
if (!succeeded) {
|
|
260
|
+
return report({
|
|
261
|
+
type: 'errorUpdate',
|
|
262
|
+
data: { newVersion: hash },
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
setLocalHashInfo(hash, {
|
|
266
|
+
name,
|
|
267
|
+
description,
|
|
268
|
+
metaInfo,
|
|
269
|
+
});
|
|
270
|
+
this.downloadedHash = hash;
|
|
271
|
+
return hash;
|
|
272
|
+
};
|
|
273
|
+
downloadAndInstallApk = async (
|
|
274
|
+
url: string,
|
|
275
|
+
onDownloadProgress?: (data: ProgressData) => void,
|
|
276
|
+
) => {
|
|
277
|
+
if (Platform.OS !== 'android') {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
report({ type: 'downloadingApk' });
|
|
281
|
+
if (Platform.Version <= 23) {
|
|
282
|
+
try {
|
|
283
|
+
const granted = await PermissionsAndroid.request(
|
|
284
|
+
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
|
285
|
+
);
|
|
286
|
+
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
|
287
|
+
return report({ type: 'rejectStoragePermission' });
|
|
288
|
+
}
|
|
289
|
+
} catch (err) {
|
|
290
|
+
return report({ type: 'errorStoragePermission' });
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const progressKey = 'downloadingApk';
|
|
294
|
+
if (onDownloadProgress) {
|
|
295
|
+
this.progressHandlers[progressKey] = pushyNativeEventEmitter.addListener(
|
|
296
|
+
'RCTPushyDownloadProgress',
|
|
297
|
+
(progressData: ProgressData) => {
|
|
298
|
+
if (progressData.hash === progressKey) {
|
|
299
|
+
onDownloadProgress(progressData);
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
await PushyModule.downloadAndInstallApk({
|
|
305
|
+
url,
|
|
306
|
+
target: 'update.apk',
|
|
307
|
+
hash: progressKey,
|
|
308
|
+
}).catch(() => {
|
|
309
|
+
report({ type: 'errowDownloadAndInstallApk' });
|
|
310
|
+
});
|
|
311
|
+
if (this.progressHandlers[progressKey]) {
|
|
312
|
+
this.progressHandlers[progressKey].remove();
|
|
313
|
+
delete this.progressHandlers[progressKey];
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import { CheckResult, ProgressData } from './type';
|
|
3
|
+
import { Pushy } from './client';
|
|
4
|
+
|
|
5
|
+
const empty = {};
|
|
6
|
+
const noop = () => {};
|
|
7
|
+
|
|
8
|
+
export const defaultContext = {
|
|
9
|
+
checkUpdate: () => Promise.resolve(empty),
|
|
10
|
+
switchVersion: noop,
|
|
11
|
+
switchVersionLater: noop,
|
|
12
|
+
markSuccess: noop,
|
|
13
|
+
dismissError: noop,
|
|
14
|
+
downloadUpdate: noop,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const PushyContext = createContext<{
|
|
18
|
+
checkUpdate: () => void;
|
|
19
|
+
switchVersion: () => void;
|
|
20
|
+
switchVersionLater: () => void;
|
|
21
|
+
progress?: ProgressData;
|
|
22
|
+
markSuccess: () => void;
|
|
23
|
+
updateInfo?: CheckResult;
|
|
24
|
+
lastError?: Error;
|
|
25
|
+
dismissError: () => void;
|
|
26
|
+
client?: Pushy;
|
|
27
|
+
downloadUpdate: () => void;
|
|
28
|
+
}>(defaultContext);
|
|
29
|
+
|
|
30
|
+
export const usePushy = () => useContext(PushyContext);
|
package/src/core.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
|
+
import { EventType, UpdateEventsLogger } from './type';
|
|
3
|
+
import { log } from './utils';
|
|
4
|
+
const {
|
|
5
|
+
version: v,
|
|
6
|
+
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
|
7
|
+
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
|
8
|
+
const isTurboModuleEnabled = global.__turboModuleProxy != null;
|
|
9
|
+
|
|
10
|
+
export const PushyModule = isTurboModuleEnabled
|
|
11
|
+
? require('./turboModuleSpec').default
|
|
12
|
+
: NativeModules.Pushy;
|
|
13
|
+
|
|
14
|
+
if (!PushyModule) {
|
|
15
|
+
throw new Error('react-native-update模块无法加载,请对照安装文档检查配置。');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const PushyConstants = isTurboModuleEnabled
|
|
19
|
+
? PushyModule.getConstants()
|
|
20
|
+
: PushyModule;
|
|
21
|
+
|
|
22
|
+
export const downloadRootDir = PushyConstants.downloadRootDir;
|
|
23
|
+
export const packageVersion = PushyConstants.packageVersion;
|
|
24
|
+
export const currentVersion = PushyConstants.currentVersion;
|
|
25
|
+
export const isFirstTime = PushyConstants.isFirstTime;
|
|
26
|
+
export const rolledBackVersion = PushyConstants.rolledBackVersion;
|
|
27
|
+
export const isRolledBack = typeof rolledBackVersion === 'string';
|
|
28
|
+
|
|
29
|
+
export const buildTime = PushyConstants.buildTime;
|
|
30
|
+
let uuid = PushyConstants.uuid;
|
|
31
|
+
|
|
32
|
+
if (Platform.OS === 'android' && !PushyConstants.isUsingBundleUrl) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
'react-native-update模块无法加载,请对照文档检查Bundle URL的配置',
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function setLocalHashInfo(hash: string, info: Record<string, any>) {
|
|
39
|
+
PushyModule.setLocalHashInfo(hash, JSON.stringify(info));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function getLocalHashInfo(hash: string) {
|
|
43
|
+
return JSON.parse(await PushyModule.getLocalHashInfo(hash));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function getCurrentVersionInfo(): Promise<{
|
|
47
|
+
name?: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
metaInfo?: string;
|
|
50
|
+
}> {
|
|
51
|
+
return currentVersion ? (await getLocalHashInfo(currentVersion)) || {} : {};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const pushyNativeEventEmitter = new NativeEventEmitter(PushyModule);
|
|
55
|
+
|
|
56
|
+
if (!uuid) {
|
|
57
|
+
uuid = require('nanoid/non-secure').nanoid();
|
|
58
|
+
PushyModule.setUuid(uuid);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const noop = () => {};
|
|
62
|
+
let reporter: UpdateEventsLogger = noop;
|
|
63
|
+
|
|
64
|
+
export function onPushyEvents(customReporter: UpdateEventsLogger) {
|
|
65
|
+
reporter = customReporter;
|
|
66
|
+
if (isRolledBack) {
|
|
67
|
+
report({
|
|
68
|
+
type: 'rollback',
|
|
69
|
+
data: {
|
|
70
|
+
rolledBackVersion,
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function report({
|
|
77
|
+
type,
|
|
78
|
+
message = '',
|
|
79
|
+
data = {},
|
|
80
|
+
}: {
|
|
81
|
+
type: EventType;
|
|
82
|
+
message?: string;
|
|
83
|
+
data?: Record<string, string | number>;
|
|
84
|
+
}) {
|
|
85
|
+
log(type + ' ' + message);
|
|
86
|
+
reporter({
|
|
87
|
+
type,
|
|
88
|
+
data: {
|
|
89
|
+
currentVersion,
|
|
90
|
+
cInfo,
|
|
91
|
+
packageVersion,
|
|
92
|
+
buildTime,
|
|
93
|
+
message,
|
|
94
|
+
...data,
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
log('uuid: ' + uuid);
|
|
100
|
+
|
|
101
|
+
export const cInfo = {
|
|
102
|
+
pushy: require('../package.json').version,
|
|
103
|
+
rn: RNVersion,
|
|
104
|
+
os: Platform.OS + ' ' + Platform.Version,
|
|
105
|
+
uuid,
|
|
106
|
+
};
|
package/src/index.ts
ADDED
package/src/index.web.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Fragment } from 'react';
|
|
2
|
+
|
|
3
|
+
const noop = () => {};
|
|
4
|
+
export class Pushy {
|
|
5
|
+
constructor() {
|
|
6
|
+
console.warn('react-native-update is not supported and will do nothing on web.');
|
|
7
|
+
return new Proxy(this, {
|
|
8
|
+
get() {
|
|
9
|
+
return noop;
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { PushyContext, usePushy } from './context';
|
|
16
|
+
|
|
17
|
+
export const PushyProvider = Fragment;
|