react-native-update 10.48.1 → 10.48.3
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-CN.md +40 -4
- package/README.md +40 -4
- package/android/src/main/java/cn/reactnative/modules/update/UpdateEventEmitter.java +13 -4
- package/biome.json +59 -0
- package/harmony/pushy/src/main/ets/DownloadTask.ts +2 -2
- package/harmony/pushy.har +0 -0
- package/package.json +5 -6
- package/src/NativePushy.ts +2 -1
- package/src/client.ts +62 -54
- package/src/context.ts +7 -7
- package/src/core.ts +51 -51
- package/src/endpoint.ts +7 -7
- package/src/error.ts +3 -3
- package/src/i18n.ts +2 -2
- package/src/index.ts +4 -4
- package/src/isInRollout.ts +10 -1
- package/src/provider.tsx +46 -56
- package/src/resolveCheckResult.ts +1 -1
- package/src/telemetry.ts +1 -1
- package/src/type.ts +2 -2
- package/src/utils.ts +30 -30
- package/.eslintrc.js +0 -4
- package/.prettierrc.js +0 -6
package/src/context.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { createContext, useContext, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { Pushy, Cresc } from './client';
|
|
2
|
+
import type { Cresc, Pushy } from './client';
|
|
4
3
|
import i18n from './i18n';
|
|
4
|
+
import type { CheckResult, ProgressData } from './type';
|
|
5
5
|
|
|
6
6
|
const noop = () => {};
|
|
7
|
-
const asyncNoop = () => Promise.resolve();
|
|
7
|
+
const asyncNoop = () => Promise.resolve(undefined);
|
|
8
8
|
|
|
9
9
|
export const defaultContext = {
|
|
10
10
|
checkUpdate: asyncNoop,
|
|
@@ -24,12 +24,12 @@ export const defaultContext = {
|
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
export const UpdateContext = createContext<{
|
|
27
|
-
checkUpdate: () => Promise<
|
|
27
|
+
checkUpdate: () => Promise<undefined | CheckResult>;
|
|
28
28
|
switchVersion: () => Promise<void>;
|
|
29
29
|
switchVersionLater: () => Promise<void>;
|
|
30
30
|
markSuccess: () => void;
|
|
31
31
|
dismissError: () => void;
|
|
32
|
-
downloadUpdate: () => Promise<boolean |
|
|
32
|
+
downloadUpdate: () => Promise<boolean | undefined>;
|
|
33
33
|
downloadAndInstallApk: (url: string) => Promise<void>;
|
|
34
34
|
// @deprecated use currentVersionInfo instead
|
|
35
35
|
getCurrentVersionInfo: () => Promise<{
|
|
@@ -46,7 +46,7 @@ export const UpdateContext = createContext<{
|
|
|
46
46
|
restartApp: () => Promise<void>;
|
|
47
47
|
resetToPackagedBundle: (options?: {
|
|
48
48
|
restart?: boolean;
|
|
49
|
-
}) => Promise<boolean |
|
|
49
|
+
}) => Promise<boolean | undefined>;
|
|
50
50
|
currentHash: string;
|
|
51
51
|
packageVersion: string;
|
|
52
52
|
client?: Pushy | Cresc;
|
|
@@ -58,7 +58,7 @@ export const UpdateContext = createContext<{
|
|
|
58
58
|
// otherwise every tick would re-render all useUpdate() consumers even when
|
|
59
59
|
// they never read progress.
|
|
60
60
|
export const ProgressContext = createContext<ProgressData | undefined>(
|
|
61
|
-
undefined
|
|
61
|
+
undefined
|
|
62
62
|
);
|
|
63
63
|
|
|
64
64
|
/**
|
package/src/core.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
|
-
import i18n from './i18n';
|
|
3
2
|
import { UpdateError } from './error';
|
|
3
|
+
import i18n from './i18n';
|
|
4
4
|
import { emptyModule, error, log } from './utils';
|
|
5
5
|
|
|
6
6
|
/* eslint-disable @react-native/no-deep-imports */
|
|
7
7
|
const {
|
|
8
|
-
|
|
8
|
+
version: v,
|
|
9
9
|
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
|
10
10
|
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
|
11
11
|
const isTurboModuleEnabled =
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// https://github.com/facebook/react-native/pull/48362
|
|
13
|
+
(global as any).__turboModuleProxy || (global as any).RN$Bridgeless;
|
|
14
14
|
|
|
15
15
|
export const PushyModule =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
Platform.OS === 'web'
|
|
17
|
+
? emptyModule
|
|
18
|
+
: isTurboModuleEnabled
|
|
19
|
+
? require('./NativePushy').default
|
|
20
|
+
: NativeModules.Pushy;
|
|
21
21
|
|
|
22
22
|
export const UpdateModule = PushyModule;
|
|
23
23
|
|
|
24
24
|
if (!PushyModule) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
throw new UpdateError(
|
|
26
|
+
'Failed to load react-native-update native module, please try to recompile',
|
|
27
|
+
'MODULE_NOT_LOADED'
|
|
28
|
+
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const PushyConstants = isTurboModuleEnabled
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
? PushyModule.getConstants()
|
|
33
|
+
: PushyModule;
|
|
34
34
|
|
|
35
35
|
export const downloadRootDir: string = PushyConstants.downloadRootDir;
|
|
36
36
|
export const packageVersion: string = PushyConstants.packageVersion;
|
|
37
37
|
export const currentVersion: string = PushyConstants.currentVersion;
|
|
38
38
|
|
|
39
39
|
export function setLocalHashInfo(hash: string, info: Record<string, any>) {
|
|
40
|
-
|
|
40
|
+
PushyModule.setLocalHashInfo(hash, JSON.stringify(info));
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const currentVersionInfoString: string = PushyConstants.currentVersionInfo;
|
|
44
44
|
let _currentVersionInfo: Record<string, any> = {};
|
|
45
45
|
let isDebugChannel = false;
|
|
46
46
|
if (currentVersionInfoString) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
try {
|
|
48
|
+
_currentVersionInfo = JSON.parse(currentVersionInfoString);
|
|
49
|
+
if (_currentVersionInfo.debugChannel) {
|
|
50
|
+
isDebugChannel = true;
|
|
51
|
+
delete _currentVersionInfo.debugChannel;
|
|
52
|
+
setLocalHashInfo(currentVersion, _currentVersionInfo);
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
error(
|
|
56
|
+
i18n.t('error_parse_version_info', { info: currentVersionInfoString })
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
59
|
}
|
|
60
60
|
export const currentVersionInfo = _currentVersionInfo;
|
|
61
61
|
|
|
@@ -68,46 +68,46 @@ export const buildTime: string = PushyConstants.buildTime;
|
|
|
68
68
|
// 原生 patch 内核可消费的 diff 轨道版本(2 = hdiffv2 轨道:HBC 变换 +
|
|
69
69
|
// 流式容器);旧原生无此常量时为 0(不上报,服务端只发 baseline)
|
|
70
70
|
export const supportedDiffVersion: number =
|
|
71
|
-
|
|
71
|
+
PushyConstants.supportedDiffVersion || 0;
|
|
72
72
|
let uuid = PushyConstants.uuid;
|
|
73
73
|
|
|
74
74
|
async function getLocalHashInfo(hash: string) {
|
|
75
|
-
|
|
75
|
+
return JSON.parse(await PushyModule.getLocalHashInfo(hash));
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// @deprecated use currentVersionInfo instead
|
|
79
79
|
export async function getCurrentVersionInfo(): Promise<{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
name?: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
metaInfo?: string;
|
|
83
83
|
}> {
|
|
84
|
-
|
|
84
|
+
return currentVersion ? (await getLocalHashInfo(currentVersion)) || {} : {};
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
export const pushyNativeEventEmitter = new NativeEventEmitter(PushyModule);
|
|
88
88
|
|
|
89
89
|
if (!uuid) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
uuid = require('nanoid/non-secure').nanoid();
|
|
91
|
+
// If persisting fails the uuid drifts on every launch, which skews gray
|
|
92
|
+
// release bucketing and inflates stats — log it instead of failing silently.
|
|
93
|
+
Promise.resolve(PushyModule.setUuid(uuid)).catch((e: any) => {
|
|
94
|
+
log('setUuid error:', e?.message || e);
|
|
95
|
+
});
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export const cInfo = {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
rnu: require('../package.json').version,
|
|
100
|
+
rn: RNVersion,
|
|
101
|
+
os: `${Platform.OS} ${Platform.Version}`,
|
|
102
|
+
uuid,
|
|
103
103
|
};
|
|
104
104
|
|
|
105
105
|
log('bootup status', {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
packageVersion,
|
|
107
|
+
currentVersion,
|
|
108
|
+
currentVersionInfo,
|
|
109
|
+
isFirstTime,
|
|
110
|
+
isFirstTimeDebug,
|
|
111
|
+
isDebugChannel,
|
|
112
|
+
cInfo,
|
|
113
113
|
});
|
package/src/endpoint.ts
CHANGED
|
@@ -28,7 +28,7 @@ const normalizeError = (error: unknown) => {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export const dedupeEndpoints = (
|
|
31
|
-
endpoints: Array<string | null | undefined
|
|
31
|
+
endpoints: Array<string | null | undefined>
|
|
32
32
|
): string[] => {
|
|
33
33
|
const result: string[] = [];
|
|
34
34
|
const visited = new Set<string>();
|
|
@@ -46,7 +46,7 @@ export const dedupeEndpoints = (
|
|
|
46
46
|
|
|
47
47
|
export const pickRandomEndpoint = (
|
|
48
48
|
endpoints: string[],
|
|
49
|
-
random: () => number = Math.random
|
|
49
|
+
random: () => number = Math.random
|
|
50
50
|
) => {
|
|
51
51
|
if (!endpoints.length) {
|
|
52
52
|
throw new UpdateError('No endpoints configured', 'NO_ENDPOINTS');
|
|
@@ -57,13 +57,13 @@ export const pickRandomEndpoint = (
|
|
|
57
57
|
export async function selectFastestSuccessfulEndpoint<T>(
|
|
58
58
|
endpoints: string[],
|
|
59
59
|
tryEndpoint: (endpoint: string) => Promise<T>,
|
|
60
|
-
now: () => number = Date.now
|
|
60
|
+
now: () => number = Date.now
|
|
61
61
|
): Promise<{
|
|
62
62
|
successes: EndpointAttemptSuccess<T>[];
|
|
63
63
|
failures: EndpointAttemptFailure[];
|
|
64
64
|
}> {
|
|
65
65
|
const attempts = await Promise.all(
|
|
66
|
-
endpoints.map(async endpoint => {
|
|
66
|
+
endpoints.map(async (endpoint) => {
|
|
67
67
|
const start = now();
|
|
68
68
|
try {
|
|
69
69
|
const value = await tryEndpoint(endpoint);
|
|
@@ -80,7 +80,7 @@ export async function selectFastestSuccessfulEndpoint<T>(
|
|
|
80
80
|
error: normalizeError(error),
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
})
|
|
83
|
+
})
|
|
84
84
|
);
|
|
85
85
|
|
|
86
86
|
const successes: EndpointAttemptSuccess<T>[] = [];
|
|
@@ -147,7 +147,7 @@ export async function executeEndpointFallback<T>({
|
|
|
147
147
|
? await getRemoteEndpoints().catch(() => [])
|
|
148
148
|
: [];
|
|
149
149
|
candidates = dedupeEndpoints([...candidates, ...remoteEndpoints]).filter(
|
|
150
|
-
endpoint => !excludedEndpoints.has(endpoint)
|
|
150
|
+
(endpoint) => !excludedEndpoints.has(endpoint)
|
|
151
151
|
);
|
|
152
152
|
|
|
153
153
|
if (!candidates.length) {
|
|
@@ -157,7 +157,7 @@ export async function executeEndpointFallback<T>({
|
|
|
157
157
|
const { successes, failures } = await selectFastestSuccessfulEndpoint(
|
|
158
158
|
candidates,
|
|
159
159
|
tryEndpoint,
|
|
160
|
-
now
|
|
160
|
+
now
|
|
161
161
|
);
|
|
162
162
|
|
|
163
163
|
if (successes.length) {
|
package/src/error.ts
CHANGED
|
@@ -62,7 +62,7 @@ const KNOWN_CODES = new Set<string>([
|
|
|
62
62
|
* else is treated as absent so it never leaks into telemetry aggregation.
|
|
63
63
|
*/
|
|
64
64
|
export const asUpdateErrorCode = (
|
|
65
|
-
code: unknown
|
|
65
|
+
code: unknown
|
|
66
66
|
): UpdateErrorCode | undefined =>
|
|
67
67
|
typeof code === 'string' && KNOWN_CODES.has(code)
|
|
68
68
|
? (code as UpdateErrorCode)
|
|
@@ -76,7 +76,7 @@ export class UpdateError extends Error {
|
|
|
76
76
|
constructor(
|
|
77
77
|
message: string,
|
|
78
78
|
code: UpdateErrorCode,
|
|
79
|
-
options?: { cause?: unknown; extra?: Record<string, string | number> }
|
|
79
|
+
options?: { cause?: unknown; extra?: Record<string, string | number> }
|
|
80
80
|
) {
|
|
81
81
|
super(message);
|
|
82
82
|
this.name = 'UpdateError';
|
|
@@ -96,7 +96,7 @@ export class UpdateError extends Error {
|
|
|
96
96
|
*/
|
|
97
97
|
export const toUpdateError = (
|
|
98
98
|
e: unknown,
|
|
99
|
-
code: UpdateErrorCode
|
|
99
|
+
code: UpdateErrorCode
|
|
100
100
|
): UpdateError => {
|
|
101
101
|
if (e instanceof Error) {
|
|
102
102
|
const err = e as UpdateError;
|
package/src/i18n.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import zhTranslations from './locales/zh';
|
|
2
1
|
import enTranslations from './locales/en';
|
|
2
|
+
import zhTranslations from './locales/zh';
|
|
3
3
|
|
|
4
4
|
type TranslationKey = keyof typeof zhTranslations | keyof typeof enTranslations;
|
|
5
5
|
type TranslationValues = Record<string, string | number>;
|
|
@@ -92,7 +92,7 @@ class I18n {
|
|
|
92
92
|
const i18n = new I18n();
|
|
93
93
|
|
|
94
94
|
// Export both the instance and the class for flexibility
|
|
95
|
-
export {
|
|
95
|
+
export { I18n, i18n };
|
|
96
96
|
export default i18n;
|
|
97
97
|
|
|
98
98
|
/**
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export { Pushy, Cresc } from './client';
|
|
2
1
|
export type { UpdateErrorListener } from './client';
|
|
3
|
-
export {
|
|
4
|
-
export type { UpdateErrorCode } from './error';
|
|
2
|
+
export { Cresc, Pushy } from './client';
|
|
5
3
|
export {
|
|
6
4
|
ProgressContext,
|
|
7
5
|
UpdateContext,
|
|
@@ -9,5 +7,7 @@ export {
|
|
|
9
7
|
useUpdate,
|
|
10
8
|
useUpdateProgress,
|
|
11
9
|
} from './context';
|
|
12
|
-
export { PushyProvider, UpdateProvider } from './provider';
|
|
13
10
|
export { PushyModule, UpdateModule } from './core';
|
|
11
|
+
export type { UpdateErrorCode } from './error';
|
|
12
|
+
export { UpdateError } from './error';
|
|
13
|
+
export { PushyProvider, UpdateProvider } from './provider';
|
package/src/isInRollout.ts
CHANGED
|
@@ -4,7 +4,14 @@ import { cInfo } from './core';
|
|
|
4
4
|
|
|
5
5
|
/* eslint-disable no-bitwise */
|
|
6
6
|
export function murmurhash3_32_gc(key: string, seed = 0) {
|
|
7
|
-
let remainder
|
|
7
|
+
let remainder: number,
|
|
8
|
+
bytes: number,
|
|
9
|
+
h1: number,
|
|
10
|
+
h1b: number,
|
|
11
|
+
c1: number,
|
|
12
|
+
c2: number,
|
|
13
|
+
k1: number,
|
|
14
|
+
i: number;
|
|
8
15
|
|
|
9
16
|
remainder = key.length & 3; // key.length % 4
|
|
10
17
|
bytes = key.length - remainder;
|
|
@@ -36,8 +43,10 @@ export function murmurhash3_32_gc(key: string, seed = 0) {
|
|
|
36
43
|
k1 = 0;
|
|
37
44
|
|
|
38
45
|
switch (remainder) {
|
|
46
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: MurmurHash fallthrough
|
|
39
47
|
case 3:
|
|
40
48
|
k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
|
|
49
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: MurmurHash fallthrough
|
|
41
50
|
case 2:
|
|
42
51
|
k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
|
|
43
52
|
case 1:
|
package/src/provider.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
// biome-ignore lint/correctness/noUnusedImports: preserve React import for compatibility with older React versions
|
|
1
2
|
import React, {
|
|
2
|
-
ReactNode,
|
|
3
|
+
type ReactNode,
|
|
3
4
|
useCallback,
|
|
4
5
|
useEffect,
|
|
5
6
|
useMemo,
|
|
@@ -8,26 +9,22 @@ import React, {
|
|
|
8
9
|
} from 'react';
|
|
9
10
|
import {
|
|
10
11
|
Alert,
|
|
11
|
-
NativeEventSubscription,
|
|
12
12
|
AppState,
|
|
13
|
-
Platform,
|
|
14
13
|
Linking,
|
|
14
|
+
type NativeEventSubscription,
|
|
15
|
+
Platform,
|
|
15
16
|
} from 'react-native';
|
|
16
|
-
import {
|
|
17
|
+
import { URL } from 'react-native-url-polyfill';
|
|
18
|
+
import { type Cresc, type Pushy, sharedState } from './client';
|
|
19
|
+
import { ProgressContext, UpdateContext } from './context';
|
|
17
20
|
import {
|
|
18
21
|
currentVersion,
|
|
19
|
-
packageVersion,
|
|
20
|
-
getCurrentVersionInfo,
|
|
21
22
|
currentVersionInfo,
|
|
23
|
+
getCurrentVersionInfo,
|
|
24
|
+
packageVersion,
|
|
22
25
|
} from './core';
|
|
23
|
-
import {
|
|
24
|
-
CheckResult,
|
|
25
|
-
ProgressData,
|
|
26
|
-
UpdateTestPayload,
|
|
27
|
-
} from './type';
|
|
28
|
-
import { ProgressContext, UpdateContext } from './context';
|
|
29
|
-
import { URL } from 'react-native-url-polyfill';
|
|
30
26
|
import { resolveCheckResult } from './resolveCheckResult';
|
|
27
|
+
import type { CheckResult, ProgressData, UpdateTestPayload } from './type';
|
|
31
28
|
import { assertWeb, log, noop } from './utils';
|
|
32
29
|
|
|
33
30
|
export const UpdateProvider = ({
|
|
@@ -59,7 +56,7 @@ export const UpdateProvider = ({
|
|
|
59
56
|
Alert.alert(...args);
|
|
60
57
|
}
|
|
61
58
|
},
|
|
62
|
-
[options.updateStrategy]
|
|
59
|
+
[options.updateStrategy]
|
|
63
60
|
);
|
|
64
61
|
|
|
65
62
|
const alertError = useCallback(
|
|
@@ -68,7 +65,7 @@ export const UpdateProvider = ({
|
|
|
68
65
|
Alert.alert(...args);
|
|
69
66
|
}
|
|
70
67
|
},
|
|
71
|
-
[options.updateStrategy]
|
|
68
|
+
[options.updateStrategy]
|
|
72
69
|
);
|
|
73
70
|
|
|
74
71
|
// All client errors flow through this single subscription (regardless of
|
|
@@ -82,35 +79,35 @@ export const UpdateProvider = ({
|
|
|
82
79
|
client.t(
|
|
83
80
|
eventType === 'errorChecking'
|
|
84
81
|
? 'error_update_check_failed'
|
|
85
|
-
: 'update_failed'
|
|
82
|
+
: 'update_failed'
|
|
86
83
|
),
|
|
87
|
-
e.message
|
|
84
|
+
e.message
|
|
88
85
|
);
|
|
89
86
|
}),
|
|
90
|
-
[client, alertError]
|
|
87
|
+
[client, alertError]
|
|
91
88
|
);
|
|
92
89
|
|
|
93
90
|
const switchVersion = useCallback(
|
|
94
91
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
|
95
|
-
if (info
|
|
92
|
+
if (info?.hash) {
|
|
96
93
|
return client.switchVersion(info.hash);
|
|
97
94
|
}
|
|
98
95
|
},
|
|
99
|
-
[client]
|
|
96
|
+
[client]
|
|
100
97
|
);
|
|
101
98
|
|
|
102
99
|
const switchVersionLater = useCallback(
|
|
103
100
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
|
104
|
-
if (info
|
|
101
|
+
if (info?.hash) {
|
|
105
102
|
return client.switchVersionLater(info.hash);
|
|
106
103
|
}
|
|
107
104
|
},
|
|
108
|
-
[client]
|
|
105
|
+
[client]
|
|
109
106
|
);
|
|
110
107
|
|
|
111
108
|
const downloadUpdate = useCallback(
|
|
112
109
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
|
113
|
-
if (!info
|
|
110
|
+
if (!info?.update) {
|
|
114
111
|
return false;
|
|
115
112
|
}
|
|
116
113
|
try {
|
|
@@ -167,7 +164,7 @@ export const UpdateProvider = ({
|
|
|
167
164
|
return false;
|
|
168
165
|
}
|
|
169
166
|
},
|
|
170
|
-
[client, options, alertUpdate, alertError]
|
|
167
|
+
[client, options, alertUpdate, alertError]
|
|
171
168
|
);
|
|
172
169
|
|
|
173
170
|
const downloadAndInstallApk = useCallback(
|
|
@@ -176,7 +173,7 @@ export const UpdateProvider = ({
|
|
|
176
173
|
await client.downloadAndInstallApk(downloadUrl, setProgress);
|
|
177
174
|
}
|
|
178
175
|
},
|
|
179
|
-
[client]
|
|
176
|
+
[client]
|
|
180
177
|
);
|
|
181
178
|
|
|
182
179
|
const checkUpdate = useCallback(
|
|
@@ -229,25 +226,18 @@ export const UpdateProvider = ({
|
|
|
229
226
|
}
|
|
230
227
|
return info;
|
|
231
228
|
}
|
|
232
|
-
alertUpdate(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
downloadUrl.endsWith('.apk')
|
|
242
|
-
) {
|
|
243
|
-
downloadAndInstallApk(downloadUrl).catch(noop);
|
|
244
|
-
} else {
|
|
245
|
-
Linking.openURL(downloadUrl);
|
|
246
|
-
}
|
|
247
|
-
},
|
|
229
|
+
alertUpdate(client.t('alert_title'), client.t('alert_app_updated'), [
|
|
230
|
+
{
|
|
231
|
+
text: client.t('alert_update_button'),
|
|
232
|
+
onPress: () => {
|
|
233
|
+
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
|
|
234
|
+
downloadAndInstallApk(downloadUrl).catch(noop);
|
|
235
|
+
} else {
|
|
236
|
+
Linking.openURL(downloadUrl);
|
|
237
|
+
}
|
|
248
238
|
},
|
|
249
|
-
|
|
250
|
-
);
|
|
239
|
+
},
|
|
240
|
+
]);
|
|
251
241
|
}
|
|
252
242
|
} else if (info.update) {
|
|
253
243
|
if (
|
|
@@ -272,7 +262,7 @@ export const UpdateProvider = ({
|
|
|
272
262
|
downloadUpdate().catch(noop);
|
|
273
263
|
},
|
|
274
264
|
},
|
|
275
|
-
]
|
|
265
|
+
]
|
|
276
266
|
);
|
|
277
267
|
}
|
|
278
268
|
return info;
|
|
@@ -284,7 +274,7 @@ export const UpdateProvider = ({
|
|
|
284
274
|
alertError,
|
|
285
275
|
downloadAndInstallApk,
|
|
286
276
|
downloadUpdate,
|
|
287
|
-
]
|
|
277
|
+
]
|
|
288
278
|
);
|
|
289
279
|
|
|
290
280
|
const markSuccess = client.markSuccess;
|
|
@@ -307,11 +297,11 @@ export const UpdateProvider = ({
|
|
|
307
297
|
if (checkStrategy === 'both' || checkStrategy === 'onAppResume') {
|
|
308
298
|
stateListener.current = AppState.addEventListener(
|
|
309
299
|
'change',
|
|
310
|
-
nextAppState => {
|
|
300
|
+
(nextAppState) => {
|
|
311
301
|
if (nextAppState === 'active') {
|
|
312
302
|
checkUpdate().catch(noop);
|
|
313
303
|
}
|
|
314
|
-
}
|
|
304
|
+
}
|
|
315
305
|
);
|
|
316
306
|
}
|
|
317
307
|
if (checkStrategy === 'both' || checkStrategy === 'onAppStart') {
|
|
@@ -321,9 +311,9 @@ export const UpdateProvider = ({
|
|
|
321
311
|
if (markSuccessTimer) {
|
|
322
312
|
clearTimeout(markSuccessTimer);
|
|
323
313
|
}
|
|
324
|
-
stateListener.current
|
|
314
|
+
stateListener.current?.remove();
|
|
325
315
|
};
|
|
326
|
-
}, [checkUpdate, options,
|
|
316
|
+
}, [checkUpdate, options, markSuccess, client]);
|
|
327
317
|
|
|
328
318
|
useEffect(() => {
|
|
329
319
|
const { dismissErrorAfter } = options;
|
|
@@ -343,7 +333,7 @@ export const UpdateProvider = ({
|
|
|
343
333
|
|
|
344
334
|
const parseTestPayload = useCallback(
|
|
345
335
|
(payload: UpdateTestPayload) => {
|
|
346
|
-
if (payload
|
|
336
|
+
if (payload?.type?.startsWith('__rnPushy')) {
|
|
347
337
|
const logger = options.logger || (() => {});
|
|
348
338
|
options.logger = ({ type, data }) => {
|
|
349
339
|
logger({ type, data });
|
|
@@ -354,10 +344,10 @@ export const UpdateProvider = ({
|
|
|
354
344
|
sharedState.toHash = toHash;
|
|
355
345
|
checkUpdate({ extra: { toHash } })
|
|
356
346
|
.then(() => {
|
|
357
|
-
if (updateInfoRef.current
|
|
347
|
+
if (updateInfoRef.current?.upToDate) {
|
|
358
348
|
Alert.alert(
|
|
359
349
|
client.t('alert_info'),
|
|
360
|
-
client.t('alert_no_update_wait')
|
|
350
|
+
client.t('alert_no_update_wait')
|
|
361
351
|
);
|
|
362
352
|
}
|
|
363
353
|
})
|
|
@@ -370,7 +360,7 @@ export const UpdateProvider = ({
|
|
|
370
360
|
}
|
|
371
361
|
return false;
|
|
372
362
|
},
|
|
373
|
-
[checkUpdate, options, client]
|
|
363
|
+
[checkUpdate, options, client]
|
|
374
364
|
);
|
|
375
365
|
|
|
376
366
|
const parseTestQrCode = useCallback(
|
|
@@ -383,7 +373,7 @@ export const UpdateProvider = ({
|
|
|
383
373
|
return false;
|
|
384
374
|
}
|
|
385
375
|
},
|
|
386
|
-
[parseTestPayload]
|
|
376
|
+
[parseTestPayload]
|
|
387
377
|
);
|
|
388
378
|
|
|
389
379
|
const restartApp = useCallback(async () => {
|
|
@@ -394,7 +384,7 @@ export const UpdateProvider = ({
|
|
|
394
384
|
async (resetOptions?: { restart?: boolean }) => {
|
|
395
385
|
return client.resetToPackagedBundle(resetOptions);
|
|
396
386
|
},
|
|
397
|
-
[client]
|
|
387
|
+
[client]
|
|
398
388
|
);
|
|
399
389
|
|
|
400
390
|
useEffect(() => {
|
|
@@ -469,7 +459,7 @@ export const UpdateProvider = ({
|
|
|
469
459
|
parseTestQrCode,
|
|
470
460
|
restartApp,
|
|
471
461
|
resetToPackagedBundle,
|
|
472
|
-
]
|
|
462
|
+
]
|
|
473
463
|
);
|
|
474
464
|
|
|
475
465
|
return (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { currentVersion, packageVersion } from './core';
|
|
2
2
|
import { isInRollout } from './isInRollout';
|
|
3
|
-
import { CheckResult } from './type';
|
|
3
|
+
import type { CheckResult } from './type';
|
|
4
4
|
import { log } from './utils';
|
|
5
5
|
|
|
6
6
|
export function resolveCheckResult(rootInfo: CheckResult): CheckResult {
|
package/src/telemetry.ts
CHANGED
package/src/type.ts
CHANGED
|
@@ -126,8 +126,8 @@ export interface ClientOptions {
|
|
|
126
126
|
beforeDownloadUpdate?: (info: CheckResult) => Promise<boolean> | boolean;
|
|
127
127
|
afterDownloadUpdate?: (info: CheckResult) => Promise<boolean> | boolean;
|
|
128
128
|
beforeReload?: (
|
|
129
|
-
context: BeforeReloadContext
|
|
130
|
-
) => Promise<boolean |
|
|
129
|
+
context: BeforeReloadContext
|
|
130
|
+
) => Promise<boolean | undefined> | boolean | undefined;
|
|
131
131
|
onPackageExpired?: (info: CheckResult) => Promise<boolean> | boolean;
|
|
132
132
|
overridePackageVersion?: string;
|
|
133
133
|
/** Maximum number of retry attempts for failed downloads (default: 3) */
|