react-native-update 10.42.4 → 10.42.5
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.
|
@@ -75,7 +75,7 @@ export class PushyTurboModule extends UITurboModule {
|
|
|
75
75
|
const currentVersionInfo = currentVersion
|
|
76
76
|
? this.context.getKv(`hash_${currentVersion}`)
|
|
77
77
|
: '';
|
|
78
|
-
const isFirstTime = this.context.
|
|
78
|
+
const isFirstTime = this.context.consumeFirstLoadMarker();
|
|
79
79
|
const rolledBackVersion = this.context.rolledBackVersion();
|
|
80
80
|
const uuid = this.context.getKv('uuid');
|
|
81
81
|
const isUsingBundleUrl = this.context.getIsUsingBundleUrl();
|
|
@@ -25,6 +25,7 @@ export class UpdateContext {
|
|
|
25
25
|
private preferences!: preferences.Preferences;
|
|
26
26
|
private static DEBUG: boolean = false;
|
|
27
27
|
private static isUsingBundleUrl: boolean = false;
|
|
28
|
+
private static ignoreRollback: boolean = false;
|
|
28
29
|
|
|
29
30
|
constructor(context: common.UIAbilityContext) {
|
|
30
31
|
this.context = context;
|
|
@@ -72,9 +73,8 @@ export class UpdateContext {
|
|
|
72
73
|
|
|
73
74
|
public getBuildTime(): string {
|
|
74
75
|
try {
|
|
75
|
-
const content =
|
|
76
|
-
'meta.json'
|
|
77
|
-
);
|
|
76
|
+
const content =
|
|
77
|
+
this.context.resourceManager.getRawFileContentSync('meta.json');
|
|
78
78
|
const metaData = JSON.parse(
|
|
79
79
|
new util.TextDecoder().decodeToString(content),
|
|
80
80
|
) as Record<string, string | number | boolean | null | undefined>;
|
|
@@ -182,6 +182,8 @@ export class UpdateContext {
|
|
|
182
182
|
clearExisting?: boolean;
|
|
183
183
|
removeStaleHash?: boolean;
|
|
184
184
|
cleanUp?: boolean;
|
|
185
|
+
markFirstLoadMarker?: boolean;
|
|
186
|
+
clearFirstLoadMarker?: boolean;
|
|
185
187
|
} = {},
|
|
186
188
|
): void {
|
|
187
189
|
if (options.clearExisting) {
|
|
@@ -191,6 +193,12 @@ export class UpdateContext {
|
|
|
191
193
|
if (options.removeStaleHash && state.staleVersionToDelete) {
|
|
192
194
|
this.preferences.deleteSync(`hash_${state.staleVersionToDelete}`);
|
|
193
195
|
}
|
|
196
|
+
if (options.markFirstLoadMarker) {
|
|
197
|
+
this.preferences.putSync('firstLoadMarked', 'true');
|
|
198
|
+
}
|
|
199
|
+
if (options.clearFirstLoadMarker) {
|
|
200
|
+
this.preferences.deleteSync('firstLoadMarked');
|
|
201
|
+
}
|
|
194
202
|
this.flushPreferences('persist state');
|
|
195
203
|
if (options.cleanUp) {
|
|
196
204
|
this.cleanUp();
|
|
@@ -203,6 +211,7 @@ export class UpdateContext {
|
|
|
203
211
|
options: {
|
|
204
212
|
removeStaleHash?: boolean;
|
|
205
213
|
cleanUp?: boolean;
|
|
214
|
+
clearFirstLoadMarker?: boolean;
|
|
206
215
|
} = {},
|
|
207
216
|
): StateCoreResult {
|
|
208
217
|
const nextState = NativePatchCore.runStateCore(
|
|
@@ -245,6 +254,7 @@ export class UpdateContext {
|
|
|
245
254
|
return;
|
|
246
255
|
}
|
|
247
256
|
|
|
257
|
+
UpdateContext.ignoreRollback = false;
|
|
248
258
|
this.cleanUp();
|
|
249
259
|
this.persistState(nextState, { clearExisting: true });
|
|
250
260
|
}
|
|
@@ -278,7 +288,10 @@ export class UpdateContext {
|
|
|
278
288
|
}
|
|
279
289
|
|
|
280
290
|
public clearFirstTime(): void {
|
|
281
|
-
this.runStateOperation(STATE_OP_CLEAR_FIRST_TIME, '', {
|
|
291
|
+
this.runStateOperation(STATE_OP_CLEAR_FIRST_TIME, '', {
|
|
292
|
+
cleanUp: true,
|
|
293
|
+
clearFirstLoadMarker: true,
|
|
294
|
+
});
|
|
282
295
|
}
|
|
283
296
|
|
|
284
297
|
public clearRollbackMark(): void {
|
|
@@ -361,23 +374,38 @@ export class UpdateContext {
|
|
|
361
374
|
}
|
|
362
375
|
|
|
363
376
|
this.runStateOperation(STATE_OP_SWITCH_VERSION, hash);
|
|
377
|
+
UpdateContext.ignoreRollback = false;
|
|
364
378
|
} catch (e) {
|
|
365
379
|
console.error('Failed to switch version:', e);
|
|
366
380
|
throw e;
|
|
367
381
|
}
|
|
368
382
|
}
|
|
369
383
|
|
|
384
|
+
public consumeFirstLoadMarker(): boolean {
|
|
385
|
+
const marked = this.readString('firstLoadMarked') === 'true';
|
|
386
|
+
if (marked) {
|
|
387
|
+
this.preferences.deleteSync('firstLoadMarked');
|
|
388
|
+
this.flushPreferences('clear first load marker');
|
|
389
|
+
}
|
|
390
|
+
return marked;
|
|
391
|
+
}
|
|
392
|
+
|
|
370
393
|
public getBundleUrl() {
|
|
371
394
|
UpdateContext.isUsingBundleUrl = true;
|
|
372
395
|
const launchState = NativePatchCore.runStateCore(
|
|
373
396
|
STATE_OP_RESOLVE_LAUNCH,
|
|
374
397
|
this.getStateSnapshot(),
|
|
375
398
|
'',
|
|
376
|
-
|
|
377
|
-
|
|
399
|
+
UpdateContext.ignoreRollback,
|
|
400
|
+
true,
|
|
378
401
|
);
|
|
379
402
|
if (launchState.didRollback || launchState.consumedFirstTime) {
|
|
380
|
-
this.persistState(launchState
|
|
403
|
+
this.persistState(launchState, {
|
|
404
|
+
markFirstLoadMarker: launchState.consumedFirstTime,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (launchState.consumedFirstTime) {
|
|
408
|
+
UpdateContext.ignoreRollback = true;
|
|
381
409
|
}
|
|
382
410
|
|
|
383
411
|
let version = launchState.loadVersion || '';
|
package/harmony/pushy.har
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from './type';
|
|
29
29
|
import {
|
|
30
30
|
assertWeb,
|
|
31
|
+
computeProgress,
|
|
31
32
|
DEFAULT_FETCH_TIMEOUT_MS,
|
|
32
33
|
emptyObj,
|
|
33
34
|
fetchWithTimeout,
|
|
@@ -491,13 +492,19 @@ export class Pushy {
|
|
|
491
492
|
}
|
|
492
493
|
const patchStartTime = Date.now();
|
|
493
494
|
if (onDownloadProgress) {
|
|
495
|
+
const wrapProgress = (data: ProgressData) => {
|
|
496
|
+
onDownloadProgress({
|
|
497
|
+
...data,
|
|
498
|
+
progress: computeProgress(data.received, data.total),
|
|
499
|
+
});
|
|
500
|
+
};
|
|
494
501
|
// @ts-expect-error harmony not in existing platforms
|
|
495
502
|
if (Platform.OS === 'harmony') {
|
|
496
503
|
sharedState.progressHandlers[hash] = DeviceEventEmitter.addListener(
|
|
497
504
|
'RCTPushyDownloadProgress',
|
|
498
|
-
progressData => {
|
|
505
|
+
(progressData: ProgressData) => {
|
|
499
506
|
if (progressData.hash === hash) {
|
|
500
|
-
|
|
507
|
+
wrapProgress(progressData);
|
|
501
508
|
}
|
|
502
509
|
},
|
|
503
510
|
);
|
|
@@ -505,54 +512,47 @@ export class Pushy {
|
|
|
505
512
|
sharedState.progressHandlers[hash] =
|
|
506
513
|
pushyNativeEventEmitter.addListener(
|
|
507
514
|
'RCTPushyDownloadProgress',
|
|
508
|
-
progressData => {
|
|
515
|
+
(progressData: ProgressData) => {
|
|
509
516
|
if (progressData.hash === hash) {
|
|
510
|
-
|
|
517
|
+
wrapProgress(progressData);
|
|
511
518
|
}
|
|
512
519
|
},
|
|
513
520
|
);
|
|
514
521
|
}
|
|
515
522
|
}
|
|
523
|
+
const maxRetries = Math.max(0, Math.floor(this.options.maxRetries ?? 3));
|
|
516
524
|
let succeeded = '';
|
|
517
|
-
this.report({
|
|
518
|
-
type: 'downloading',
|
|
519
|
-
data: {
|
|
520
|
-
newVersion: hash,
|
|
521
|
-
},
|
|
522
|
-
});
|
|
523
525
|
let lastError: any;
|
|
524
526
|
const errorMessages: string[] = [];
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
succeeded = 'diff';
|
|
535
|
-
} catch (e: any) {
|
|
536
|
-
const errorMessage = this.t('error_diff_failed', {
|
|
537
|
-
message: e.message,
|
|
538
|
-
});
|
|
539
|
-
errorMessages.push(errorMessage);
|
|
540
|
-
lastError = Error(errorMessage);
|
|
541
|
-
log(errorMessage);
|
|
527
|
+
|
|
528
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
529
|
+
if (attempt > 0) {
|
|
530
|
+
const backoffMs = Math.min(1000 * 2 ** (attempt - 1), 10000);
|
|
531
|
+
log(`retry attempt ${attempt}/${maxRetries}, waiting ${backoffMs}ms`);
|
|
532
|
+
await new Promise(r => setTimeout(r, backoffMs));
|
|
533
|
+
errorMessages.length = 0;
|
|
534
|
+
lastError = undefined;
|
|
535
|
+
succeeded = '';
|
|
542
536
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
537
|
+
this.report({
|
|
538
|
+
type: 'downloading',
|
|
539
|
+
data: {
|
|
540
|
+
newVersion: hash,
|
|
541
|
+
attempt,
|
|
542
|
+
},
|
|
543
|
+
});
|
|
544
|
+
const diffUrl = await testUrls(joinUrls(paths, diff));
|
|
545
|
+
if (diffUrl && !__DEV__) {
|
|
546
|
+
log('downloading diff');
|
|
548
547
|
try {
|
|
549
|
-
await PushyModule.
|
|
550
|
-
updateUrl:
|
|
548
|
+
await PushyModule.downloadPatchFromPpk({
|
|
549
|
+
updateUrl: diffUrl,
|
|
551
550
|
hash,
|
|
551
|
+
originHash: currentVersion,
|
|
552
552
|
});
|
|
553
|
-
succeeded = '
|
|
553
|
+
succeeded = 'diff';
|
|
554
554
|
} catch (e: any) {
|
|
555
|
-
const errorMessage = this.t('
|
|
555
|
+
const errorMessage = this.t('error_diff_failed', {
|
|
556
556
|
message: e.message,
|
|
557
557
|
});
|
|
558
558
|
errorMessages.push(errorMessage);
|
|
@@ -560,28 +560,51 @@ export class Pushy {
|
|
|
560
560
|
log(errorMessage);
|
|
561
561
|
}
|
|
562
562
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
563
|
+
if (!succeeded) {
|
|
564
|
+
const pdiffUrl = await testUrls(joinUrls(paths, pdiff));
|
|
565
|
+
if (pdiffUrl && !__DEV__) {
|
|
566
|
+
log('downloading pdiff');
|
|
567
|
+
try {
|
|
568
|
+
await PushyModule.downloadPatchFromPackage({
|
|
569
|
+
updateUrl: pdiffUrl,
|
|
570
|
+
hash,
|
|
571
|
+
});
|
|
572
|
+
succeeded = 'pdiff';
|
|
573
|
+
} catch (e: any) {
|
|
574
|
+
const errorMessage = this.t('error_pdiff_failed', {
|
|
575
|
+
message: e.message,
|
|
576
|
+
});
|
|
577
|
+
errorMessages.push(errorMessage);
|
|
578
|
+
lastError = Error(errorMessage);
|
|
579
|
+
log(errorMessage);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (!succeeded) {
|
|
584
|
+
const fullUrl = await testUrls(joinUrls(paths, full));
|
|
585
|
+
if (fullUrl) {
|
|
586
|
+
log('downloading full patch');
|
|
587
|
+
try {
|
|
588
|
+
await PushyModule.downloadFullUpdate({
|
|
589
|
+
updateUrl: fullUrl,
|
|
590
|
+
hash,
|
|
591
|
+
});
|
|
592
|
+
succeeded = 'full';
|
|
593
|
+
} catch (e: any) {
|
|
594
|
+
const errorMessage = this.t('error_full_patch_failed', {
|
|
595
|
+
message: e.message,
|
|
596
|
+
});
|
|
597
|
+
errorMessages.push(errorMessage);
|
|
598
|
+
lastError = Error(errorMessage);
|
|
599
|
+
log(errorMessage);
|
|
600
|
+
}
|
|
601
|
+
} else if (__DEV__) {
|
|
602
|
+
log(this.t('dev_incremental_update_disabled'));
|
|
573
603
|
succeeded = 'full';
|
|
574
|
-
} catch (e: any) {
|
|
575
|
-
const errorMessage = this.t('error_full_patch_failed', {
|
|
576
|
-
message: e.message,
|
|
577
|
-
});
|
|
578
|
-
errorMessages.push(errorMessage);
|
|
579
|
-
lastError = Error(errorMessage);
|
|
580
|
-
log(errorMessage);
|
|
581
604
|
}
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
|
|
605
|
+
}
|
|
606
|
+
if (succeeded) {
|
|
607
|
+
break;
|
|
585
608
|
}
|
|
586
609
|
}
|
|
587
610
|
if (sharedState.progressHandlers[hash]) {
|
package/src/globals.d.ts
ADDED
package/src/type.ts
CHANGED
|
@@ -33,6 +33,8 @@ export interface ProgressData {
|
|
|
33
33
|
hash: string;
|
|
34
34
|
received: number;
|
|
35
35
|
total: number;
|
|
36
|
+
/** Download progress percentage (0-100), computed from received / total and clamped to range. Only populated in downloadUpdate callbacks. */
|
|
37
|
+
progress?: number;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
// 用于描述一次检查结束后的最终状态,便于业务侧感知成功、跳过或失败
|
|
@@ -119,6 +121,8 @@ export interface ClientOptions {
|
|
|
119
121
|
) => Promise<boolean | void> | boolean | void;
|
|
120
122
|
onPackageExpired?: (info: CheckResult) => Promise<boolean> | boolean;
|
|
121
123
|
overridePackageVersion?: string;
|
|
124
|
+
/** Maximum number of retry attempts for failed downloads (default: 3) */
|
|
125
|
+
maxRetries?: number;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
export interface UpdateTestPayload {
|
package/src/utils.ts
CHANGED
|
@@ -108,6 +108,11 @@ export const assertWeb = () => {
|
|
|
108
108
|
return true;
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
+
export const computeProgress = (received: number, total: number): number =>
|
|
112
|
+
total > 0
|
|
113
|
+
? Math.min(100, Math.max(0, Math.floor((received / total) * 100)))
|
|
114
|
+
: 0;
|
|
115
|
+
|
|
111
116
|
export const fetchWithTimeout = (
|
|
112
117
|
url: string,
|
|
113
118
|
params: Parameters<typeof fetch>[1],
|