react-native-update 9.1.6 → 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/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/lib/main.ts
DELETED
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
updateBackupEndpoints,
|
|
3
|
-
getCheckUrl,
|
|
4
|
-
setCustomEndpoints,
|
|
5
|
-
} from './endpoint';
|
|
6
|
-
import {
|
|
7
|
-
NativeEventEmitter,
|
|
8
|
-
NativeModules,
|
|
9
|
-
Platform,
|
|
10
|
-
PermissionsAndroid,
|
|
11
|
-
} from 'react-native';
|
|
12
|
-
import {
|
|
13
|
-
CheckResult,
|
|
14
|
-
EventType,
|
|
15
|
-
ProgressData,
|
|
16
|
-
UpdateAvailableResult,
|
|
17
|
-
UpdateEventsListener,
|
|
18
|
-
} from './type';
|
|
19
|
-
import { assertRelease, logger } from './utils';
|
|
20
|
-
export { setCustomEndpoints };
|
|
21
|
-
const {
|
|
22
|
-
version: v,
|
|
23
|
-
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
|
24
|
-
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
|
25
|
-
const isTurboModuleEnabled = global.__turboModuleProxy != null;
|
|
26
|
-
|
|
27
|
-
export const PushyModule = isTurboModuleEnabled
|
|
28
|
-
? require('./NativeUpdate').default
|
|
29
|
-
: NativeModules.Pushy;
|
|
30
|
-
|
|
31
|
-
if (!PushyModule) {
|
|
32
|
-
throw new Error('react-native-update模块无法加载,请对照安装文档检查配置。');
|
|
33
|
-
}
|
|
34
|
-
const PushyConstants = isTurboModuleEnabled
|
|
35
|
-
? PushyModule.getConstants()
|
|
36
|
-
: PushyModule;
|
|
37
|
-
|
|
38
|
-
export const downloadRootDir = PushyConstants.downloadRootDir;
|
|
39
|
-
export const packageVersion = PushyConstants.packageVersion;
|
|
40
|
-
export const currentVersion = PushyConstants.currentVersion;
|
|
41
|
-
export const isFirstTime = PushyConstants.isFirstTime;
|
|
42
|
-
const rolledBackVersion = PushyConstants.rolledBackVersion;
|
|
43
|
-
export const isRolledBack = typeof rolledBackVersion === 'string';
|
|
44
|
-
|
|
45
|
-
export const buildTime = PushyConstants.buildTime;
|
|
46
|
-
let blockUpdate = PushyConstants.blockUpdate;
|
|
47
|
-
let uuid = PushyConstants.uuid;
|
|
48
|
-
|
|
49
|
-
if (Platform.OS === 'android' && !PushyConstants.isUsingBundleUrl) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
'react-native-update模块无法加载,请对照文档检查Bundle URL的配置',
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function setLocalHashInfo(hash: string, info: Record<string, any>) {
|
|
56
|
-
PushyModule.setLocalHashInfo(hash, JSON.stringify(info));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function getLocalHashInfo(hash: string) {
|
|
60
|
-
return JSON.parse(await PushyModule.getLocalHashInfo(hash));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function getCurrentVersionInfo(): Promise<{
|
|
64
|
-
name?: string;
|
|
65
|
-
description?: string;
|
|
66
|
-
metaInfo?: string;
|
|
67
|
-
}> {
|
|
68
|
-
return currentVersion ? (await getLocalHashInfo(currentVersion)) || {} : {};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const eventEmitter = new NativeEventEmitter(PushyModule);
|
|
72
|
-
|
|
73
|
-
if (!uuid) {
|
|
74
|
-
uuid = require('nanoid/non-secure').nanoid();
|
|
75
|
-
PushyModule.setUuid(uuid);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const noop = () => {};
|
|
79
|
-
let reporter: UpdateEventsListener = noop;
|
|
80
|
-
|
|
81
|
-
export function onPushyEvents(customReporter: UpdateEventsListener) {
|
|
82
|
-
reporter = customReporter;
|
|
83
|
-
if (isRolledBack) {
|
|
84
|
-
report({
|
|
85
|
-
type: 'rollback',
|
|
86
|
-
data: {
|
|
87
|
-
rolledBackVersion,
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function report({
|
|
94
|
-
type,
|
|
95
|
-
message = '',
|
|
96
|
-
data = {},
|
|
97
|
-
}: {
|
|
98
|
-
type: EventType;
|
|
99
|
-
message?: string;
|
|
100
|
-
data?: Record<string, string | number>;
|
|
101
|
-
}) {
|
|
102
|
-
logger(type + ' ' + message);
|
|
103
|
-
reporter({
|
|
104
|
-
type,
|
|
105
|
-
data: {
|
|
106
|
-
currentVersion,
|
|
107
|
-
cInfo,
|
|
108
|
-
packageVersion,
|
|
109
|
-
buildTime,
|
|
110
|
-
message,
|
|
111
|
-
...data,
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
logger('uuid: ' + uuid);
|
|
117
|
-
|
|
118
|
-
export const cInfo = {
|
|
119
|
-
pushy: require('../package.json').version,
|
|
120
|
-
rn: RNVersion,
|
|
121
|
-
os: Platform.OS + ' ' + Platform.Version,
|
|
122
|
-
uuid,
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
let lastChecking;
|
|
126
|
-
const empty = {};
|
|
127
|
-
let lastResult: CheckResult;
|
|
128
|
-
export async function checkUpdate(APPKEY: string) {
|
|
129
|
-
assertRelease();
|
|
130
|
-
const now = Date.now();
|
|
131
|
-
if (lastResult && lastChecking && now - lastChecking < 1000 * 60) {
|
|
132
|
-
// logger('repeated checking, ignored');
|
|
133
|
-
return lastResult;
|
|
134
|
-
}
|
|
135
|
-
lastChecking = now;
|
|
136
|
-
if (blockUpdate && blockUpdate.until > Date.now() / 1000) {
|
|
137
|
-
report({
|
|
138
|
-
type: 'errorChecking',
|
|
139
|
-
message: `热更新已暂停,原因:${blockUpdate.reason}。请在"${new Date(
|
|
140
|
-
blockUpdate.until * 1000,
|
|
141
|
-
).toLocaleString()}"之后重试。`,
|
|
142
|
-
});
|
|
143
|
-
return lastResult || empty;
|
|
144
|
-
}
|
|
145
|
-
report({ type: 'checking' });
|
|
146
|
-
const fetchPayload = {
|
|
147
|
-
method: 'POST',
|
|
148
|
-
headers: {
|
|
149
|
-
Accept: 'application/json',
|
|
150
|
-
'Content-Type': 'application/json',
|
|
151
|
-
},
|
|
152
|
-
body: JSON.stringify({
|
|
153
|
-
packageVersion,
|
|
154
|
-
hash: currentVersion,
|
|
155
|
-
buildTime,
|
|
156
|
-
cInfo,
|
|
157
|
-
}),
|
|
158
|
-
};
|
|
159
|
-
let resp;
|
|
160
|
-
try {
|
|
161
|
-
resp = await fetch(getCheckUrl(APPKEY), fetchPayload);
|
|
162
|
-
} catch (e) {
|
|
163
|
-
report({
|
|
164
|
-
type: 'errorChecking',
|
|
165
|
-
message: '无法连接主更新服务器,尝试备用节点',
|
|
166
|
-
});
|
|
167
|
-
const backupEndpoints = await updateBackupEndpoints();
|
|
168
|
-
if (backupEndpoints) {
|
|
169
|
-
try {
|
|
170
|
-
resp = await Promise.race(
|
|
171
|
-
backupEndpoints.map((endpoint) =>
|
|
172
|
-
fetch(getCheckUrl(APPKEY, endpoint), fetchPayload),
|
|
173
|
-
),
|
|
174
|
-
);
|
|
175
|
-
} catch {}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if (!resp) {
|
|
179
|
-
report({
|
|
180
|
-
type: 'errorChecking',
|
|
181
|
-
message: '无法连接更新服务器,请检查网络连接后重试',
|
|
182
|
-
});
|
|
183
|
-
return lastResult || empty;
|
|
184
|
-
}
|
|
185
|
-
const result: CheckResult = await resp.json();
|
|
186
|
-
|
|
187
|
-
lastResult = result;
|
|
188
|
-
// @ts-ignore
|
|
189
|
-
checkOperation(result.op);
|
|
190
|
-
|
|
191
|
-
if (resp.status !== 200) {
|
|
192
|
-
report({
|
|
193
|
-
type: 'errorChecking',
|
|
194
|
-
//@ts-ignore
|
|
195
|
-
message: result.message,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return result;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function checkOperation(
|
|
203
|
-
op: { type: string; reason: string; duration: number }[],
|
|
204
|
-
) {
|
|
205
|
-
if (!Array.isArray(op)) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
op.forEach((action) => {
|
|
209
|
-
if (action.type === 'block') {
|
|
210
|
-
blockUpdate = {
|
|
211
|
-
reason: action.reason,
|
|
212
|
-
until: Math.round((Date.now() + action.duration) / 1000),
|
|
213
|
-
};
|
|
214
|
-
PushyModule.setBlockUpdate(blockUpdate);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
let downloadingThrottling = false;
|
|
220
|
-
let downloadedHash: string;
|
|
221
|
-
export async function downloadUpdate(
|
|
222
|
-
options: UpdateAvailableResult,
|
|
223
|
-
eventListeners?: {
|
|
224
|
-
onDownloadProgress?: (data: ProgressData) => void;
|
|
225
|
-
},
|
|
226
|
-
) {
|
|
227
|
-
assertRelease();
|
|
228
|
-
if (!options.update) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
if (rolledBackVersion === options.hash) {
|
|
232
|
-
logger(`rolledback hash ${rolledBackVersion}, ignored`);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
if (downloadedHash === options.hash) {
|
|
236
|
-
logger(`duplicated downloaded hash ${downloadedHash}, ignored`);
|
|
237
|
-
return downloadedHash;
|
|
238
|
-
}
|
|
239
|
-
if (downloadingThrottling) {
|
|
240
|
-
logger('repeated downloading, ignored');
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
downloadingThrottling = true;
|
|
244
|
-
setTimeout(() => {
|
|
245
|
-
downloadingThrottling = false;
|
|
246
|
-
}, 3000);
|
|
247
|
-
let progressHandler;
|
|
248
|
-
if (eventListeners) {
|
|
249
|
-
if (eventListeners.onDownloadProgress) {
|
|
250
|
-
const downloadCallback = eventListeners.onDownloadProgress;
|
|
251
|
-
progressHandler = eventEmitter.addListener(
|
|
252
|
-
'RCTPushyDownloadProgress',
|
|
253
|
-
(progressData) => {
|
|
254
|
-
if (progressData.hash === options.hash) {
|
|
255
|
-
downloadCallback(progressData);
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
let succeeded = false;
|
|
262
|
-
report({ type: 'downloading' });
|
|
263
|
-
if (options.diffUrl) {
|
|
264
|
-
logger('downloading diff');
|
|
265
|
-
try {
|
|
266
|
-
await PushyModule.downloadPatchFromPpk({
|
|
267
|
-
updateUrl: options.diffUrl,
|
|
268
|
-
hash: options.hash,
|
|
269
|
-
originHash: currentVersion,
|
|
270
|
-
});
|
|
271
|
-
succeeded = true;
|
|
272
|
-
} catch (e) {
|
|
273
|
-
logger(`diff error: ${e.message}, try pdiff`);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if (!succeeded && options.pdiffUrl) {
|
|
277
|
-
logger('downloading pdiff');
|
|
278
|
-
try {
|
|
279
|
-
await PushyModule.downloadPatchFromPackage({
|
|
280
|
-
updateUrl: options.pdiffUrl,
|
|
281
|
-
hash: options.hash,
|
|
282
|
-
});
|
|
283
|
-
succeeded = true;
|
|
284
|
-
} catch (e) {
|
|
285
|
-
logger(`pdiff error: ${e.message}, try full patch`);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (!succeeded && options.updateUrl) {
|
|
289
|
-
logger('downloading full patch');
|
|
290
|
-
try {
|
|
291
|
-
await PushyModule.downloadFullUpdate({
|
|
292
|
-
updateUrl: options.updateUrl,
|
|
293
|
-
hash: options.hash,
|
|
294
|
-
});
|
|
295
|
-
succeeded = true;
|
|
296
|
-
} catch (e) {
|
|
297
|
-
logger(`full patch error: ${e.message}`);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
progressHandler && progressHandler.remove();
|
|
301
|
-
if (!succeeded) {
|
|
302
|
-
return report({ type: 'errorUpdate', data: { newVersion: options.hash } });
|
|
303
|
-
}
|
|
304
|
-
setLocalHashInfo(options.hash, {
|
|
305
|
-
name: options.name,
|
|
306
|
-
description: options.description,
|
|
307
|
-
metaInfo: options.metaInfo,
|
|
308
|
-
});
|
|
309
|
-
downloadedHash = options.hash;
|
|
310
|
-
return options.hash;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function assertHash(hash: string) {
|
|
314
|
-
if (!downloadedHash) {
|
|
315
|
-
logger(`no downloaded hash`);
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
if (hash !== downloadedHash) {
|
|
319
|
-
logger(`use downloaded hash ${downloadedHash} first`);
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
let applyingUpdate = false;
|
|
326
|
-
export function switchVersion(hash: string) {
|
|
327
|
-
assertRelease();
|
|
328
|
-
if (assertHash(hash) && !applyingUpdate) {
|
|
329
|
-
logger('switchVersion: ' + hash);
|
|
330
|
-
applyingUpdate = true;
|
|
331
|
-
PushyModule.reloadUpdate({ hash });
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
export function switchVersionLater(hash: string) {
|
|
336
|
-
assertRelease();
|
|
337
|
-
if (assertHash(hash)) {
|
|
338
|
-
logger('switchVersionLater: ' + hash);
|
|
339
|
-
PushyModule.setNeedUpdate({ hash });
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
let marked = false;
|
|
344
|
-
export function markSuccess() {
|
|
345
|
-
assertRelease();
|
|
346
|
-
if (marked) {
|
|
347
|
-
logger('repeated markSuccess, ignored');
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
marked = true;
|
|
351
|
-
PushyModule.markSuccess();
|
|
352
|
-
report({ type: 'markSuccess' });
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
export async function downloadAndInstallApk({
|
|
356
|
-
url,
|
|
357
|
-
onDownloadProgress,
|
|
358
|
-
}: {
|
|
359
|
-
url: string;
|
|
360
|
-
onDownloadProgress?: (data: ProgressData) => void;
|
|
361
|
-
}) {
|
|
362
|
-
if (Platform.OS !== 'android') {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
report({ type: 'downloadingApk' });
|
|
366
|
-
if (Platform.Version <= 23) {
|
|
367
|
-
try {
|
|
368
|
-
const granted = await PermissionsAndroid.request(
|
|
369
|
-
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
|
370
|
-
);
|
|
371
|
-
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
|
372
|
-
return report({ type: 'rejectStoragePermission' });
|
|
373
|
-
}
|
|
374
|
-
} catch (err) {
|
|
375
|
-
return report({ type: 'errorStoragePermission' });
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
let hash = Date.now().toString();
|
|
379
|
-
let progressHandler;
|
|
380
|
-
if (onDownloadProgress) {
|
|
381
|
-
progressHandler = eventEmitter.addListener(
|
|
382
|
-
'RCTPushyDownloadProgress',
|
|
383
|
-
(progressData: ProgressData) => {
|
|
384
|
-
if (progressData.hash === hash) {
|
|
385
|
-
onDownloadProgress(progressData);
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
await PushyModule.downloadAndInstallApk({
|
|
391
|
-
url,
|
|
392
|
-
target: 'update.apk',
|
|
393
|
-
hash,
|
|
394
|
-
}).catch(() => {
|
|
395
|
-
report({ type: 'errowDownloadAndInstallApk' });
|
|
396
|
-
});
|
|
397
|
-
progressHandler && progressHandler.remove();
|
|
398
|
-
}
|
package/lib/simpleUpdate.tsx
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import React, { PureComponent, ComponentType } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Platform,
|
|
4
|
-
Alert,
|
|
5
|
-
Linking,
|
|
6
|
-
AppState,
|
|
7
|
-
NativeEventSubscription,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
isFirstTime,
|
|
12
|
-
isRolledBack,
|
|
13
|
-
checkUpdate,
|
|
14
|
-
downloadUpdate,
|
|
15
|
-
switchVersion,
|
|
16
|
-
switchVersionLater,
|
|
17
|
-
markSuccess,
|
|
18
|
-
downloadAndInstallApk,
|
|
19
|
-
onPushyEvents,
|
|
20
|
-
} from './main';
|
|
21
|
-
import { UpdateEventsListener } from './type';
|
|
22
|
-
|
|
23
|
-
export function simpleUpdate(
|
|
24
|
-
WrappedComponent: ComponentType,
|
|
25
|
-
options: { appKey?: string; onPushyEvents?: UpdateEventsListener } = {},
|
|
26
|
-
) {
|
|
27
|
-
const { appKey, onPushyEvents: eventListeners } = options;
|
|
28
|
-
if (!appKey) {
|
|
29
|
-
throw new Error('appKey is required for simpleUpdate()');
|
|
30
|
-
}
|
|
31
|
-
if (typeof eventListeners === 'function') {
|
|
32
|
-
onPushyEvents(eventListeners);
|
|
33
|
-
}
|
|
34
|
-
return __DEV__
|
|
35
|
-
? WrappedComponent
|
|
36
|
-
: class AppUpdate extends PureComponent {
|
|
37
|
-
stateListener: NativeEventSubscription;
|
|
38
|
-
componentDidMount() {
|
|
39
|
-
if (isRolledBack) {
|
|
40
|
-
Alert.alert('抱歉', '刚刚更新遭遇错误,已为您恢复到更新前版本');
|
|
41
|
-
} else if (isFirstTime) {
|
|
42
|
-
markSuccess();
|
|
43
|
-
}
|
|
44
|
-
this.stateListener = AppState.addEventListener(
|
|
45
|
-
'change',
|
|
46
|
-
(nextAppState) => {
|
|
47
|
-
if (nextAppState === 'active') {
|
|
48
|
-
this.checkUpdate();
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
);
|
|
52
|
-
this.checkUpdate();
|
|
53
|
-
}
|
|
54
|
-
componentWillUnmount() {
|
|
55
|
-
this.stateListener && this.stateListener.remove();
|
|
56
|
-
}
|
|
57
|
-
doUpdate = async (info) => {
|
|
58
|
-
try {
|
|
59
|
-
const hash = await downloadUpdate(info);
|
|
60
|
-
if (!hash) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
this.stateListener && this.stateListener.remove();
|
|
64
|
-
Alert.alert('提示', '下载完毕,是否立即更新?', [
|
|
65
|
-
{
|
|
66
|
-
text: '以后再说',
|
|
67
|
-
style: 'cancel',
|
|
68
|
-
onPress: () => {
|
|
69
|
-
switchVersionLater(hash);
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
text: '立即更新',
|
|
74
|
-
style: 'default',
|
|
75
|
-
onPress: () => {
|
|
76
|
-
switchVersion(hash);
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
]);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
Alert.alert('更新失败', err.message);
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
checkUpdate = async () => {
|
|
86
|
-
let info;
|
|
87
|
-
try {
|
|
88
|
-
info = await checkUpdate(appKey!);
|
|
89
|
-
} catch (err) {
|
|
90
|
-
Alert.alert('更新检查失败', err.message);
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (info.expired) {
|
|
94
|
-
Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [
|
|
95
|
-
{
|
|
96
|
-
text: '确定',
|
|
97
|
-
onPress: () => {
|
|
98
|
-
if (info.downloadUrl) {
|
|
99
|
-
if (
|
|
100
|
-
Platform.OS === 'android' &&
|
|
101
|
-
info.downloadUrl.endsWith('.apk')
|
|
102
|
-
) {
|
|
103
|
-
downloadAndInstallApk({
|
|
104
|
-
url: info.downloadUrl,
|
|
105
|
-
});
|
|
106
|
-
} else {
|
|
107
|
-
Linking.openURL(info.downloadUrl);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
]);
|
|
113
|
-
} else if (info.update) {
|
|
114
|
-
Alert.alert(
|
|
115
|
-
'提示',
|
|
116
|
-
'检查到新的版本' + info.name + ',是否下载?\n' + info.description,
|
|
117
|
-
[
|
|
118
|
-
{ text: '否', style: 'cancel' },
|
|
119
|
-
{
|
|
120
|
-
text: '是',
|
|
121
|
-
style: 'default',
|
|
122
|
-
onPress: () => {
|
|
123
|
-
this.doUpdate(info);
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
],
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
render() {
|
|
132
|
-
return <WrappedComponent {...this.props} />;
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
}
|