@hot-updater/react-native 0.20.11 → 0.20.13
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/main/java/com/hotupdater/HotUpdater.kt +1 -1
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +6 -6
- package/android/src/newarch/HotUpdaterModule.kt +11 -5
- package/android/src/newarch/ReactIntegrationManager.kt +40 -2
- package/android/src/oldarch/HotUpdaterModule.kt +11 -5
- package/android/src/oldarch/HotUpdaterSpec.kt +1 -1
- package/android/src/oldarch/ReactIntegrationManager.kt +36 -2
- package/ios/HotUpdater/Internal/HotUpdater.mm +18 -15
- package/lib/commonjs/index.js +21 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +34 -15
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/runUpdateProcess.js +2 -2
- package/lib/commonjs/runUpdateProcess.js.map +1 -1
- package/lib/commonjs/store.js +13 -2
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/wrap.js +1 -1
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/index.js +21 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +32 -14
- package/lib/module/native.js.map +1 -1
- package/lib/module/runUpdateProcess.js +2 -2
- package/lib/module/runUpdateProcess.js.map +1 -1
- package/lib/module/store.js +13 -2
- package/lib/module/store.js.map +1 -1
- package/lib/module/wrap.js +2 -3
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +23 -5
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +1 -1
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/runUpdateProcess.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +1 -1
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +23 -5
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +1 -1
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/runUpdateProcess.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +1 -1
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/package.json +5 -5
- package/plugin/build/withHotUpdater.js +0 -1
- package/src/checkForUpdate.ts +1 -1
- package/src/index.ts +22 -5
- package/src/native.ts +38 -14
- package/src/runUpdateProcess.ts +2 -2
- package/src/specs/NativeHotUpdater.ts +1 -1
- package/src/store.ts +18 -3
- package/src/wrap.tsx +2 -3
package/src/native.ts
CHANGED
|
@@ -34,6 +34,11 @@ export type UpdateParams = UpdateBundleParams & {
|
|
|
34
34
|
status: UpdateStatus;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
// In-flight update deduplication by bundleId (session-scoped).
|
|
38
|
+
const inflightUpdates = new Map<string, Promise<boolean>>();
|
|
39
|
+
// Tracks the last successfully installed bundleId for this session.
|
|
40
|
+
let lastInstalledBundleId: string | null = null;
|
|
41
|
+
|
|
37
42
|
/**
|
|
38
43
|
* Downloads files and applies them to the app.
|
|
39
44
|
*
|
|
@@ -60,6 +65,11 @@ export async function updateBundle(
|
|
|
60
65
|
const status =
|
|
61
66
|
typeof paramsOrBundleId === "string" ? "UPDATE" : paramsOrBundleId.status;
|
|
62
67
|
|
|
68
|
+
// If we have already installed this bundle in this session, skip re-download.
|
|
69
|
+
if (status === "UPDATE" && lastInstalledBundleId === updateBundleId) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
const currentBundleId = getBundleId();
|
|
64
74
|
|
|
65
75
|
// updateBundleId <= currentBundleId
|
|
@@ -72,16 +82,32 @@ export async function updateBundle(
|
|
|
72
82
|
);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
if
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
// In-flight guard: return the same promise if the same bundle is already updating.
|
|
86
|
+
const existing = inflightUpdates.get(updateBundleId);
|
|
87
|
+
if (existing) return existing;
|
|
88
|
+
|
|
89
|
+
const targetFileUrl =
|
|
90
|
+
typeof paramsOrBundleId === "string"
|
|
91
|
+
? (fileUrl ?? null)
|
|
92
|
+
: paramsOrBundleId.fileUrl;
|
|
93
|
+
|
|
94
|
+
const promise = (async () => {
|
|
95
|
+
try {
|
|
96
|
+
const ok = await HotUpdaterNative.updateBundle({
|
|
97
|
+
bundleId: updateBundleId,
|
|
98
|
+
fileUrl: targetFileUrl,
|
|
99
|
+
});
|
|
100
|
+
if (ok) {
|
|
101
|
+
lastInstalledBundleId = updateBundleId;
|
|
102
|
+
}
|
|
103
|
+
return ok;
|
|
104
|
+
} finally {
|
|
105
|
+
inflightUpdates.delete(updateBundleId);
|
|
106
|
+
}
|
|
107
|
+
})();
|
|
108
|
+
|
|
109
|
+
inflightUpdates.set(updateBundleId, promise);
|
|
110
|
+
return promise;
|
|
85
111
|
}
|
|
86
112
|
|
|
87
113
|
/**
|
|
@@ -95,10 +121,8 @@ export const getAppVersion = (): string | null => {
|
|
|
95
121
|
/**
|
|
96
122
|
* Reloads the app.
|
|
97
123
|
*/
|
|
98
|
-
export const reload = () => {
|
|
99
|
-
|
|
100
|
-
HotUpdaterNative.reload();
|
|
101
|
-
});
|
|
124
|
+
export const reload = async () => {
|
|
125
|
+
await HotUpdaterNative.reload();
|
|
102
126
|
};
|
|
103
127
|
|
|
104
128
|
/**
|
package/src/runUpdateProcess.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface RunUpdateProcessOptions extends CheckForUpdateOptions {
|
|
|
43
43
|
* });
|
|
44
44
|
*
|
|
45
45
|
* if(result.status !== "UP_TO_DATE" && result.shouldForceUpdate) {
|
|
46
|
-
* HotUpdater.reload();
|
|
46
|
+
* await HotUpdater.reload();
|
|
47
47
|
* }
|
|
48
48
|
* ```
|
|
49
49
|
*
|
|
@@ -65,7 +65,7 @@ export const runUpdateProcess = async ({
|
|
|
65
65
|
|
|
66
66
|
const isUpdated = await updateInfo.updateBundle();
|
|
67
67
|
if (isUpdated && updateInfo.shouldForceUpdate && reloadOnForceUpdate) {
|
|
68
|
-
reload();
|
|
68
|
+
await reload();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
if (!isUpdated) {
|
package/src/store.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import useSyncExternalStoreExports from "use-sync-external-store/shim/with-selector";
|
|
2
2
|
export type HotUpdaterState = {
|
|
3
3
|
progress: number;
|
|
4
|
-
|
|
4
|
+
isUpdateDownloaded: boolean;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports;
|
|
@@ -9,7 +9,7 @@ const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports;
|
|
|
9
9
|
const createHotUpdaterStore = () => {
|
|
10
10
|
let state: HotUpdaterState = {
|
|
11
11
|
progress: 0,
|
|
12
|
-
|
|
12
|
+
isUpdateDownloaded: false,
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
const getSnapshot = () => {
|
|
@@ -25,10 +25,25 @@ const createHotUpdaterStore = () => {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const setState = (newState: Partial<HotUpdaterState>) => {
|
|
28
|
-
|
|
28
|
+
// Merge first, then normalize derived fields
|
|
29
|
+
const nextState: HotUpdaterState = {
|
|
29
30
|
...state,
|
|
30
31
|
...newState,
|
|
31
32
|
};
|
|
33
|
+
|
|
34
|
+
// Derive `isUpdateDownloaded` from `progress` if provided.
|
|
35
|
+
// If `progress` is not provided but `isUpdateDownloaded` is,
|
|
36
|
+
// honor the explicit value.
|
|
37
|
+
if ("progress" in newState && typeof newState.progress === "number") {
|
|
38
|
+
nextState.isUpdateDownloaded = newState.progress >= 1;
|
|
39
|
+
} else if (
|
|
40
|
+
"isUpdateDownloaded" in newState &&
|
|
41
|
+
typeof newState.isUpdateDownloaded === "boolean"
|
|
42
|
+
) {
|
|
43
|
+
nextState.isUpdateDownloaded = newState.isUpdateDownloaded;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
state = nextState;
|
|
32
47
|
emitChange();
|
|
33
48
|
};
|
|
34
49
|
|
package/src/wrap.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useEffect, useLayoutEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useLayoutEffect, useState } from "react";
|
|
3
2
|
import { type CheckForUpdateOptions, checkForUpdate } from "./checkForUpdate";
|
|
4
3
|
import type { HotUpdaterError } from "./error";
|
|
5
4
|
import { useEventCallback } from "./hooks/useEventCallback";
|
|
@@ -117,7 +116,7 @@ export function wrap<P extends React.JSX.IntrinsicAttributes = object>(
|
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
if (reloadOnForceUpdate) {
|
|
120
|
-
reload();
|
|
119
|
+
await reload();
|
|
121
120
|
}
|
|
122
121
|
|
|
123
122
|
restOptions.onUpdateProcessCompleted?.({
|