@forthtilliath/expo-release-updates-ui 0.4.0 → 0.5.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/README.md +9 -3
- package/dist/UpdateNotifier.js +1 -1
- package/dist/useApkInstall.d.ts +8 -3
- package/dist/useApkInstall.d.ts.map +1 -1
- package/dist/useApkInstall.js +6 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -138,24 +138,28 @@ Mount it once near the root: it checks on launch (`useUpdateCheck`), shows the b
|
|
|
138
138
|
```tsx
|
|
139
139
|
import { UpdateNotifier } from "@forthtilliath/expo-release-updates-ui/UpdateNotifier";
|
|
140
140
|
|
|
141
|
+
const repo = { owner: "acme", repo: "app" };
|
|
142
|
+
|
|
141
143
|
<View
|
|
142
144
|
style={{ position: "absolute", top: 56, left: 16, right: 16, zIndex: 10 }}
|
|
143
145
|
>
|
|
144
146
|
<UpdateNotifier
|
|
145
147
|
enabled={settings !== undefined}
|
|
146
148
|
currentVersion={Constants.expoConfig?.version ?? "0.0.0"}
|
|
147
|
-
checkForUpdate={fetchLatestRelease}
|
|
149
|
+
checkForUpdate={() => fetchLatestRelease(repo)}
|
|
148
150
|
getLastCheck={() => ({
|
|
149
151
|
lastCheckedAt: settings?.lastUpdateCheckAt ?? null,
|
|
150
152
|
dismissedVersion: settings?.dismissedUpdateVersion ?? null,
|
|
151
153
|
})}
|
|
152
154
|
onChecked={(at) => recordUpdateCheck(at)}
|
|
153
155
|
onDismissVersion={(version) => dismissUpdateVersion(version)}
|
|
154
|
-
downloadAndInstallApk={(apkUrl, onProgress) =>
|
|
156
|
+
downloadAndInstallApk={(apkUrl, onProgress, apkSha256) =>
|
|
155
157
|
downloadAndInstallApk({
|
|
156
158
|
apkUrl,
|
|
157
159
|
fileName: "myapp-update.apk",
|
|
158
160
|
onProgress,
|
|
161
|
+
allowedUrlPrefix: releaseDownloadUrlPrefix(repo),
|
|
162
|
+
expectedSha256: apkSha256,
|
|
159
163
|
})
|
|
160
164
|
}
|
|
161
165
|
styles={{ banner: { container: { backgroundColor: colors.surface } } }}
|
|
@@ -165,7 +169,9 @@ import { UpdateNotifier } from "@forthtilliath/expo-release-updates-ui/UpdateNot
|
|
|
165
169
|
|
|
166
170
|
Pass **`enabled={false}` until the settings `getLastCheck` reads have loaded** (async database, live query…): the check runs once, on mount, so starting earlier would ignore both the 12h throttle and the dismissed version. Positioning is left to the parent. `labels` / `styles` take `{ banner, install }`, same keys as `UpdateAvailableBanner` and `UpdateInstallCard`.
|
|
167
171
|
|
|
168
|
-
|
|
172
|
+
`downloadAndInstallApk` receives the release's `apkSha256` (from `fetchLatestRelease`) as its third argument: pass it on as `expectedSha256` so a swapped or damaged APK is never installed (needs expo-file-system 58+), and restrict the URL to your repo's releases with `allowedUrlPrefix`.
|
|
173
|
+
|
|
174
|
+
The building blocks are exported too, to compose a different flow: `useApkInstall(downloadAndInstallApk)` (`{ state, start(version, apkUrl, apkSha256?), retry, reset }`) and `<UpdateInstallCard state onRetry onClose />` (renders nothing while idle).
|
|
169
175
|
|
|
170
176
|
## Scripts
|
|
171
177
|
|
package/dist/UpdateNotifier.js
CHANGED
|
@@ -37,7 +37,7 @@ function ActiveUpdateNotifier({ downloadAndInstallApk, onDismissVersion, locale
|
|
|
37
37
|
// Not persisted as dismissed: if the install doesn't go through, the
|
|
38
38
|
// banner may come back on a later launch (unlike "Ignore").
|
|
39
39
|
update.dismiss();
|
|
40
|
-
install.start(release.version, release.apkUrl);
|
|
40
|
+
install.start(release.version, release.apkUrl, release.apkSha256);
|
|
41
41
|
}, onDismiss: () => {
|
|
42
42
|
onDismissVersion(release.version);
|
|
43
43
|
update.dismiss();
|
package/dist/useApkInstall.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Downloads an APK then hands it to Android's installer, reporting progress
|
|
3
|
+
* from 0 to 1. `apkSha256` is the release's `apkSha256` (from
|
|
4
|
+
* `fetchLatestRelease`), to pass on as `expectedSha256`.
|
|
5
|
+
*/
|
|
6
|
+
export type DownloadAndInstallApk = (apkUrl: string, onProgress?: (fraction: number) => void, apkSha256?: string) => Promise<void>;
|
|
3
7
|
export type ApkInstallState = {
|
|
4
8
|
status: "idle";
|
|
5
9
|
} | {
|
|
@@ -10,10 +14,11 @@ export type ApkInstallState = {
|
|
|
10
14
|
status: "error";
|
|
11
15
|
version: string;
|
|
12
16
|
apkUrl: string;
|
|
17
|
+
apkSha256?: string;
|
|
13
18
|
};
|
|
14
19
|
export declare function useApkInstall(downloadAndInstallApk: DownloadAndInstallApk): {
|
|
15
20
|
state: ApkInstallState;
|
|
16
|
-
start: (version: string, apkUrl: string) => void;
|
|
21
|
+
start: (version: string, apkUrl: string, apkSha256?: string) => void;
|
|
17
22
|
retry: () => void;
|
|
18
23
|
reset: () => void;
|
|
19
24
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useApkInstall.d.ts","sourceRoot":"","sources":["../src/useApkInstall.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"useApkInstall.d.ts","sourceRoot":"","sources":["../src/useApkInstall.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,eAAe,GACvB;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAClB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAK7E,wBAAgB,aAAa,CAAC,qBAAqB,EAAE,qBAAqB;;qBAGhD,MAAM,UAAU,MAAM,cAAc,MAAM;;;EA4BnE"}
|
package/dist/useApkInstall.js
CHANGED
|
@@ -4,21 +4,22 @@ import { useState } from "react";
|
|
|
4
4
|
// state (keeping the URL) so the user can retry.
|
|
5
5
|
export function useApkInstall(downloadAndInstallApk) {
|
|
6
6
|
const [state, setState] = useState({ status: "idle" });
|
|
7
|
-
function start(version, apkUrl) {
|
|
7
|
+
function start(version, apkUrl, apkSha256) {
|
|
8
8
|
setState({ status: "downloading", version, progress: 0 });
|
|
9
9
|
downloadAndInstallApk(apkUrl, (progress) => {
|
|
10
10
|
setState({ status: "downloading", version, progress });
|
|
11
|
-
})
|
|
11
|
+
}, apkSha256)
|
|
12
12
|
.then(() => {
|
|
13
13
|
setState({ status: "idle" });
|
|
14
14
|
})
|
|
15
15
|
.catch(() => {
|
|
16
|
-
setState({ status: "error", version, apkUrl });
|
|
16
|
+
setState({ status: "error", version, apkUrl, apkSha256 });
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
function retry() {
|
|
20
|
-
if (state.status === "error")
|
|
21
|
-
start(state.version, state.apkUrl);
|
|
20
|
+
if (state.status === "error") {
|
|
21
|
+
start(state.version, state.apkUrl, state.apkSha256);
|
|
22
|
+
}
|
|
22
23
|
}
|
|
23
24
|
function reset() {
|
|
24
25
|
setState({ status: "idle" });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forthtilliath/expo-release-updates-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"./*": "./dist/*.js"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@forthtilliath/expo-release-updates": "^0.
|
|
25
|
+
"@forthtilliath/expo-release-updates": "^0.8.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": ">=19",
|