mirror of
https://gitcode.com/gh_mirrors/re/react-native-pushy.git
synced 2025-11-22 23:46:10 +08:00
Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b4c03924a | ||
|
|
d458371f54 | ||
|
|
84381e5ed7 | ||
|
|
8970fd406d | ||
|
|
34d6fef493 | ||
|
|
84b71e33a8 | ||
|
|
6cd99dece0 | ||
|
|
d726f3602b | ||
|
|
da21c99bcc | ||
|
|
1f8748375c | ||
|
|
fa731cd583 | ||
|
|
d077dcb6d3 | ||
|
|
59b60fdc6d | ||
|
|
c768705221 | ||
|
|
57206dd2f1 | ||
|
|
4e27d906c3 | ||
|
|
c24f469475 | ||
|
|
8f8a29eda8 | ||
|
|
a78542b214 | ||
|
|
8d9ae57a5f | ||
|
|
2502935fc0 | ||
|
|
8e6d9bf460 | ||
|
|
897f334343 | ||
|
|
33bc69c3fb | ||
|
|
5028ce31be |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -52,3 +52,10 @@ Example/testHotUpdate/harmony
|
|||||||
Example/testHotUpdate/android/app/.cxx
|
Example/testHotUpdate/android/app/.cxx
|
||||||
Example/harmony_use_pushy/libs
|
Example/harmony_use_pushy/libs
|
||||||
**/mcp.json
|
**/mcp.json
|
||||||
|
|
||||||
|
|
||||||
|
harmony/package
|
||||||
|
**/oh_modules
|
||||||
|
harmony/pushy/.preview
|
||||||
|
Example/harmony_use_pushy/harmony/entry/src/main/resources/rawfile/meta.json
|
||||||
|
**/.hvigor
|
||||||
|
|||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -4,9 +4,3 @@
|
|||||||
[submodule "android/jni/HDiffPatch"]
|
[submodule "android/jni/HDiffPatch"]
|
||||||
path = android/jni/HDiffPatch
|
path = android/jni/HDiffPatch
|
||||||
url = https://github.com/sisong/HDiffPatch.git
|
url = https://github.com/sisong/HDiffPatch.git
|
||||||
[submodule "harmony/src/main/cpp/HDiffPatch"]
|
|
||||||
path = harmony/src/main/cpp/HDiffPatch
|
|
||||||
url = https://github.com/sisong/HDiffPatch.git
|
|
||||||
[submodule "harmony/src/main/cpp/lzma"]
|
|
||||||
path = harmony/src/main/cpp/lzma
|
|
||||||
url = https://github.com/sisong/lzma.git
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
}
|
},
|
||||||
|
"package": "com.anonymous.expoUsePushy"
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"favicon": "./assets/favicon.png"
|
"favicon": "./assets/favicon.png"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1 @@
|
|||||||
import { registerRootComponent } from 'expo';
|
import 'expo-router/entry';
|
||||||
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
|
||||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
|
||||||
// the environment is set up appropriately
|
|
||||||
registerRootComponent(App);
|
|
||||||
|
|||||||
@@ -1,27 +1,50 @@
|
|||||||
{
|
{
|
||||||
"name": "expousepushy",
|
"name": "expousepushy",
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
|
"reset-project": "node ./scripts/reset-project.js",
|
||||||
"android": "expo run:android",
|
"android": "expo run:android",
|
||||||
"ios": "expo run:ios",
|
"ios": "expo run:ios",
|
||||||
"web": "expo start --web"
|
"web": "expo start --web",
|
||||||
|
"lint": "expo lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/metro-runtime": "~4.0.1",
|
"@expo/vector-icons": "^14.1.0",
|
||||||
"expo": "~52.0.46",
|
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||||
"expo-status-bar": "~2.0.1",
|
"@react-navigation/elements": "^2.3.8",
|
||||||
"react": "18.3.1",
|
"@react-navigation/native": "^7.1.6",
|
||||||
"react-dom": "18.3.1",
|
"expo": "~53.0.22",
|
||||||
"react-native": "0.76.9",
|
"expo-blur": "~14.1.5",
|
||||||
"react-native-update": "^10.30.3",
|
"expo-constants": "~17.1.7",
|
||||||
"react-native-web": "~0.19.13"
|
"expo-font": "~13.3.2",
|
||||||
|
"expo-haptics": "~14.1.4",
|
||||||
|
"expo-image": "~2.4.0",
|
||||||
|
"expo-linking": "~7.1.7",
|
||||||
|
"expo-router": "~5.1.5",
|
||||||
|
"expo-splash-screen": "~0.30.10",
|
||||||
|
"expo-status-bar": "~2.2.3",
|
||||||
|
"expo-symbols": "~0.4.5",
|
||||||
|
"expo-system-ui": "~5.0.11",
|
||||||
|
"expo-web-browser": "~14.2.0",
|
||||||
|
"react": "19.0.0",
|
||||||
|
"react-dom": "19.0.0",
|
||||||
|
"react-native": "0.79.6",
|
||||||
|
"react-native-gesture-handler": "~2.24.0",
|
||||||
|
"react-native-reanimated": "~3.17.4",
|
||||||
|
"react-native-safe-area-context": "5.4.0",
|
||||||
|
"react-native-screens": "~4.11.1",
|
||||||
|
"react-native-update": "^10.34.4",
|
||||||
|
"react-native-web": "~0.20.0",
|
||||||
|
"react-native-webview": "13.13.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@types/react": "~18.3.12",
|
"@types/react": "~19.0.10",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "~5.8.3",
|
||||||
|
"eslint": "^9.25.0",
|
||||||
|
"eslint-config-expo": "~9.2.0"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +1,43 @@
|
|||||||
{
|
{
|
||||||
"app": {
|
app: {
|
||||||
"signingConfigs": [],
|
signingConfigs: [],
|
||||||
"products": [
|
products: [
|
||||||
{
|
{
|
||||||
"name": "default",
|
name: 'default',
|
||||||
"signingConfig": "default",
|
signingConfig: 'default',
|
||||||
"compatibleSdkVersion": "5.0.0(12)",
|
compatibleSdkVersion: '5.0.0(12)',
|
||||||
"runtimeOS": "HarmonyOS",
|
runtimeOS: 'HarmonyOS',
|
||||||
"buildOption": {
|
buildOption: {
|
||||||
"strictMode": {
|
strictMode: {
|
||||||
"caseSensitiveCheck": true,
|
caseSensitiveCheck: true,
|
||||||
"useNormalizedOHMUrl": true
|
useNormalizedOHMUrl: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"buildModeSet": [
|
buildModeSet: [
|
||||||
{
|
{
|
||||||
"name": "debug",
|
name: 'debug',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "release"
|
name: 'release',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
"modules": [
|
modules: [
|
||||||
{
|
{
|
||||||
"name": "entry",
|
name: 'entry',
|
||||||
"srcPath": "./entry",
|
srcPath: './entry',
|
||||||
"targets": [
|
targets: [
|
||||||
{
|
{
|
||||||
"name": "default",
|
name: 'default',
|
||||||
"applyToProducts": [
|
applyToProducts: ['default'],
|
||||||
"default"
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
}
|
name: 'pushy',
|
||||||
]
|
srcPath: '../node_modules/react-native-update/harmony/pushy',
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,26 @@
|
|||||||
{
|
{
|
||||||
"meta": {
|
"meta": {
|
||||||
"stableOrder": true
|
"stableOrder": true,
|
||||||
|
"enableUnifiedLockfile": false
|
||||||
},
|
},
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
"@rnoh/react-native-openharmony@0.72.38": "@rnoh/react-native-openharmony@0.72.38",
|
"@rnoh/react-native-openharmony@0.72.38": "@rnoh/react-native-openharmony@0.72.38",
|
||||||
"pushy@../../node_modules/react-native-update/harmony": "pushy@../../node_modules/react-native-update/harmony"
|
"pushy@../../node_modules/react-native-update/harmony/pushy": "pushy@../../node_modules/react-native-update/harmony/pushy"
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@rnoh/react-native-openharmony@0.72.38": {
|
"@rnoh/react-native-openharmony@0.72.38": {
|
||||||
"name": "@rnoh/react-native-openharmony",
|
"name": "",
|
||||||
"version": "0.72.38",
|
"version": "0.72.38",
|
||||||
"integrity": "sha512-br5SIrbB0OarSLirenleE7eTOX1lNccMJ7nb/G7qWTyJ7kW4DalmTXVKYpoT2qaOLls1uEE7McD1OjbZZM9jug==",
|
"integrity": "sha512-br5SIrbB0OarSLirenleE7eTOX1lNccMJ7nb/G7qWTyJ7kW4DalmTXVKYpoT2qaOLls1uEE7McD1OjbZZM9jug==",
|
||||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@rnoh/react-native-openharmony/-/react-native-openharmony-0.72.38.har",
|
"resolved": "https://ohpm.openharmony.cn/ohpm/@rnoh/react-native-openharmony/-/react-native-openharmony-0.72.38.har",
|
||||||
"registryType": "ohpm"
|
"registryType": "ohpm"
|
||||||
},
|
},
|
||||||
"pushy@../../node_modules/react-native-update/harmony": {
|
"pushy@../../node_modules/react-native-update/harmony/pushy": {
|
||||||
"name": "pushy",
|
"name": "pushy",
|
||||||
"version": "3.1.0-0.0.7",
|
"version": "3.1.0-0.0.7",
|
||||||
"resolved": "../../node_modules/react-native-update/harmony",
|
"resolved": "",
|
||||||
"registryType": "local",
|
"registryType": "local",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rnoh/react-native-openharmony": "^0.72.38"
|
"@rnoh/react-native-openharmony": "^0.72.38"
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "entry",
|
name: 'entry',
|
||||||
"version": "1.0.0",
|
version: '1.0.0',
|
||||||
"description": "Please describe the basic information.",
|
description: 'Please describe the basic information.',
|
||||||
"main": "",
|
main: '',
|
||||||
"author": "",
|
author: '',
|
||||||
"license": "",
|
license: '',
|
||||||
"dependencies": {
|
dependencies: {
|
||||||
"@rnoh/react-native-openharmony": "0.72.38",
|
'@rnoh/react-native-openharmony': '0.72.38',
|
||||||
"pushy": "file:../../node_modules/react-native-update/harmony/pushy.har",
|
pushy: 'file:../../node_modules/react-native-update/harmony/pushy',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"pushy_build_time": "2025-04-30T02:46:33.340Z",
|
|
||||||
"versionName": "1.0.0"
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { appTasks } from '@ohos/hvigor-ohos-plugin';
|
import {appTasks} from '@ohos/hvigor-ohos-plugin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
|
system: appTasks /* Built-in plugin of Hvigor. It cannot be modified. */,
|
||||||
plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
|
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */,
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
{
|
{
|
||||||
"meta": {
|
"meta": {
|
||||||
"stableOrder": true
|
"stableOrder": true,
|
||||||
|
"enableUnifiedLockfile": false
|
||||||
},
|
},
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
|
|
||||||
"@ohos/hypium@1.0.19": "@ohos/hypium@1.0.19"
|
"@ohos/hypium@1.0.19": "@ohos/hypium@1.0.19"
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ohos/hamock@1.0.0": {
|
|
||||||
"name": "@ohos/hamock",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
|
|
||||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
|
|
||||||
"registryType": "ohpm"
|
|
||||||
},
|
|
||||||
"@ohos/hypium@1.0.19": {
|
"@ohos/hypium@1.0.19": {
|
||||||
"name": "@ohos/hypium",
|
"name": "",
|
||||||
"version": "1.0.19",
|
"version": "1.0.19",
|
||||||
"integrity": "sha512-cEjDgLFCm3cWZDeRXk7agBUkPqjWxUo6AQeiu0gEkb3J8ESqlduQLSIXeo3cCsm8U/asL7iKjF85ZyOuufAGSQ==",
|
"integrity": "sha512-cEjDgLFCm3cWZDeRXk7agBUkPqjWxUo6AQeiu0gEkb3J8ESqlduQLSIXeo3cCsm8U/asL7iKjF85ZyOuufAGSQ==",
|
||||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.19.har",
|
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.19.har",
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
{
|
{
|
||||||
"modelVersion": "5.0.0",
|
modelVersion: '5.0.0',
|
||||||
"description": "Please describe the basic information.",
|
description: 'Please describe the basic information.',
|
||||||
"dependencies": {
|
dependencies: {},
|
||||||
|
devDependencies: {
|
||||||
|
'@ohos/hypium': '1.0.19'
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
arkTs: {
|
||||||
"@ohos/hypium": "1.0.19",
|
compilerOptions: {
|
||||||
"@ohos/hamock": "1.0.0"
|
noImplicitAny: false,
|
||||||
|
suppressImplicitAnyIndexErrors: true,
|
||||||
|
strict: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"arkTs": {
|
overrides: {
|
||||||
"compilerOptions": {
|
'@rnoh/react-native-openharmony': '0.72.38',
|
||||||
"noImplicitAny": false,
|
|
||||||
"suppressImplicitAnyIndexErrors": true,
|
|
||||||
"strict": false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"overrides": {
|
|
||||||
"@rnoh/react-native-openharmony": "0.72.38"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
"react-native-safe-area-context": "^5.6.1",
|
"react-native-safe-area-context": "^5.6.1",
|
||||||
"react-native-svg": "^15.13.0",
|
"react-native-svg": "^15.13.0",
|
||||||
"react-native-update": "^10.31.2",
|
"react-native-update": "^10.34.4",
|
||||||
"react-native-vector-icons": "^10.3.0",
|
"react-native-vector-icons": "^10.3.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1430,7 +1430,7 @@
|
|||||||
|
|
||||||
"react-native-svg": ["react-native-svg@15.13.0", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/YPK+PAAXg4T0x2d2vYPvqqAhOYid2bRKxUVT7STIyd1p2JxWmsGQkfZxXCkEFN7TwLfIyVlT5RimT91Pj/qXw=="],
|
"react-native-svg": ["react-native-svg@15.13.0", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/YPK+PAAXg4T0x2d2vYPvqqAhOYid2bRKxUVT7STIyd1p2JxWmsGQkfZxXCkEFN7TwLfIyVlT5RimT91Pj/qXw=="],
|
||||||
|
|
||||||
"react-native-update": ["react-native-update@10.31.2", "", { "dependencies": { "nanoid": "^3.3.3", "react-native-url-polyfill": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-native": ">=0.59.0" } }, "sha512-doKTDyU/+6eN1jDswSh1HxnM9/XuxYFM65dLadsYVR+JvdLJ0PtbceSauthv4HYI3QXoeGaStkrRCaQAVKvp+w=="],
|
"react-native-update": ["react-native-update@10.34.4", "", { "dependencies": { "nanoid": "^3.3.3", "react-native-url-polyfill": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-native": ">=0.59.0" } }, "sha512-yuXlff7EMUDyp1js2NylOw9jT0sVXoc5rpaRhzoYYcwfQTQq1Qp53qpyupDuUj43MEv5ikfJ6xBd/iRpXuanNg=="],
|
||||||
|
|
||||||
"react-native-url-polyfill": ["react-native-url-polyfill@2.0.0", "", { "dependencies": { "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "react-native": "*" } }, "sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA=="],
|
"react-native-url-polyfill": ["react-native-url-polyfill@2.0.0", "", { "dependencies": { "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "react-native": "*" } }, "sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA=="],
|
||||||
|
|
||||||
|
|||||||
@@ -403,6 +403,8 @@
|
|||||||
"-DFOLLY_NO_CONFIG",
|
"-DFOLLY_NO_CONFIG",
|
||||||
"-DFOLLY_MOBILE=1",
|
"-DFOLLY_MOBILE=1",
|
||||||
"-DFOLLY_USE_LIBCPP=1",
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = "$(inherited)";
|
OTHER_LDFLAGS = "$(inherited)";
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
@@ -475,6 +477,8 @@
|
|||||||
"-DFOLLY_NO_CONFIG",
|
"-DFOLLY_NO_CONFIG",
|
||||||
"-DFOLLY_MOBILE=1",
|
"-DFOLLY_MOBILE=1",
|
||||||
"-DFOLLY_USE_LIBCPP=1",
|
"-DFOLLY_USE_LIBCPP=1",
|
||||||
|
"-DFOLLY_CFG_NO_COROUTINES=1",
|
||||||
|
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = "$(inherited)";
|
OTHER_LDFLAGS = "$(inherited)";
|
||||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||||
|
|||||||
@@ -1835,7 +1835,7 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- SocketRocket
|
- SocketRocket
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-update (10.31.2):
|
- react-native-update (10.34.4):
|
||||||
- boost
|
- boost
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- fast_float
|
- fast_float
|
||||||
@@ -1854,7 +1854,7 @@ PODS:
|
|||||||
- React-graphics
|
- React-graphics
|
||||||
- React-ImageManager
|
- React-ImageManager
|
||||||
- React-jsi
|
- React-jsi
|
||||||
- react-native-update/RCTPushy (= 10.31.2)
|
- react-native-update/RCTPushy (= 10.34.4)
|
||||||
- React-NativeModulesApple
|
- React-NativeModulesApple
|
||||||
- React-RCTFabric
|
- React-RCTFabric
|
||||||
- React-renderercss
|
- React-renderercss
|
||||||
@@ -1866,7 +1866,7 @@ PODS:
|
|||||||
- SocketRocket
|
- SocketRocket
|
||||||
- SSZipArchive
|
- SSZipArchive
|
||||||
- Yoga
|
- Yoga
|
||||||
- react-native-update/RCTPushy (10.31.2):
|
- react-native-update/RCTPushy (10.34.4):
|
||||||
- boost
|
- boost
|
||||||
- DoubleConversion
|
- DoubleConversion
|
||||||
- fast_float
|
- fast_float
|
||||||
@@ -2800,7 +2800,7 @@ SPEC CHECKSUMS:
|
|||||||
React-Mapbuffer: 9d2434a42701d6144ca18f0ca1c4507808ca7696
|
React-Mapbuffer: 9d2434a42701d6144ca18f0ca1c4507808ca7696
|
||||||
React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b
|
React-microtasksnativemodule: 75b6604b667d297292345302cc5bfb6b6aeccc1b
|
||||||
react-native-safe-area-context: c6e2edd1c1da07bdce287fa9d9e60c5f7b514616
|
react-native-safe-area-context: c6e2edd1c1da07bdce287fa9d9e60c5f7b514616
|
||||||
react-native-update: 7a05a78c6da651c1961b8407859f44bd0aa9b03a
|
react-native-update: 822780a6d3c8482d47ba50b5801ed295c0dfcaff
|
||||||
React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3
|
React-NativeModulesApple: 879fbdc5dcff7136abceb7880fe8a2022a1bd7c3
|
||||||
React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d
|
React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d
|
||||||
React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510
|
React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510
|
||||||
|
|||||||
@@ -10,8 +10,7 @@
|
|||||||
"test:e2e": "detox test --configuration android.emu.debug",
|
"test:e2e": "detox test --configuration android.emu.debug",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"postinstall": "patch-package",
|
"postinstall": "patch-package",
|
||||||
"apk": "cd android && ./gradlew assembleRelease",
|
"apk": "cd android && ./gradlew assembleRelease"
|
||||||
"dev:harmony": "react-native bundle-harmony --dev"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"form-data": "^4.0.4",
|
"form-data": "^4.0.4",
|
||||||
@@ -22,7 +21,7 @@
|
|||||||
"react-native-paper": "^5.14.5",
|
"react-native-paper": "^5.14.5",
|
||||||
"react-native-safe-area-context": "^5.6.1",
|
"react-native-safe-area-context": "^5.6.1",
|
||||||
"react-native-svg": "^15.13.0",
|
"react-native-svg": "^15.13.0",
|
||||||
"react-native-update": "^10.31.2",
|
"react-native-update": "^10.34.4",
|
||||||
"react-native-vector-icons": "^10.3.0"
|
"react-native-vector-icons": "^10.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import okio.BufferedSink;
|
import okio.BufferedSink;
|
||||||
@@ -198,6 +199,10 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
|
|||||||
return fout.toByteArray();
|
return fout.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getCRC32AsDecimal(long crc32Value) {
|
||||||
|
return String.valueOf(crc32Value & 0xFFFFFFFFL);
|
||||||
|
}
|
||||||
|
|
||||||
private void copyFilesWithBlacklist(String current, File from, File to, JSONObject blackList) throws IOException {
|
private void copyFilesWithBlacklist(String current, File from, File to, JSONObject blackList) throws IOException {
|
||||||
File[] files = from.listFiles();
|
File[] files = from.listFiles();
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
@@ -273,12 +278,41 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
|
|||||||
zipFile.close();
|
zipFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void copyFromResourceV2(HashMap<String, ArrayList<File>> resToCopy2) throws IOException {
|
||||||
|
SafeZipFile zipFile = new SafeZipFile(new File(context.getPackageResourcePath()));
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
ZipEntry ze = entries.nextElement();
|
||||||
|
String fn = ze.getName();
|
||||||
|
long zipCrc32 = ze.getCrc();
|
||||||
|
String crc32Decimal = getCRC32AsDecimal(zipCrc32);
|
||||||
|
ArrayList<File> targets = resToCopy2.get(crc32Decimal);
|
||||||
|
if (targets != null) {
|
||||||
|
File lastTarget = null;
|
||||||
|
for (File target: targets) {
|
||||||
|
if (UpdateContext.DEBUG) {
|
||||||
|
Log.d("react-native-update", "Copying from resource " + fn + " to " + target);
|
||||||
|
}
|
||||||
|
if (lastTarget != null) {
|
||||||
|
copyFile(lastTarget, target);
|
||||||
|
} else {
|
||||||
|
zipFile.unzipToFile(ze, target);
|
||||||
|
lastTarget = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zipFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONException {
|
private void doPatchFromApk(DownloadTaskParams param) throws IOException, JSONException {
|
||||||
downloadFile(param);
|
downloadFile(param);
|
||||||
|
|
||||||
removeDirectory(param.unzipDirectory);
|
removeDirectory(param.unzipDirectory);
|
||||||
param.unzipDirectory.mkdirs();
|
param.unzipDirectory.mkdirs();
|
||||||
HashMap<String, ArrayList<File>> copyList = new HashMap<String, ArrayList<File>>();
|
HashMap<String, ArrayList<File>> copyList = new HashMap<String, ArrayList<File>>();
|
||||||
|
HashMap<String, ArrayList<File>> copiesv2List = new HashMap<String, ArrayList<File>>();
|
||||||
|
Boolean isV2 = false;
|
||||||
|
|
||||||
boolean foundDiff = false;
|
boolean foundDiff = false;
|
||||||
boolean foundBundlePatch = false;
|
boolean foundBundlePatch = false;
|
||||||
@@ -297,29 +331,58 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
|
|||||||
JSONObject obj = (JSONObject)new JSONTokener(json).nextValue();
|
JSONObject obj = (JSONObject)new JSONTokener(json).nextValue();
|
||||||
|
|
||||||
JSONObject copies = obj.getJSONObject("copies");
|
JSONObject copies = obj.getJSONObject("copies");
|
||||||
|
JSONObject copiesv2 = obj.getJSONObject("copiesv2");
|
||||||
Iterator<?> keys = copies.keys();
|
Iterator<?> keys = copies.keys();
|
||||||
while( keys.hasNext() ) {
|
Iterator<?> keysV2 = copiesv2.keys();
|
||||||
String to = (String)keys.next();
|
if(keysV2.hasNext()){
|
||||||
String from = copies.getString(to);
|
isV2 = true;
|
||||||
if (from.isEmpty()) {
|
while( keysV2.hasNext() ) {
|
||||||
from = to;
|
String from = (String)keysV2.next();
|
||||||
}
|
String to = copiesv2.getString(from);
|
||||||
ArrayList<File> target = null;
|
if (from.isEmpty()) {
|
||||||
if (!copyList.containsKey(from)) {
|
from = to;
|
||||||
target = new ArrayList<File>();
|
}
|
||||||
copyList.put(from, target);
|
ArrayList<File> target = null;
|
||||||
} else {
|
if (!copiesv2List.containsKey(from)) {
|
||||||
target = copyList.get((from));
|
target = new ArrayList<File>();
|
||||||
}
|
copiesv2List.put(from, target);
|
||||||
File toFile = new File(param.unzipDirectory, to);
|
} else {
|
||||||
|
target = copiesv2List.get((from));
|
||||||
|
}
|
||||||
|
File toFile = new File(param.unzipDirectory, to);
|
||||||
|
|
||||||
// Fixing a Zip Path Traversal Vulnerability
|
// Fixing a Zip Path Traversal Vulnerability
|
||||||
// https://support.google.com/faqs/answer/9294009
|
// https://support.google.com/faqs/answer/9294009
|
||||||
String canonicalPath = toFile.getCanonicalPath();
|
String canonicalPath = toFile.getCanonicalPath();
|
||||||
if (!canonicalPath.startsWith(param.unzipDirectory.getCanonicalPath() + File.separator)) {
|
if (!canonicalPath.startsWith(param.unzipDirectory.getCanonicalPath() + File.separator)) {
|
||||||
throw new SecurityException("Illegal name: " + to);
|
throw new SecurityException("Illegal name: " + to);
|
||||||
|
}
|
||||||
|
target.add(toFile);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
while( keys.hasNext() ) {
|
||||||
|
String to = (String)keys.next();
|
||||||
|
String from = copies.getString(to);
|
||||||
|
if (from.isEmpty()) {
|
||||||
|
from = to;
|
||||||
|
}
|
||||||
|
ArrayList<File> target = null;
|
||||||
|
if (!copyList.containsKey(from)) {
|
||||||
|
target = new ArrayList<File>();
|
||||||
|
copyList.put(from, target);
|
||||||
|
} else {
|
||||||
|
target = copyList.get((from));
|
||||||
|
}
|
||||||
|
File toFile = new File(param.unzipDirectory, to);
|
||||||
|
|
||||||
|
// Fixing a Zip Path Traversal Vulnerability
|
||||||
|
// https://support.google.com/faqs/answer/9294009
|
||||||
|
String canonicalPath = toFile.getCanonicalPath();
|
||||||
|
if (!canonicalPath.startsWith(param.unzipDirectory.getCanonicalPath() + File.separator)) {
|
||||||
|
throw new SecurityException("Illegal name: " + to);
|
||||||
|
}
|
||||||
|
target.add(toFile);
|
||||||
}
|
}
|
||||||
target.add(toFile);
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -348,7 +411,11 @@ class DownloadTask extends AsyncTask<DownloadTaskParams, long[], Void> {
|
|||||||
throw new Error("bundle patch not found");
|
throw new Error("bundle patch not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
copyFromResource(copyList);
|
if(isV2){
|
||||||
|
copyFromResourceV2(copiesv2List);
|
||||||
|
}else{
|
||||||
|
copyFromResource(copyList);
|
||||||
|
}
|
||||||
|
|
||||||
if (UpdateContext.DEBUG) {
|
if (UpdateContext.DEBUG) {
|
||||||
Log.d("react-native-update", "Unzip finished");
|
Log.d("react-native-update", "Unzip finished");
|
||||||
|
|||||||
Binary file not shown.
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"meta": {
|
"meta": {
|
||||||
"stableOrder": true
|
"stableOrder": true,
|
||||||
|
"enableUnifiedLockfile": false
|
||||||
},
|
},
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@rnoh/react-native-openharmony@0.72.38": {
|
"@rnoh/react-native-openharmony@0.72.38": {
|
||||||
"name": "@rnoh/react-native-openharmony",
|
"name": "",
|
||||||
"version": "0.72.38",
|
"version": "0.72.38",
|
||||||
"integrity": "sha512-br5SIrbB0OarSLirenleE7eTOX1lNccMJ7nb/G7qWTyJ7kW4DalmTXVKYpoT2qaOLls1uEE7McD1OjbZZM9jug==",
|
"integrity": "sha512-br5SIrbB0OarSLirenleE7eTOX1lNccMJ7nb/G7qWTyJ7kW4DalmTXVKYpoT2qaOLls1uEE7McD1OjbZZM9jug==",
|
||||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@rnoh/react-native-openharmony/-/react-native-openharmony-0.72.38.har",
|
"resolved": "https://ohpm.openharmony.cn/ohpm/@rnoh/react-native-openharmony/-/react-native-openharmony-0.72.38.har",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"license": "ISC",
|
"license": "MIT",
|
||||||
"types": "",
|
"types": "",
|
||||||
"devDependencies": {},
|
"devDependencies": {},
|
||||||
"name": "pushy",
|
"name": "pushy",
|
||||||
@@ -8,5 +8,6 @@
|
|||||||
"version": "3.1.0-0.0.7",
|
"version": "3.1.0-0.0.7",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rnoh/react-native-openharmony":"^0.72.38"
|
"@rnoh/react-native-openharmony":"^0.72.38"
|
||||||
}
|
},
|
||||||
|
"modelVersion": "5.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
project(rnupdate)
|
project(rnupdate)
|
||||||
|
|
||||||
set(HDIFFPATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}/HDiffPatch)
|
# Point to android/jni directory for shared source code
|
||||||
set(LZMA_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lzma)
|
set(ANDROID_JNI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../../node_modules/react-native-update/android/jni)
|
||||||
|
set(HDIFFPATCH_DIR ${ANDROID_JNI_DIR}/HDiffPatch)
|
||||||
|
set(LZMA_DIR ${ANDROID_JNI_DIR}/lzma)
|
||||||
set(HDP_SOURCES
|
set(HDP_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/pushy.c
|
${CMAKE_CURRENT_SOURCE_DIR}/pushy.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/hpatch.c
|
${ANDROID_JNI_DIR}/hpatch.c
|
||||||
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch/patch.c
|
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch/patch.c
|
||||||
${HDIFFPATCH_DIR}/file_for_patch.c
|
${HDIFFPATCH_DIR}/file_for_patch.c
|
||||||
${LZMA_DIR}/C/LzmaDec.c
|
${LZMA_DIR}/C/LzmaDec.c
|
||||||
@@ -20,6 +22,7 @@ add_library(rnupdate SHARED
|
|||||||
|
|
||||||
target_include_directories(rnupdate PRIVATE
|
target_include_directories(rnupdate PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${ANDROID_JNI_DIR}
|
||||||
${HDIFFPATCH_DIR}
|
${HDIFFPATCH_DIR}
|
||||||
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch
|
${HDIFFPATCH_DIR}/libHDiffPatch/HPatch
|
||||||
${LZMA_DIR}/C
|
${LZMA_DIR}/C
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
// hpatch.c
|
|
||||||
// Copyright 2021 housisong, All rights reserved
|
|
||||||
#include "hpatch.h"
|
|
||||||
#include "HDiffPatch/libHDiffPatch/HPatch/patch.h"
|
|
||||||
#include "HDiffPatch/file_for_patch.h"
|
|
||||||
|
|
||||||
//#define _CompressPlugin_zlib
|
|
||||||
//#define _CompressPlugin_bz2
|
|
||||||
#define _CompressPlugin_lzma
|
|
||||||
#define _CompressPlugin_lzma2
|
|
||||||
#define _IsNeedIncludeDefaultCompressHead 0
|
|
||||||
#include "lzma/C/LzmaDec.h"
|
|
||||||
#include "lzma/C/Lzma2Dec.h"
|
|
||||||
#include "HDiffPatch/decompress_plugin_demo.h"
|
|
||||||
|
|
||||||
#define kMaxLoadMemOldSize ((1<<20)*8)
|
|
||||||
|
|
||||||
#define _check(v,errorType) do{ \
|
|
||||||
if (!(v)){ if (result==kHPatch_ok) result=errorType; if (!_isInClear){ goto _clear; }; } }while(0)
|
|
||||||
|
|
||||||
int hpatch_getInfo_by_mem(hpatch_singleCompressedDiffInfo* out_patinfo,
|
|
||||||
const uint8_t* pat,size_t patsize){
|
|
||||||
hpatch_TStreamInput patStream;
|
|
||||||
mem_as_hStreamInput(&patStream,pat,pat+patsize);
|
|
||||||
if (!getSingleCompressedDiffInfo(out_patinfo,&patStream,0))
|
|
||||||
return kHPatch_error_info;//data error;
|
|
||||||
return kHPatch_ok; //ok
|
|
||||||
}
|
|
||||||
|
|
||||||
static hpatch_TDecompress* getDecompressPlugin(const char* compressType){
|
|
||||||
#ifdef _CompressPlugin_zlib
|
|
||||||
if (zlibDecompressPlugin.is_can_open(compressType))
|
|
||||||
return &zlibDecompressPlugin;
|
|
||||||
#endif
|
|
||||||
#ifdef _CompressPlugin_bz2
|
|
||||||
if (bz2DecompressPlugin.is_can_open(compressType))
|
|
||||||
return &bz2DecompressPlugin;
|
|
||||||
#endif
|
|
||||||
#ifdef _CompressPlugin_lzma
|
|
||||||
if (lzmaDecompressPlugin.is_can_open(compressType))
|
|
||||||
return &lzmaDecompressPlugin;
|
|
||||||
#endif
|
|
||||||
#ifdef _CompressPlugin_lzma2
|
|
||||||
if (lzma2DecompressPlugin.is_can_open(compressType))
|
|
||||||
return &lzma2DecompressPlugin;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int hpatch_by_stream(const hpatch_TStreamInput* old,hpatch_BOOL isLoadOldAllToMem,const hpatch_TStreamInput* pat,
|
|
||||||
hpatch_TStreamOutput* out_new,const hpatch_singleCompressedDiffInfo* patInfo){
|
|
||||||
int result=kHPatch_ok;
|
|
||||||
int _isInClear=hpatch_FALSE;
|
|
||||||
hpatch_TDecompress* decompressPlugin=0;
|
|
||||||
uint8_t* temp_cache=0;
|
|
||||||
size_t temp_cache_size;
|
|
||||||
hpatch_singleCompressedDiffInfo _patinfo;
|
|
||||||
hpatch_TStreamInput _old;
|
|
||||||
{// info
|
|
||||||
if (!patInfo){
|
|
||||||
_check(getSingleCompressedDiffInfo(&_patinfo,pat,0),kHPatch_error_info);
|
|
||||||
patInfo=&_patinfo;
|
|
||||||
}
|
|
||||||
_check(old->streamSize==patInfo->oldDataSize,kHPatch_error_old_size);
|
|
||||||
_check(out_new->streamSize>=patInfo->newDataSize,kHPatch_error_new_size);
|
|
||||||
out_new->streamSize=patInfo->newDataSize;
|
|
||||||
if (strlen(patInfo->compressType)>0){
|
|
||||||
decompressPlugin=getDecompressPlugin(patInfo->compressType);
|
|
||||||
_check(decompressPlugin,kHPatch_error_compressType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{// mem
|
|
||||||
size_t mem_size;
|
|
||||||
size_t oldSize=(size_t)old->streamSize;
|
|
||||||
isLoadOldAllToMem=isLoadOldAllToMem&&(old->streamSize<=kMaxLoadMemOldSize);
|
|
||||||
temp_cache_size=patInfo->stepMemSize+hpatch_kFileIOBufBetterSize*3;
|
|
||||||
mem_size=temp_cache_size+(isLoadOldAllToMem?oldSize:0);
|
|
||||||
temp_cache=malloc(mem_size);
|
|
||||||
_check(temp_cache,kHPatch_error_malloc);
|
|
||||||
if (isLoadOldAllToMem){//load old to mem
|
|
||||||
uint8_t* oldMem=temp_cache+temp_cache_size;
|
|
||||||
_check(old->read(old,0,oldMem,oldMem+oldSize),kHPatch_error_old_fread);
|
|
||||||
mem_as_hStreamInput(&_old,oldMem,oldMem+oldSize);
|
|
||||||
old=&_old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_check(patch_single_compressed_diff(out_new,old,pat,patInfo->diffDataPos,
|
|
||||||
patInfo->uncompressedSize,decompressPlugin,patInfo->coverCount,
|
|
||||||
patInfo->stepMemSize,temp_cache,temp_cache+temp_cache_size),kHPatch_error_patch);
|
|
||||||
|
|
||||||
_clear:
|
|
||||||
_isInClear=hpatch_TRUE;
|
|
||||||
if (temp_cache){ free(temp_cache); temp_cache=0; }
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hpatch_by_mem(const uint8_t* old,size_t oldsize,uint8_t* newBuf,size_t newsize,
|
|
||||||
const uint8_t* pat,size_t patsize,const hpatch_singleCompressedDiffInfo* patInfo){
|
|
||||||
hpatch_TStreamInput oldStream;
|
|
||||||
hpatch_TStreamInput patStream;
|
|
||||||
hpatch_TStreamOutput newStream;
|
|
||||||
mem_as_hStreamInput(&oldStream,old,old+oldsize);
|
|
||||||
mem_as_hStreamInput(&patStream,pat,pat+patsize);
|
|
||||||
mem_as_hStreamOutput(&newStream,newBuf,newBuf+newsize);
|
|
||||||
return hpatch_by_stream(&oldStream,hpatch_FALSE,&patStream,&newStream,patInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
int hpatch_by_file(const char* oldfile, const char* newfile, const char* patchfile){
|
|
||||||
int result=kHPatch_ok;
|
|
||||||
int _isInClear=hpatch_FALSE;
|
|
||||||
int patch_result;
|
|
||||||
hpatch_TFileStreamInput oldStream;
|
|
||||||
hpatch_TFileStreamInput patStream;
|
|
||||||
hpatch_TFileStreamOutput newStream;
|
|
||||||
hpatch_TFileStreamInput_init(&oldStream);
|
|
||||||
hpatch_TFileStreamInput_init(&patStream);
|
|
||||||
hpatch_TFileStreamOutput_init(&newStream);
|
|
||||||
|
|
||||||
_check(hpatch_TFileStreamInput_open(&oldStream,oldfile),kHPatch_error_old_fopen);
|
|
||||||
_check(hpatch_TFileStreamInput_open(&patStream,patchfile),kHPatch_error_pat_fopen);
|
|
||||||
_check(hpatch_TFileStreamOutput_open(&newStream,newfile,~(hpatch_StreamPos_t)0),kHPatch_error_new_fopen);
|
|
||||||
|
|
||||||
patch_result=hpatch_by_stream(&oldStream.base,hpatch_TRUE,&patStream.base,&newStream.base,0);
|
|
||||||
if (patch_result!=kHPatch_ok){
|
|
||||||
_check(!oldStream.fileError,kHPatch_error_old_fread);
|
|
||||||
_check(!patStream.fileError,kHPatch_error_pat_fread);
|
|
||||||
_check(!newStream.fileError,kHPatch_error_new_fwrite);
|
|
||||||
_check(hpatch_FALSE,patch_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
_clear:
|
|
||||||
_isInClear=hpatch_TRUE;
|
|
||||||
_check(hpatch_TFileStreamInput_close(&oldStream),kHPatch_error_old_fclose);
|
|
||||||
_check(hpatch_TFileStreamInput_close(&patStream),kHPatch_error_pat_fclose);
|
|
||||||
_check(hpatch_TFileStreamOutput_close(&newStream),kHPatch_error_new_fclose);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// hpatch.h
|
|
||||||
// import HDiffPatch, support patchData created by "hdiffz -SD -c-lzma2 oldfile newfile patchfile"
|
|
||||||
// Copyright 2021 housisong, All rights reserved
|
|
||||||
|
|
||||||
#ifndef HDIFFPATCH_PATCH_H
|
|
||||||
#define HDIFFPATCH_PATCH_H
|
|
||||||
# include <stdint.h> //for uint8_t
|
|
||||||
#include "HDiffPatch/libHDiffPatch/HPatch/patch_types.h" //for hpatch_singleCompressedDiffInfo
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//result
|
|
||||||
enum {
|
|
||||||
kHPatch_ok = 0,
|
|
||||||
kHPatch_error_malloc =-1,
|
|
||||||
kHPatch_error_info =-2,
|
|
||||||
kHPatch_error_compressType =-3,
|
|
||||||
kHPatch_error_patch =-4,
|
|
||||||
kHPatch_error_old_fopen =-5,
|
|
||||||
kHPatch_error_old_fread =-6,
|
|
||||||
kHPatch_error_old_fclose =-7,
|
|
||||||
kHPatch_error_pat_fopen =-8,
|
|
||||||
kHPatch_error_pat_fread =-9,
|
|
||||||
kHPatch_error_pat_fclose =-10,
|
|
||||||
kHPatch_error_new_fopen =-11,
|
|
||||||
kHPatch_error_new_fwrite =-12,
|
|
||||||
kHPatch_error_new_fclose =-13,
|
|
||||||
kHPatch_error_old_size =-14,
|
|
||||||
kHPatch_error_new_size =-15,
|
|
||||||
};
|
|
||||||
|
|
||||||
int hpatch_getInfo_by_mem(hpatch_singleCompressedDiffInfo* out_patinfo,
|
|
||||||
const uint8_t* pat,size_t patsize);
|
|
||||||
|
|
||||||
//patInfo can NULL
|
|
||||||
int hpatch_by_mem(const uint8_t* old,size_t oldsize, uint8_t* newBuf,size_t newsize,
|
|
||||||
const uint8_t* pat,size_t patsize,const hpatch_singleCompressedDiffInfo* patInfo);
|
|
||||||
int hpatch_by_file(const char* oldfile, const char* newfile, const char* patchfile);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif //HDIFFPATCH_PATCH_H
|
|
||||||
@@ -60,13 +60,13 @@ export class DownloadTask {
|
|||||||
const exists = fileIo.accessSync(params.targetFile);
|
const exists = fileIo.accessSync(params.targetFile);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
await fileIo.unlink(params.targetFile);
|
await fileIo.unlink(params.targetFile);
|
||||||
}else{
|
} else {
|
||||||
const targetDir = params.targetFile.substring(
|
const targetDir = params.targetFile.substring(
|
||||||
0,
|
0,
|
||||||
params.targetFile.lastIndexOf('/'),
|
params.targetFile.lastIndexOf('/'),
|
||||||
);
|
);
|
||||||
const exists = fileIo.accessSync(targetDir);
|
const exists = fileIo.accessSync(targetDir);
|
||||||
if(!exists){
|
if (!exists) {
|
||||||
await fileIo.mkdir(targetDir);
|
await fileIo.mkdir(targetDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ export class DownloadTask {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (response.responseCode > 299) {
|
if (response.responseCode > 299) {
|
||||||
throw new Error(`Server error: ${response.responseCode}`);
|
throw Error(`Server error: ${response.responseCode}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentLength = parseInt(response.header['content-length'] || '0');
|
const contentLength = parseInt(response.header['content-length'] || '0');
|
||||||
@@ -108,9 +108,10 @@ export class DownloadTask {
|
|||||||
const stats = await fileIo.stat(params.targetFile);
|
const stats = await fileIo.stat(params.targetFile);
|
||||||
const fileSize = stats.size;
|
const fileSize = stats.size;
|
||||||
if (fileSize !== contentLength) {
|
if (fileSize !== contentLength) {
|
||||||
throw new Error(`Download incomplete: expected ${contentLength} bytes but got ${stats.size} bytes`);
|
throw Error(
|
||||||
|
`Download incomplete: expected ${contentLength} bytes but got ${stats.size} bytes`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Download failed:', error);
|
console.error('Download failed:', error);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -142,7 +143,7 @@ export class DownloadTask {
|
|||||||
bytesRead = await fileIo
|
bytesRead = await fileIo
|
||||||
.read(reader.fd, arrayBuffer)
|
.read(reader.fd, arrayBuffer)
|
||||||
.catch((err: BusinessError) => {
|
.catch((err: BusinessError) => {
|
||||||
throw new Error(
|
throw Error(
|
||||||
`Error reading file: ${err.message}, code: ${err.code}`,
|
`Error reading file: ${err.message}, code: ${err.code}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -154,7 +155,7 @@ export class DownloadTask {
|
|||||||
length: bytesRead,
|
length: bytesRead,
|
||||||
})
|
})
|
||||||
.catch((err: BusinessError) => {
|
.catch((err: BusinessError) => {
|
||||||
throw new Error(
|
throw Error(
|
||||||
`Error writing file: ${err.message}, code: ${err.code}`,
|
`Error writing file: ${err.message}, code: ${err.code}`,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -295,16 +296,16 @@ export class DownloadTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fn !== '.DS_Store'){
|
if (fn !== '.DS_Store') {
|
||||||
await zip.decompressFile(fn, params.unzipDirectory);
|
await zip.decompressFile(fn, params.unzipDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundDiff) {
|
if (!foundDiff) {
|
||||||
throw new Error('diff.json not found');
|
throw Error('diff.json not found');
|
||||||
}
|
}
|
||||||
if (!foundBundlePatch) {
|
if (!foundBundlePatch) {
|
||||||
throw new Error('bundle patch not found');
|
throw Error('bundle patch not found');
|
||||||
}
|
}
|
||||||
await this.copyFromResource(copyList);
|
await this.copyFromResource(copyList);
|
||||||
}
|
}
|
||||||
@@ -366,12 +367,18 @@ export class DownloadTask {
|
|||||||
new Uint8Array(entry.content),
|
new Uint8Array(entry.content),
|
||||||
);
|
);
|
||||||
const outputFile = `${params.unzipDirectory}/bundle.harmony.js`;
|
const outputFile = `${params.unzipDirectory}/bundle.harmony.js`;
|
||||||
const writer = await fileIo.open(outputFile, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
|
const writer = await fileIo.open(
|
||||||
|
outputFile,
|
||||||
|
fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY,
|
||||||
|
);
|
||||||
const chunkSize = 4096;
|
const chunkSize = 4096;
|
||||||
let bytesWritten = 0;
|
let bytesWritten = 0;
|
||||||
const totalLength = patched.byteLength;
|
const totalLength = patched.byteLength;
|
||||||
while (bytesWritten < totalLength) {
|
while (bytesWritten < totalLength) {
|
||||||
const chunk = patched.slice(bytesWritten, bytesWritten + chunkSize);
|
const chunk = patched.slice(
|
||||||
|
bytesWritten,
|
||||||
|
bytesWritten + chunkSize,
|
||||||
|
);
|
||||||
await fileIo.write(writer.fd, chunk);
|
await fileIo.write(writer.fd, chunk);
|
||||||
bytesWritten += chunk.byteLength;
|
bytesWritten += chunk.byteLength;
|
||||||
}
|
}
|
||||||
@@ -387,10 +394,10 @@ export class DownloadTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!foundDiff) {
|
if (!foundDiff) {
|
||||||
throw new Error('diff.json not found');
|
throw Error('diff.json not found');
|
||||||
}
|
}
|
||||||
if (!foundBundlePatch) {
|
if (!foundBundlePatch) {
|
||||||
throw new Error('bundle patch not found');
|
throw Error('bundle patch not found');
|
||||||
}
|
}
|
||||||
console.info('Patch from PPK completed');
|
console.info('Patch from PPK completed');
|
||||||
}
|
}
|
||||||
@@ -478,7 +485,7 @@ export class DownloadTask {
|
|||||||
await this.downloadFile(params);
|
await this.downloadFile(params);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown task type: ${params.type}`);
|
throw Error(`Unknown task type: ${params.type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
params.listener?.onDownloadCompleted(params);
|
params.listener?.onDownloadCompleted(params);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export class PushyFileJSBundleProvider extends JSBundleProvider {
|
|||||||
this.updateContext = new UpdateContext(context);
|
this.updateContext = new UpdateContext(context);
|
||||||
}
|
}
|
||||||
getURL(): string {
|
getURL(): string {
|
||||||
return this.updateContext.getBundleUrl().substring(1);
|
return this.updateContext.getBundleUrl()?.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBundle(): Promise<ArrayBuffer> {
|
async getBundle(): Promise<ArrayBuffer> {
|
||||||
|
|||||||
@@ -9,47 +9,47 @@ import { UpdateModuleImpl } from './UpdateModuleImpl';
|
|||||||
import { UpdateContext } from './UpdateContext';
|
import { UpdateContext } from './UpdateContext';
|
||||||
import { EventHub } from './EventHub';
|
import { EventHub } from './EventHub';
|
||||||
|
|
||||||
const TAG = "PushyTurboModule"
|
const TAG = 'PushyTurboModule';
|
||||||
|
|
||||||
export class PushyTurboModule extends TurboModule {
|
export class PushyTurboModule extends TurboModule {
|
||||||
mUiCtx: common.UIAbilityContext
|
mUiCtx: common.UIAbilityContext;
|
||||||
context: UpdateContext
|
context: UpdateContext;
|
||||||
|
|
||||||
constructor(protected ctx: TurboModuleContext) {
|
constructor(protected ctx: TurboModuleContext) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
logger.debug(TAG, ",PushyTurboModule constructor");
|
logger.debug(TAG, ',PushyTurboModule constructor');
|
||||||
this.mUiCtx = ctx.uiAbilityContext
|
this.mUiCtx = ctx.uiAbilityContext;
|
||||||
this.context = new UpdateContext(this.mUiCtx)
|
this.context = new UpdateContext(this.mUiCtx);
|
||||||
EventHub.getInstance().setRNInstance(ctx.rnInstance)
|
EventHub.getInstance().setRNInstance(ctx.rnInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getConstants(): Object {
|
getConstants(): Object {
|
||||||
logger.debug(TAG, ",call getConstants");
|
logger.debug(TAG, ',call getConstants');
|
||||||
const context = this.mUiCtx;
|
const context = this.mUiCtx;
|
||||||
const preferencesManager = dataPreferences.getPreferencesSync(context,{ name: 'update' });
|
const preferencesManager = dataPreferences.getPreferencesSync(context,{ name: 'update' });
|
||||||
const isFirstTime = preferencesManager.getSync("isFirstTime", false) as boolean;
|
const isFirstTime = preferencesManager.getSync('isFirstTime', false) as boolean;
|
||||||
const rolledBackVersion = preferencesManager.getSync("rolledBackVersion", "") as string;
|
const rolledBackVersion = preferencesManager.getSync('rolledBackVersion', '') as string;
|
||||||
const uuid = preferencesManager.getSync("uuid", "") as string;
|
const uuid = preferencesManager.getSync('uuid', '') as string;
|
||||||
const currentVersion = preferencesManager.getSync("currentVersion", "") as string;
|
const currentVersion = preferencesManager.getSync('currentVersion', '') as string;
|
||||||
const currentVersionInfo = this.context.getKv(`hash_${currentVersion}`);
|
const currentVersionInfo = this.context.getKv(`hash_${currentVersion}`);
|
||||||
const buildTime = preferencesManager.getSync("buildTime", "") as string;
|
const buildTime = preferencesManager.getSync('buildTime', '') as string;
|
||||||
const isUsingBundleUrl = this.context.getIsUsingBundleUrl();
|
const isUsingBundleUrl = this.context.getIsUsingBundleUrl();
|
||||||
let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
|
let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
|
||||||
let packageVersion = '';
|
let packageVersion = '';
|
||||||
try {
|
try {
|
||||||
const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleFlags);
|
const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleFlags);
|
||||||
packageVersion = bundleInfo?.versionName || "Unknown"
|
packageVersion = bundleInfo?.versionName || 'Unknown';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to get bundle info:", error);
|
console.error('Failed to get bundle info:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFirstTime) {
|
if (isFirstTime) {
|
||||||
preferencesManager.deleteSync("isFirstTime");
|
preferencesManager.deleteSync('isFirstTime');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rolledBackVersion) {
|
if (rolledBackVersion) {
|
||||||
preferencesManager.deleteSync("rolledBackVersion");
|
preferencesManager.deleteSync('rolledBackVersion');
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -62,12 +62,12 @@ getConstants(): Object {
|
|||||||
isFirstTime,
|
isFirstTime,
|
||||||
rolledBackVersion,
|
rolledBackVersion,
|
||||||
uuid,
|
uuid,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setLocalHashInfo(hash: string, info: string): boolean {
|
setLocalHashInfo(hash: string, info: string): boolean {
|
||||||
logger.debug(TAG, ",call setLocalHashInfo");
|
logger.debug(TAG, ',call setLocalHashInfo');
|
||||||
return UpdateModuleImpl.setLocalHashInfo(this.context, hash, info);
|
return UpdateModuleImpl.setLocalHashInfo(this.context, hash, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,50 +76,50 @@ getConstants(): Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setUuid(uuid: string): Promise<boolean> {
|
async setUuid(uuid: string): Promise<boolean> {
|
||||||
logger.debug(TAG, `,call setUuid`);
|
logger.debug(TAG, ',call setUuid');
|
||||||
return UpdateModuleImpl.setUuid(this.context,uuid);
|
return UpdateModuleImpl.setUuid(this.context,uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
async reloadUpdate(options: { hash: string }): Promise<void> {
|
async reloadUpdate(options: { hash: string }): Promise<void> {
|
||||||
logger.debug(TAG, `,call reloadUpdate`);
|
logger.debug(TAG, ',call reloadUpdate');
|
||||||
return UpdateModuleImpl.reloadUpdate(this.context, this.mUiCtx, options);
|
return UpdateModuleImpl.reloadUpdate(this.context, this.mUiCtx, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNeedUpdate(options: { hash: string }): Promise<boolean> {
|
async setNeedUpdate(options: { hash: string }): Promise<boolean> {
|
||||||
logger.debug(TAG, `,call setNeedUpdate`);
|
logger.debug(TAG, ',call setNeedUpdate');
|
||||||
return UpdateModuleImpl.setNeedUpdate(this.context, options);
|
return UpdateModuleImpl.setNeedUpdate(this.context, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async markSuccess(): Promise<boolean> {
|
async markSuccess(): Promise<boolean> {
|
||||||
logger.debug(TAG, `,call markSuccess`);
|
logger.debug(TAG, ',call markSuccess');
|
||||||
return UpdateModuleImpl.markSuccess(this.context);
|
return UpdateModuleImpl.markSuccess(this.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadPatchFromPpk(options: { updateUrl: string; hash: string; originHash: string }): Promise<void> {
|
async downloadPatchFromPpk(options: { updateUrl: string; hash: string; originHash: string }): Promise<void> {
|
||||||
logger.debug(TAG, `,call downloadPatchFromPpk`);
|
logger.debug(TAG, ',call downloadPatchFromPpk');
|
||||||
return UpdateModuleImpl.downloadPatchFromPpk(this.context, options);
|
return UpdateModuleImpl.downloadPatchFromPpk(this.context, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadPatchFromPackage(options: { updateUrl: string; hash: string }): Promise<void> {
|
async downloadPatchFromPackage(options: { updateUrl: string; hash: string }): Promise<void> {
|
||||||
logger.debug(TAG, `,call downloadPatchFromPackage`);
|
logger.debug(TAG, ',call downloadPatchFromPackage');
|
||||||
return UpdateModuleImpl.downloadPatchFromPackage(this.context, options);
|
return UpdateModuleImpl.downloadPatchFromPackage(this.context, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadFullUpdate(options: { updateUrl: string; hash: string }): Promise<void> {
|
async downloadFullUpdate(options: { updateUrl: string; hash: string }): Promise<void> {
|
||||||
logger.debug(TAG, `,call downloadFullUpdate`);
|
logger.debug(TAG, ',call downloadFullUpdate');
|
||||||
return UpdateModuleImpl.downloadFullUpdate(this.context, options);
|
return UpdateModuleImpl.downloadFullUpdate(this.context, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadAndInstallApk(options: { url: string; target: string; hash: string }): Promise<void> {
|
async downloadAndInstallApk(options: { url: string; target: string; hash: string }): Promise<void> {
|
||||||
logger.debug(TAG, `,call downloadAndInstallApk`);
|
logger.debug(TAG, ',call downloadAndInstallApk');
|
||||||
return UpdateModuleImpl.downloadAndInstallApk(this.mUiCtx, options);
|
return UpdateModuleImpl.downloadAndInstallApk(this.mUiCtx, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
addListener(eventName: string): void {
|
addListener(eventName: string): void {
|
||||||
logger.debug(TAG, `,call addListener`);
|
logger.debug(TAG, ',call addListener');
|
||||||
}
|
}
|
||||||
|
|
||||||
removeListeners(count: number): void {
|
removeListeners(count: number): void {
|
||||||
logger.debug(TAG, `,call removeListeners`);
|
logger.debug(TAG, ',call removeListeners');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,249 +6,276 @@ import common from '@ohos.app.ability.common';
|
|||||||
import { DownloadTaskParams } from './DownloadTaskParams';
|
import { DownloadTaskParams } from './DownloadTaskParams';
|
||||||
|
|
||||||
export class UpdateContext {
|
export class UpdateContext {
|
||||||
private context: common.UIAbilityContext;
|
private context: common.UIAbilityContext;
|
||||||
private rootDir: string;
|
private rootDir: string;
|
||||||
private preferences: preferences.Preferences;
|
private preferences: preferences.Preferences;
|
||||||
private static DEBUG: boolean = false;
|
private static DEBUG: boolean = false;
|
||||||
private static isUsingBundleUrl: boolean = false;
|
private static isUsingBundleUrl: boolean = false;
|
||||||
|
|
||||||
constructor(context: common.UIAbilityContext) {
|
constructor(context: common.UIAbilityContext) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.rootDir = context.filesDir + '/_update';
|
this.rootDir = context.filesDir + '/_update';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!fileIo.accessSync(this.rootDir)) {
|
if (!fileIo.accessSync(this.rootDir)) {
|
||||||
fileIo.mkdirSync(this.rootDir);
|
fileIo.mkdirSync(this.rootDir);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to create root directory:', e);
|
console.error('Failed to create root directory:', e);
|
||||||
}
|
|
||||||
this.initPreferences();
|
|
||||||
}
|
}
|
||||||
|
this.initPreferences();
|
||||||
|
}
|
||||||
|
|
||||||
private initPreferences() {
|
private initPreferences() {
|
||||||
try {
|
try {
|
||||||
this.preferences = preferences.getPreferencesSync(this.context, {name:'update'});
|
this.preferences = preferences.getPreferencesSync(this.context, {
|
||||||
const packageVersion = this.getPackageVersion();
|
name: 'update',
|
||||||
const storedVersion = this.preferences.getSync('packageVersion', '');
|
});
|
||||||
if(!storedVersion){
|
const packageVersion = this.getPackageVersion();
|
||||||
this.preferences.putSync('packageVersion', packageVersion);
|
const storedVersion = this.preferences.getSync('packageVersion', '');
|
||||||
this.preferences.flush();
|
if (!storedVersion) {
|
||||||
} else if (storedVersion && packageVersion !== storedVersion) {
|
this.preferences.putSync('packageVersion', packageVersion);
|
||||||
this.preferences.clear();
|
this.preferences.flush();
|
||||||
this.preferences.putSync('packageVersion', packageVersion);
|
} else if (storedVersion && packageVersion !== storedVersion) {
|
||||||
this.preferences.flush();
|
this.preferences.clear();
|
||||||
this.cleanUp();
|
this.preferences.putSync('packageVersion', packageVersion);
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to init preferences:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public setKv(key: string, value: string): void {
|
|
||||||
this.preferences.putSync(key, value);
|
|
||||||
this.preferences.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getKv(key: string): string {
|
|
||||||
return this.preferences.getSync(key, '') as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isFirstTime(): boolean {
|
|
||||||
return this.preferences.getSync('firstTime', false) as boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
public rolledBackVersion(): string {
|
|
||||||
return this.preferences.getSync('rolledBackVersion', '') as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public markSuccess(): void {
|
|
||||||
this.preferences.putSync('firstTimeOk', true);
|
|
||||||
const lastVersion = this.preferences.getSync('lastVersion', '') as string;
|
|
||||||
const curVersion = this.preferences.getSync('currentVersion', '') as string;
|
|
||||||
|
|
||||||
if (lastVersion && lastVersion !== curVersion) {
|
|
||||||
this.preferences.deleteSync('lastVersion');
|
|
||||||
this.preferences.deleteSync(`hash_${lastVersion}`);
|
|
||||||
}
|
|
||||||
this.preferences.flush();
|
this.preferences.flush();
|
||||||
this.cleanUp();
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to init preferences:', e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public clearFirstTime(): void {
|
public setKv(key: string, value: string): void {
|
||||||
this.preferences.putSync('firstTime', false);
|
this.preferences.putSync(key, value);
|
||||||
this.preferences.flush();
|
this.preferences.flush();
|
||||||
this.cleanUp();
|
}
|
||||||
|
|
||||||
|
public getKv(key: string): string {
|
||||||
|
return this.preferences.getSync(key, '') as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isFirstTime(): boolean {
|
||||||
|
return this.preferences.getSync('firstTime', false) as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public rolledBackVersion(): string {
|
||||||
|
return this.preferences.getSync('rolledBackVersion', '') as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
public markSuccess(): void {
|
||||||
|
this.preferences.putSync('firstTimeOk', true);
|
||||||
|
const lastVersion = this.preferences.getSync('lastVersion', '') as string;
|
||||||
|
const curVersion = this.preferences.getSync('currentVersion', '') as string;
|
||||||
|
|
||||||
|
if (lastVersion && lastVersion !== curVersion) {
|
||||||
|
this.preferences.deleteSync('lastVersion');
|
||||||
|
this.preferences.deleteSync(`hash_${lastVersion}`);
|
||||||
}
|
}
|
||||||
|
this.preferences.flush();
|
||||||
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
public clearRollbackMark(): void {
|
public clearFirstTime(): void {
|
||||||
this.preferences.putSync('rolledBackVersion', null);
|
this.preferences.putSync('firstTime', false);
|
||||||
this.preferences.flush();
|
this.preferences.flush();
|
||||||
this.cleanUp();
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clearRollbackMark(): void {
|
||||||
|
this.preferences.putSync('rolledBackVersion', null);
|
||||||
|
this.preferences.flush();
|
||||||
|
this.cleanUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async downloadFullUpdate(
|
||||||
|
url: string,
|
||||||
|
hash: string,
|
||||||
|
listener: DownloadFileListener,
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const params = new DownloadTaskParams();
|
||||||
|
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FULL;
|
||||||
|
params.url = url;
|
||||||
|
params.hash = hash;
|
||||||
|
params.listener = listener;
|
||||||
|
params.targetFile = `${this.rootDir}/${hash}.ppk`;
|
||||||
|
const downloadTask = new DownloadTask(this.context);
|
||||||
|
await downloadTask.execute(params);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to download full update:', e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async downloadFullUpdate(url: string, hash: string, listener: DownloadFileListener): Promise<void> {
|
public async downloadFile(
|
||||||
try {
|
url: string,
|
||||||
const params = new DownloadTaskParams();
|
hash: string,
|
||||||
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FULL;
|
fileName: string,
|
||||||
params.url = url;
|
listener: DownloadFileListener,
|
||||||
params.hash = hash;
|
): Promise<void> {
|
||||||
params.listener = listener;
|
const params = new DownloadTaskParams();
|
||||||
params.targetFile = `${this.rootDir}/${hash}.ppk`;
|
params.type = DownloadTaskParams.TASK_TYPE_PLAIN_DOWNLOAD;
|
||||||
const downloadTask = new DownloadTask(this.context);
|
params.url = url;
|
||||||
await downloadTask.execute(params);
|
params.hash = hash;
|
||||||
} catch (e) {
|
params.listener = listener;
|
||||||
console.error('Failed to download full update:', e);
|
params.targetFile = this.rootDir + '/' + fileName;
|
||||||
|
|
||||||
|
const downloadTask = new DownloadTask(this.context);
|
||||||
|
await downloadTask.execute(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async downloadPatchFromPpk(
|
||||||
|
url: string,
|
||||||
|
hash: string,
|
||||||
|
originHash: string,
|
||||||
|
listener: DownloadFileListener,
|
||||||
|
): Promise<void> {
|
||||||
|
const params = new DownloadTaskParams();
|
||||||
|
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK;
|
||||||
|
params.url = url;
|
||||||
|
params.hash = hash;
|
||||||
|
params.originHash = originHash;
|
||||||
|
params.listener = listener;
|
||||||
|
params.targetFile = `${this.rootDir}/${originHash}_${hash}.ppk.patch`;
|
||||||
|
params.unzipDirectory = `${this.rootDir}/${hash}`;
|
||||||
|
params.originDirectory = `${this.rootDir}/${params.originHash}`;
|
||||||
|
|
||||||
|
const downloadTask = new DownloadTask(this.context);
|
||||||
|
await downloadTask.execute(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async downloadPatchFromPackage(
|
||||||
|
url: string,
|
||||||
|
hash: string,
|
||||||
|
listener: DownloadFileListener,
|
||||||
|
): Promise<void> {
|
||||||
|
try {
|
||||||
|
const params = new DownloadTaskParams();
|
||||||
|
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_APP;
|
||||||
|
params.url = url;
|
||||||
|
params.hash = hash;
|
||||||
|
params.listener = listener;
|
||||||
|
params.targetFile = `${this.rootDir}/${hash}.app.patch`;
|
||||||
|
params.unzipDirectory = `${this.rootDir}/${hash}`;
|
||||||
|
|
||||||
|
const downloadTask = new DownloadTask(this.context);
|
||||||
|
return await downloadTask.execute(params);
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
console.error('Failed to download APK patch:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public switchVersion(hash: string): void {
|
||||||
|
try {
|
||||||
|
const bundlePath = `${this.rootDir}/${hash}/bundle.harmony.js`;
|
||||||
|
if (!fileIo.accessSync(bundlePath)) {
|
||||||
|
throw Error(`Bundle version ${hash} not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastVersion = this.getKv('currentVersion');
|
||||||
|
this.setKv('currentVersion', hash);
|
||||||
|
if (lastVersion && lastVersion !== hash) {
|
||||||
|
this.setKv('lastVersion', lastVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setKv('firstTime', 'true');
|
||||||
|
this.setKv('firstTimeOk', 'false');
|
||||||
|
this.setKv('rolledBackVersion', '');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to switch version:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getBundleUrl(
|
||||||
|
context: common.UIAbilityContext,
|
||||||
|
defaultAssetsUrl?: string,
|
||||||
|
): string {
|
||||||
|
return new UpdateContext(context).getBundleUrl(defaultAssetsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getBundleUrl(defaultAssetsUrl?: string): string {
|
||||||
|
UpdateContext.isUsingBundleUrl = true;
|
||||||
|
const currentVersion = this.getCurrentVersion();
|
||||||
|
if (!currentVersion) {
|
||||||
|
return defaultAssetsUrl;
|
||||||
|
}
|
||||||
|
if (!this.isFirstTime()) {
|
||||||
|
if (!this.preferences.getSync('firstTimeOk', true)) {
|
||||||
|
return this.rollBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let version = currentVersion;
|
||||||
|
while (version) {
|
||||||
|
const bundleFile = `${this.rootDir}/${version}/bundle.harmony.js`;
|
||||||
|
try {
|
||||||
|
if (!fileIo.accessSync(bundleFile)) {
|
||||||
|
console.error(`Bundle version ${version} not found.`);
|
||||||
|
version = this.rollBack();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
return bundleFile;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to access bundle file:', e);
|
||||||
|
version = this.rollBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return defaultAssetsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
public async downloadFile(url: string, hash: string, fileName: string, listener: DownloadFileListener): Promise<void> {
|
getPackageVersion(): string {
|
||||||
const params = new DownloadTaskParams();
|
let bundleFlags =
|
||||||
params.type = DownloadTaskParams.TASK_TYPE_PLAIN_DOWNLOAD;
|
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
|
||||||
params.url = url;
|
let packageVersion = '';
|
||||||
params.hash = hash;
|
try {
|
||||||
params.listener = listener;
|
const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleFlags);
|
||||||
params.targetFile = this.rootDir + '/' + fileName;
|
packageVersion = bundleInfo?.versionName || 'Unknown';
|
||||||
|
} catch (error) {
|
||||||
const downloadTask = new DownloadTask(this.context);
|
console.error('获取包信息失败:', error);
|
||||||
await downloadTask.execute(params);
|
|
||||||
}
|
}
|
||||||
|
return packageVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public async downloadPatchFromPpk(url: string, hash: string, originHash: string, listener: DownloadFileListener): Promise<void> {
|
public getCurrentVersion(): string {
|
||||||
const params = new DownloadTaskParams();
|
const currentVersion = this.getKv('currentVersion');
|
||||||
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_PPK;
|
return currentVersion;
|
||||||
params.url = url;
|
}
|
||||||
params.hash = hash;
|
|
||||||
params.originHash = originHash;
|
|
||||||
params.listener = listener;
|
|
||||||
params.targetFile = `${this.rootDir}/${originHash}_${hash}.ppk.patch`;
|
|
||||||
params.unzipDirectory = `${this.rootDir}/${hash}`;
|
|
||||||
params.originDirectory = `${this.rootDir}/${params.originHash}`;
|
|
||||||
|
|
||||||
const downloadTask = new DownloadTask(this.context);
|
private rollBack(): string {
|
||||||
await downloadTask.execute(params);
|
const lastVersion = this.preferences.getSync('lastVersion', '') as string;
|
||||||
|
const currentVersion = this.preferences.getSync(
|
||||||
|
'currentVersion',
|
||||||
|
'',
|
||||||
|
) as string;
|
||||||
|
if (!lastVersion) {
|
||||||
|
this.preferences.deleteSync('currentVersion');
|
||||||
|
} else {
|
||||||
|
this.preferences.putSync('currentVersion', lastVersion);
|
||||||
}
|
}
|
||||||
|
this.preferences.putSync('firstTimeOk', true);
|
||||||
|
this.preferences.putSync('firstTime', false);
|
||||||
|
this.preferences.putSync('rolledBackVersion', currentVersion);
|
||||||
|
this.preferences.flush();
|
||||||
|
return lastVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public async downloadPatchFromPackage(url: string, hash: string, listener: DownloadFileListener): Promise<void> {
|
private cleanUp(): void {
|
||||||
try {
|
const params = new DownloadTaskParams();
|
||||||
const params = new DownloadTaskParams();
|
params.type = DownloadTaskParams.TASK_TYPE_CLEANUP;
|
||||||
params.type = DownloadTaskParams.TASK_TYPE_PATCH_FROM_APP;
|
params.hash = this.preferences.getSync('currentVersion', '') as string;
|
||||||
params.url = url;
|
params.originHash = this.preferences.getSync('lastVersion', '') as string;
|
||||||
params.hash = hash;
|
params.unzipDirectory = this.rootDir;
|
||||||
params.listener = listener;
|
const downloadTask = new DownloadTask(this.context);
|
||||||
params.targetFile = `${this.rootDir}/${hash}.app.patch`;
|
downloadTask.execute(params);
|
||||||
params.unzipDirectory = `${this.rootDir}/${hash}`;
|
}
|
||||||
|
|
||||||
const downloadTask = new DownloadTask(this.context);
|
public getIsUsingBundleUrl(): boolean {
|
||||||
return await downloadTask.execute(params);
|
return UpdateContext.isUsingBundleUrl;
|
||||||
} catch (e) {
|
}
|
||||||
throw e;
|
|
||||||
console.error('Failed to download APK patch:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public switchVersion(hash: string): void {
|
|
||||||
try {
|
|
||||||
const bundlePath = `${this.rootDir}/${hash}/bundle.harmony.js`;
|
|
||||||
if (!fileIo.accessSync(bundlePath)) {
|
|
||||||
throw new Error(`Bundle version ${hash} not found.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastVersion = this.getKv('currentVersion');
|
|
||||||
this.setKv('currentVersion', hash);
|
|
||||||
if (lastVersion && lastVersion !== hash) {
|
|
||||||
this.setKv('lastVersion', lastVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setKv('firstTime', 'true');
|
|
||||||
this.setKv('firstTimeOk', 'false');
|
|
||||||
this.setKv('rolledBackVersion', "");
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to switch version:', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static getBundleUrl(context: common.UIAbilityContext, defaultAssetsUrl?: string): string {
|
|
||||||
return new UpdateContext(context).getBundleUrl(defaultAssetsUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getBundleUrl(defaultAssetsUrl?: string): string {
|
|
||||||
UpdateContext.isUsingBundleUrl = true;
|
|
||||||
const currentVersion = this.getCurrentVersion();
|
|
||||||
if (!currentVersion) {
|
|
||||||
return defaultAssetsUrl;
|
|
||||||
}
|
|
||||||
if (!this.isFirstTime()) {
|
|
||||||
if (!this.preferences.getSync('firstTimeOk', true)) {
|
|
||||||
return this.rollBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let version = currentVersion;
|
|
||||||
while (version) {
|
|
||||||
const bundleFile = `${this.rootDir}/${version}/bundle.harmony.js`;
|
|
||||||
try {
|
|
||||||
if (!fileIo.accessSync(bundleFile)) {
|
|
||||||
console.error(`Bundle version ${version} not found.`);
|
|
||||||
version = this.rollBack();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return bundleFile;
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to access bundle file:', e);
|
|
||||||
version = this.rollBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return defaultAssetsUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPackageVersion(): string {
|
|
||||||
let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION;
|
|
||||||
let packageVersion = '';
|
|
||||||
try {
|
|
||||||
const bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleFlags);
|
|
||||||
packageVersion = bundleInfo?.versionName || "Unknown";
|
|
||||||
} catch (error) {
|
|
||||||
console.error("获取包信息失败:", error);
|
|
||||||
}
|
|
||||||
return packageVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getCurrentVersion() : string {
|
|
||||||
const currentVersion = this.getKv('currentVersion');
|
|
||||||
return currentVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private rollBack(): string {
|
|
||||||
const lastVersion = this.preferences.getSync('lastVersion', '') as string;
|
|
||||||
const currentVersion = this.preferences.getSync('currentVersion', '') as string;
|
|
||||||
if (!lastVersion) {
|
|
||||||
this.preferences.deleteSync('currentVersion');
|
|
||||||
} else {
|
|
||||||
this.preferences.putSync('currentVersion', lastVersion);
|
|
||||||
}
|
|
||||||
this.preferences.putSync('firstTimeOk', true);
|
|
||||||
this.preferences.putSync('firstTime', false);
|
|
||||||
this.preferences.putSync('rolledBackVersion', currentVersion);
|
|
||||||
this.preferences.flush();
|
|
||||||
return lastVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
private cleanUp(): void {
|
|
||||||
const params = new DownloadTaskParams();
|
|
||||||
params.type = DownloadTaskParams.TASK_TYPE_CLEANUP;
|
|
||||||
params.hash = this.preferences.getSync('currentVersion', '') as string;
|
|
||||||
params.originHash = this.preferences.getSync('lastVersion', '') as string;
|
|
||||||
params.unzipDirectory = this.rootDir;
|
|
||||||
const downloadTask = new DownloadTask(this.context);
|
|
||||||
downloadTask.execute(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getIsUsingBundleUrl(): boolean {
|
|
||||||
return UpdateContext.isUsingBundleUrl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DownloadFileListener {
|
export interface DownloadFileListener {
|
||||||
onDownloadCompleted(params: DownloadTaskParams): void;
|
onDownloadCompleted(params: DownloadTaskParams): void;
|
||||||
onDownloadFailed(error: Error): void;
|
onDownloadFailed(error: Error): void;
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,14 @@ import { UpdateContext } from './UpdateContext';
|
|||||||
import { DownloadTaskParams } from './DownloadTaskParams';
|
import { DownloadTaskParams } from './DownloadTaskParams';
|
||||||
import logger from './Logger';
|
import logger from './Logger';
|
||||||
|
|
||||||
const TAG = "UpdateModuleImpl";
|
const TAG = 'UpdateModuleImpl';
|
||||||
|
|
||||||
export class UpdateModuleImpl {
|
export class UpdateModuleImpl {
|
||||||
static readonly NAME = "Pushy";
|
static readonly NAME = 'Pushy';
|
||||||
|
|
||||||
static async downloadFullUpdate(
|
static async downloadFullUpdate(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
options: { updateUrl: string; hash: string }
|
options: { updateUrl: string; hash: string },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await updateContext.downloadFullUpdate(options.updateUrl, options.hash, {
|
await updateContext.downloadFullUpdate(options.updateUrl, options.hash, {
|
||||||
@@ -20,7 +20,7 @@ export class UpdateModuleImpl {
|
|||||||
},
|
},
|
||||||
onDownloadFailed: (error: Error) => {
|
onDownloadFailed: (error: Error) => {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `downloadFullUpdate failed: ${error}`);
|
logger.error(TAG, `downloadFullUpdate failed: ${error}`);
|
||||||
@@ -30,18 +30,18 @@ export class UpdateModuleImpl {
|
|||||||
|
|
||||||
static async downloadAndInstallApk(
|
static async downloadAndInstallApk(
|
||||||
context: common.UIAbilityContext,
|
context: common.UIAbilityContext,
|
||||||
options: { url: string; hash: string; target: string }
|
options: { url: string; hash: string; target: string },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const want = {
|
const want = {
|
||||||
action: 'action.system.home',
|
action: 'action.system.home',
|
||||||
parameters: {
|
parameters: {
|
||||||
uri: 'appmarket://details'
|
uri: 'appmarket://details',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error('获取context失败');
|
throw Error('获取context失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.startAbility(want);
|
await context.startAbility(want);
|
||||||
@@ -53,17 +53,21 @@ export class UpdateModuleImpl {
|
|||||||
|
|
||||||
static async downloadPatchFromPackage(
|
static async downloadPatchFromPackage(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
options: { updateUrl: string; hash: string }
|
options: { updateUrl: string; hash: string },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
return await updateContext.downloadPatchFromPackage(options.updateUrl, options.hash, {
|
return await updateContext.downloadPatchFromPackage(
|
||||||
onDownloadCompleted: (params: DownloadTaskParams) => {
|
options.updateUrl,
|
||||||
return Promise.resolve();
|
options.hash,
|
||||||
|
{
|
||||||
|
onDownloadCompleted: (params: DownloadTaskParams) => {
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
onDownloadFailed: (error: Error) => {
|
||||||
|
return Promise.reject(error);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
onDownloadFailed: (error: Error) => {
|
);
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `downloadPatchFromPackage failed: ${error}`);
|
logger.error(TAG, `downloadPatchFromPackage failed: ${error}`);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -72,7 +76,7 @@ export class UpdateModuleImpl {
|
|||||||
|
|
||||||
static async downloadPatchFromPpk(
|
static async downloadPatchFromPpk(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
options: { updateUrl: string; hash: string; originHash: string }
|
options: { updateUrl: string; hash: string; originHash: string },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await updateContext.downloadPatchFromPpk(
|
await updateContext.downloadPatchFromPpk(
|
||||||
@@ -85,49 +89,49 @@ export class UpdateModuleImpl {
|
|||||||
},
|
},
|
||||||
onDownloadFailed: (error: Error) => {
|
onDownloadFailed: (error: Error) => {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `downloadPatchFromPpk failed: ${error}`);
|
logger.error(TAG, `downloadPatchFromPpk failed: ${error}`);
|
||||||
throw new Error(`执行报错: ${error.message}`);
|
throw Error(`执行报错: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async reloadUpdate(
|
static async reloadUpdate(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
context: common.UIAbilityContext,
|
context: common.UIAbilityContext,
|
||||||
options: { hash: string }
|
options: { hash: string },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const hash = options.hash;
|
const hash = options.hash;
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
throw new Error('hash不能为空');
|
throw Error('hash不能为空');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateContext.switchVersion(hash);
|
await updateContext.switchVersion(hash);
|
||||||
const bundleInfo = await bundleManager.getBundleInfoForSelf(
|
const bundleInfo = await bundleManager.getBundleInfoForSelf(
|
||||||
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION
|
bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION,
|
||||||
);
|
);
|
||||||
await context.terminateSelf();
|
await context.terminateSelf();
|
||||||
const want = {
|
const want = {
|
||||||
bundleName: bundleInfo.name,
|
bundleName: bundleInfo.name,
|
||||||
abilityName: context.abilityInfo?.name
|
abilityName: context.abilityInfo?.name,
|
||||||
};
|
};
|
||||||
await context.startAbility(want);
|
await context.startAbility(want);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `reloadUpdate failed: ${error}`);
|
logger.error(TAG, `reloadUpdate failed: ${error}`);
|
||||||
throw new Error(`pushy:switchVersion failed ${error.message}`);
|
throw Error(`pushy:switchVersion failed ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setNeedUpdate(
|
static async setNeedUpdate(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
options: { hash: string }
|
options: { hash: string },
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const hash = options.hash;
|
const hash = options.hash;
|
||||||
if (!hash) {
|
if (!hash) {
|
||||||
throw new Error('hash不能为空');
|
throw Error('hash不能为空');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -135,7 +139,7 @@ export class UpdateModuleImpl {
|
|||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `setNeedUpdate failed: ${error}`);
|
logger.error(TAG, `setNeedUpdate failed: ${error}`);
|
||||||
throw new Error(`switchVersionLater failed: ${error.message}`);
|
throw Error(`switchVersionLater failed: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,20 +149,20 @@ export class UpdateModuleImpl {
|
|||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `markSuccess failed: ${error}`);
|
logger.error(TAG, `markSuccess failed: ${error}`);
|
||||||
throw new Error(`执行报错: ${error.message}`);
|
throw Error(`执行报错: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setUuid(
|
static async setUuid(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
uuid: string
|
uuid: string,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await updateContext.setKv('uuid', uuid);
|
await updateContext.setKv('uuid', uuid);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(TAG, `setUuid failed: ${error}`);
|
logger.error(TAG, `setUuid failed: ${error}`);
|
||||||
throw new Error(`执行报错: ${error.message}`);
|
throw Error(`执行报错: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,16 +178,13 @@ export class UpdateModuleImpl {
|
|||||||
static setLocalHashInfo(
|
static setLocalHashInfo(
|
||||||
updateContext: UpdateContext,
|
updateContext: UpdateContext,
|
||||||
hash: string,
|
hash: string,
|
||||||
info: string
|
info: string,
|
||||||
): boolean {
|
): boolean {
|
||||||
updateContext.setKv(`hash_${hash}`, info);
|
updateContext.setKv(`hash_${hash}`, info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getLocalHashInfo(
|
static getLocalHashInfo(updateContext: UpdateContext, hash: string): string {
|
||||||
updateContext: UpdateContext,
|
|
||||||
hash: string
|
|
||||||
): string {
|
|
||||||
const value = updateContext.getKv(`hash_${hash}`);
|
const value = updateContext.getKv(`hash_${hash}`);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-native-update",
|
"name": "react-native-update",
|
||||||
"version": "10.31.3",
|
"version": "10.34.9",
|
||||||
"description": "react-native hot update",
|
"description": "react-native hot update",
|
||||||
"main": "src/index",
|
"main": "src/index",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"lint": "eslint \"src/*.@(ts|tsx|js|jsx)\" && tsc --noEmit",
|
"lint": "eslint \"src/*.@(ts|tsx|js|jsx)\" && tsc --noEmit",
|
||||||
"submodule": "git submodule update --init --recursive",
|
"submodule": "git submodule update --init --recursive",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build-lib": "bun submodule && $ANDROID_HOME/ndk/20.1.5948944/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
|
"build:so": "bun submodule && $ANDROID_HOME/ndk/28.2.13676358/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
|
||||||
"build:ios-debug": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.debug",
|
"build:ios-debug": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.debug",
|
||||||
"build:ios-release": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.release",
|
"build:ios-release": "cd Example/testHotUpdate && bun && detox build --configuration ios.sim.release",
|
||||||
"test:ios-debug": "cd Example/testHotUpdate && detox test --configuration ios.sim.debug",
|
"test:ios-debug": "cd Example/testHotUpdate && detox test --configuration ios.sim.debug",
|
||||||
@@ -72,6 +72,5 @@
|
|||||||
"react-native": "0.73",
|
"react-native": "0.73",
|
||||||
"ts-jest": "^29.3.2",
|
"ts-jest": "^29.3.2",
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.6.3"
|
||||||
},
|
}
|
||||||
"packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,18 +105,17 @@ Pod::Spec.new do |s|
|
|||||||
|
|
||||||
# Conditionally add Expo dependency
|
# Conditionally add Expo dependency
|
||||||
if valid_expo_project
|
if valid_expo_project
|
||||||
s.public_header_files = ['ios/ImportReact.h']
|
|
||||||
s.dependency 'ExpoModulesCore'
|
s.dependency 'ExpoModulesCore'
|
||||||
end
|
end
|
||||||
|
|
||||||
s.subspec 'RCTPushy' do |ss|
|
s.subspec 'RCTPushy' do |ss|
|
||||||
ss.source_files = ['ios/RCTPushy/**/*.{h,m,mm,c}',
|
ss.source_files = ['ios/**/*.{h,m,mm,c}',
|
||||||
'android/jni/hpatch.{h,c}',
|
'android/jni/hpatch.{h,c}',
|
||||||
'android/jni/HDiffPatch/libHDiffPatch/HPatch/*.{h,c}',
|
'android/jni/HDiffPatch/libHDiffPatch/HPatch/*.{h,c}',
|
||||||
'android/jni/HDiffPatch/file_for_patch.{h,c}',
|
'android/jni/HDiffPatch/file_for_patch.{h,c}',
|
||||||
'android/jni/lzma/C/LzmaDec.{h,c}',
|
'android/jni/lzma/C/LzmaDec.{h,c}',
|
||||||
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
||||||
ss.public_header_files = ['ios/RCTPushy/**/*.h']
|
ss.public_header_files = ['ios/**/*.h']
|
||||||
end
|
end
|
||||||
|
|
||||||
# Conditionally add Expo subspec and check ExpoModulesCore version
|
# Conditionally add Expo subspec and check ExpoModulesCore version
|
||||||
|
|||||||
1
react-native.config.js
Normal file
1
react-native.config.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = {};
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
buildTime,
|
buildTime,
|
||||||
cInfo,
|
cInfo,
|
||||||
currentVersion,
|
currentVersion,
|
||||||
getCurrentVersionInfo,
|
currentVersionInfo,
|
||||||
isFirstTime,
|
isFirstTime,
|
||||||
isRolledBack,
|
isRolledBack,
|
||||||
packageVersion,
|
packageVersion,
|
||||||
@@ -93,7 +93,6 @@ export class Pushy {
|
|||||||
clientType: 'Pushy' | 'Cresc' = 'Pushy';
|
clientType: 'Pushy' | 'Cresc' = 'Pushy';
|
||||||
lastChecking?: number;
|
lastChecking?: number;
|
||||||
lastRespJson?: Promise<CheckResult>;
|
lastRespJson?: Promise<CheckResult>;
|
||||||
lastRespText?: Promise<string>;
|
|
||||||
|
|
||||||
version = cInfo.rnu;
|
version = cInfo.rnu;
|
||||||
loggerPromise = (() => {
|
loggerPromise = (() => {
|
||||||
@@ -111,12 +110,11 @@ export class Pushy {
|
|||||||
this.clientType = clientType || 'Pushy';
|
this.clientType = clientType || 'Pushy';
|
||||||
this.options.server = SERVER_PRESETS[this.clientType];
|
this.options.server = SERVER_PRESETS[this.clientType];
|
||||||
|
|
||||||
// Initialize i18n based on clientType
|
i18n.setLocale(options.locale ?? this.clientType === 'Pushy' ? 'zh' : 'en');
|
||||||
i18n.setLocale(this.clientType === 'Pushy' ? 'zh' : 'en');
|
|
||||||
|
|
||||||
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
||||||
if (!options.appKey) {
|
if (!options.appKey) {
|
||||||
throw new Error(i18n.t('error_appkey_required'));
|
throw Error(i18n.t('error_appkey_required'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +162,6 @@ export class Pushy {
|
|||||||
log(type + ' ' + message);
|
log(type + ' ' + message);
|
||||||
await this.loggerPromise.promise;
|
await this.loggerPromise.promise;
|
||||||
const { logger = noop, appKey } = this.options;
|
const { logger = noop, appKey } = this.options;
|
||||||
const info = await getCurrentVersionInfo();
|
|
||||||
const overridePackageVersion = this.options.overridePackageVersion;
|
const overridePackageVersion = this.options.overridePackageVersion;
|
||||||
logger({
|
logger({
|
||||||
type,
|
type,
|
||||||
@@ -176,7 +173,7 @@ export class Pushy {
|
|||||||
overridePackageVersion,
|
overridePackageVersion,
|
||||||
buildTime,
|
buildTime,
|
||||||
message,
|
message,
|
||||||
...info,
|
...currentVersionInfo,
|
||||||
...data,
|
...data,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -293,10 +290,10 @@ export class Pushy {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this.throwIfEnabled(new Error('errorCheckingUseBackup'));
|
this.throwIfEnabled(Error('errorCheckingUseBackup'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.throwIfEnabled(new Error('errorCheckingGetBackup'));
|
this.throwIfEnabled(Error('errorCheckingGetBackup'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
@@ -304,21 +301,21 @@ export class Pushy {
|
|||||||
type: 'errorChecking',
|
type: 'errorChecking',
|
||||||
message: this.t('error_cannot_connect_server'),
|
message: this.t('error_cannot_connect_server'),
|
||||||
});
|
});
|
||||||
this.throwIfEnabled(new Error('errorChecking'));
|
this.throwIfEnabled(Error('errorChecking'));
|
||||||
return this.lastRespJson ? await this.lastRespJson : emptyObj;
|
return this.lastRespJson ? await this.lastRespJson : emptyObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resp.status !== 200) {
|
if (!resp.ok) {
|
||||||
|
const respText = await resp.text();
|
||||||
const errorMessage = this.t('error_http_status', {
|
const errorMessage = this.t('error_http_status', {
|
||||||
status: resp.status,
|
status: resp.status,
|
||||||
statusText: resp.statusText,
|
statusText: respText,
|
||||||
});
|
});
|
||||||
this.report({
|
this.report({
|
||||||
type: 'errorChecking',
|
type: 'errorChecking',
|
||||||
message: errorMessage,
|
message: errorMessage,
|
||||||
});
|
});
|
||||||
this.throwIfEnabled(new Error(errorMessage));
|
this.throwIfEnabled(Error(errorMessage));
|
||||||
log('error checking response:', resp.status, await resp.text());
|
|
||||||
return this.lastRespJson ? await this.lastRespJson : emptyObj;
|
return this.lastRespJson ? await this.lastRespJson : emptyObj;
|
||||||
}
|
}
|
||||||
this.lastRespJson = resp.json();
|
this.lastRespJson = resp.json();
|
||||||
@@ -435,7 +432,7 @@ export class Pushy {
|
|||||||
message: e.message,
|
message: e.message,
|
||||||
});
|
});
|
||||||
errorMessages.push(errorMessage);
|
errorMessages.push(errorMessage);
|
||||||
lastError = new Error(errorMessage);
|
lastError = Error(errorMessage);
|
||||||
log(errorMessage);
|
log(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,7 +451,7 @@ export class Pushy {
|
|||||||
message: e.message,
|
message: e.message,
|
||||||
});
|
});
|
||||||
errorMessages.push(errorMessage);
|
errorMessages.push(errorMessage);
|
||||||
lastError = new Error(errorMessage);
|
lastError = Error(errorMessage);
|
||||||
log(errorMessage);
|
log(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,7 +471,7 @@ export class Pushy {
|
|||||||
message: e.message,
|
message: e.message,
|
||||||
});
|
});
|
||||||
errorMessages.push(errorMessage);
|
errorMessages.push(errorMessage);
|
||||||
lastError = new Error(errorMessage);
|
lastError = Error(errorMessage);
|
||||||
log(errorMessage);
|
log(errorMessage);
|
||||||
}
|
}
|
||||||
} else if (__DEV__) {
|
} else if (__DEV__) {
|
||||||
@@ -532,7 +529,7 @@ export class Pushy {
|
|||||||
}
|
}
|
||||||
if (sharedState.apkStatus === 'downloaded') {
|
if (sharedState.apkStatus === 'downloaded') {
|
||||||
this.report({ type: 'errorInstallApk' });
|
this.report({ type: 'errorInstallApk' });
|
||||||
this.throwIfEnabled(new Error('errorInstallApk'));
|
this.throwIfEnabled(Error('errorInstallApk'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Platform.Version <= 23) {
|
if (Platform.Version <= 23) {
|
||||||
@@ -542,7 +539,7 @@ export class Pushy {
|
|||||||
);
|
);
|
||||||
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
||||||
this.report({ type: 'rejectStoragePermission' });
|
this.report({ type: 'rejectStoragePermission' });
|
||||||
this.throwIfEnabled(new Error('rejectStoragePermission'));
|
this.throwIfEnabled(Error('rejectStoragePermission'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@@ -575,7 +572,7 @@ export class Pushy {
|
|||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
sharedState.apkStatus = null;
|
sharedState.apkStatus = null;
|
||||||
this.report({ type: 'errorDownloadAndInstallApk' });
|
this.report({ type: 'errorDownloadAndInstallApk' });
|
||||||
this.throwIfEnabled(new Error('errorDownloadAndInstallApk'));
|
this.throwIfEnabled(Error('errorDownloadAndInstallApk'));
|
||||||
});
|
});
|
||||||
sharedState.apkStatus = 'downloaded';
|
sharedState.apkStatus = 'downloaded';
|
||||||
if (sharedState.progressHandlers[progressKey]) {
|
if (sharedState.progressHandlers[progressKey]) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const PushyModule =
|
|||||||
export const UpdateModule = PushyModule;
|
export const UpdateModule = PushyModule;
|
||||||
|
|
||||||
if (!PushyModule) {
|
if (!PushyModule) {
|
||||||
throw new Error(
|
throw Error(
|
||||||
'Failed to load react-native-update native module, please try to recompile',
|
'Failed to load react-native-update native module, please try to recompile',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import { Pushy, Cresc, sharedState } from './client';
|
|||||||
import { currentVersion, packageVersion, getCurrentVersionInfo, currentVersionInfo } from './core';
|
import { currentVersion, packageVersion, getCurrentVersionInfo, currentVersionInfo } from './core';
|
||||||
import {
|
import {
|
||||||
CheckResult,
|
CheckResult,
|
||||||
MixedCheckResult,
|
|
||||||
ProgressData,
|
ProgressData,
|
||||||
UpdateTestPayload,
|
UpdateTestPayload,
|
||||||
|
VersionInfo,
|
||||||
} from './type';
|
} from './type';
|
||||||
import { UpdateContext } from './context';
|
import { UpdateContext } from './context';
|
||||||
import { URL } from 'react-native-url-polyfill';
|
import { URL } from 'react-native-url-polyfill';
|
||||||
@@ -163,7 +163,7 @@ export const UpdateProvider = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastChecking.current = now;
|
lastChecking.current = now;
|
||||||
let rootInfo: MixedCheckResult | undefined;
|
let rootInfo: CheckResult | undefined;
|
||||||
try {
|
try {
|
||||||
rootInfo = await client.checkUpdate(extra);
|
rootInfo = await client.checkUpdate(extra);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@@ -175,12 +175,12 @@ export const UpdateProvider = ({
|
|||||||
if (!rootInfo) {
|
if (!rootInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const versions = rootInfo.versions || [rootInfo as CheckResult];
|
const versions = [rootInfo.expVersion, rootInfo].filter(Boolean) as VersionInfo[];
|
||||||
delete rootInfo.versions;
|
delete rootInfo.expVersion;
|
||||||
for (const versionInfo of versions) {
|
for (const versionInfo of versions) {
|
||||||
const info: CheckResult = {
|
const info: CheckResult = {
|
||||||
...versionInfo,
|
|
||||||
...rootInfo,
|
...rootInfo,
|
||||||
|
...versionInfo,
|
||||||
};
|
};
|
||||||
const rollout = info.config?.rollout?.[packageVersion];
|
const rollout = info.config?.rollout?.[packageVersion];
|
||||||
if (info.update && rollout) {
|
if (info.update && rollout) {
|
||||||
@@ -242,7 +242,7 @@ export const UpdateProvider = ({
|
|||||||
alertUpdate(
|
alertUpdate(
|
||||||
client.t('alert_title'),
|
client.t('alert_title'),
|
||||||
client.t('alert_new_version_found', {
|
client.t('alert_new_version_found', {
|
||||||
name: info.name,
|
name: info.name!,
|
||||||
description: info.description,
|
description: info.description,
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
|
|||||||
13
src/type.ts
13
src/type.ts
@@ -24,14 +24,10 @@ interface RootResult {
|
|||||||
paths?: string[];
|
paths?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CheckResult = RootResult & VersionInfo;
|
export type CheckResult = RootResult &
|
||||||
|
Partial<VersionInfo> & {
|
||||||
export type CheckResultV2 = RootResult & {
|
expVersion?: VersionInfo;
|
||||||
versions?: VersionInfo[];
|
};
|
||||||
};
|
|
||||||
|
|
||||||
export type MixedCheckResult = CheckResult | CheckResultV2;
|
|
||||||
|
|
||||||
|
|
||||||
export interface ProgressData {
|
export interface ProgressData {
|
||||||
hash: string;
|
hash: string;
|
||||||
@@ -90,6 +86,7 @@ export interface ClientOptions {
|
|||||||
appKey: string;
|
appKey: string;
|
||||||
server?: UpdateServerConfig;
|
server?: UpdateServerConfig;
|
||||||
logger?: UpdateEventsLogger;
|
logger?: UpdateEventsLogger;
|
||||||
|
locale?: 'zh' | 'en';
|
||||||
updateStrategy?:
|
updateStrategy?:
|
||||||
| 'alwaysAlert'
|
| 'alwaysAlert'
|
||||||
| 'alertUpdateAndIgnoreError'
|
| 'alertUpdateAndIgnoreError'
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export function promiseAny<T>(promises: Promise<T>[]) {
|
|||||||
.catch(() => {
|
.catch(() => {
|
||||||
count++;
|
count++;
|
||||||
if (count === promises.length) {
|
if (count === promises.length) {
|
||||||
reject(new Error(i18n.t('error_all_promises_rejected')));
|
reject(Error(i18n.t('error_all_promises_rejected')));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -51,7 +51,7 @@ const ping = isWeb
|
|||||||
return finalUrl;
|
return finalUrl;
|
||||||
}
|
}
|
||||||
log('ping failed', url, status, statusText);
|
log('ping failed', url, status, statusText);
|
||||||
throw new Error(i18n.t('error_ping_failed'));
|
throw Error(i18n.t('error_ping_failed'));
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
pingFinished = true;
|
pingFinished = true;
|
||||||
@@ -60,7 +60,7 @@ const ping = isWeb
|
|||||||
}),
|
}),
|
||||||
new Promise((_, reject) =>
|
new Promise((_, reject) =>
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(new Error(i18n.t('error_ping_timeout')));
|
reject(Error(i18n.t('error_ping_timeout')));
|
||||||
if (!pingFinished) {
|
if (!pingFinished) {
|
||||||
log('ping timeout', url);
|
log('ping timeout', url);
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ export const enhancedFetch = async (
|
|||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw Error(
|
||||||
i18n.t('error_http_status', {
|
i18n.t('error_http_status', {
|
||||||
status: r.status,
|
status: r.status,
|
||||||
statusText: r.statusText,
|
statusText: r.statusText,
|
||||||
|
|||||||
Reference in New Issue
Block a user