mirror of
https://gitcode.com/gh_mirrors/re/react-native-pushy.git
synced 2025-09-18 02:16:11 +08:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3e02ff6099 | ||
![]() |
462a342172 | ||
![]() |
94d2e18900 | ||
![]() |
d000c40e0f | ||
![]() |
5659c79726 | ||
![]() |
b20d987473 | ||
![]() |
14c9c0b1f5 | ||
![]() |
10178e1e64 | ||
![]() |
6d980a4c04 | ||
![]() |
084fbf35ee | ||
![]() |
d666e8c0f3 | ||
![]() |
5e89fb4a25 | ||
![]() |
ab01b6010a | ||
![]() |
92bc830d98 | ||
![]() |
7531e8ca3a | ||
![]() |
b2305cff3f | ||
![]() |
c5cdb6031b | ||
![]() |
20ebf8979e | ||
![]() |
3929fc2f8e | ||
![]() |
31ee269717 | ||
![]() |
adcd57b6b5 | ||
![]() |
c595e4e54a | ||
![]() |
4f80f96a8d | ||
![]() |
a77c3c85f3 | ||
![]() |
2357a0b78d | ||
![]() |
88bacdfb15 | ||
![]() |
90fee03c45 | ||
![]() |
7243512d3c |
@@ -94,7 +94,7 @@ apply from: "../../node_modules/react-native/react.gradle"
|
|||||||
* Upload all the APKs to the Play Store and people will download
|
* Upload all the APKs to the Play Store and people will download
|
||||||
* the correct one based on the CPU architecture of their device.
|
* the correct one based on the CPU architecture of their device.
|
||||||
*/
|
*/
|
||||||
def enableSeparateBuildPerCPUArchitecture = false
|
def enableSeparateBuildPerCPUArchitecture = true
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run Proguard to shrink the Java bytecode in release builds.
|
* Run Proguard to shrink the Java bytecode in release builds.
|
||||||
@@ -141,7 +141,7 @@ android {
|
|||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "2.0"
|
||||||
testBuildType System.getProperty('testBuildType', 'debug')
|
testBuildType System.getProperty('testBuildType', 'debug')
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||||
@@ -237,6 +237,7 @@ android {
|
|||||||
release {
|
release {
|
||||||
// Caution! In production, you need to generate your own keystore file.
|
// Caution! In production, you need to generate your own keystore file.
|
||||||
// see https://reactnative.dev/docs/signed-apk-android.
|
// see https://reactnative.dev/docs/signed-apk-android.
|
||||||
|
crunchPngs false
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
minifyEnabled enableProguardInReleaseBuilds
|
minifyEnabled enableProguardInReleaseBuilds
|
||||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||||
|
@@ -24,6 +24,12 @@
|
|||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="testhotupdate" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
"react-native-camera-kit": "^14.0.0-beta15",
|
"react-native-camera-kit": "^14.0.0-beta15",
|
||||||
"react-native-paper": "^5.12.1",
|
"react-native-paper": "^5.12.1",
|
||||||
"react-native-safe-area-context": "^4.8.2",
|
"react-native-safe-area-context": "^4.8.2",
|
||||||
"react-native-update": "^10.10.0",
|
"react-native-update": "^10.11.3",
|
||||||
"react-native-vector-icons": "^10.0.3"
|
"react-native-vector-icons": "^10.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable react/no-unstable-nested-components */
|
/* eslint-disable react/no-unstable-nested-components */
|
||||||
/* eslint-disable react-native/no-inline-styles */
|
/* eslint-disable react-native/no-inline-styles */
|
||||||
import React, {useState} from 'react';
|
import React, {useRef, useState} from 'react';
|
||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Platform,
|
Platform,
|
||||||
@@ -37,7 +37,7 @@ function App() {
|
|||||||
updateInfo,
|
updateInfo,
|
||||||
packageVersion,
|
packageVersion,
|
||||||
currentHash,
|
currentHash,
|
||||||
parseTestPayload,
|
parseTestQrCode,
|
||||||
progress: {received, total} = {},
|
progress: {received, total} = {},
|
||||||
} = usePushy();
|
} = usePushy();
|
||||||
const [useDefaultAlert, setUseDefaultAlert] = useState(true);
|
const [useDefaultAlert, setUseDefaultAlert] = useState(true);
|
||||||
@@ -47,6 +47,7 @@ function App() {
|
|||||||
const snackbarVisible =
|
const snackbarVisible =
|
||||||
!useDefaultAlert && showUpdateSnackbar && updateInfo?.update;
|
!useDefaultAlert && showUpdateSnackbar && updateInfo?.update;
|
||||||
const [showCamera, setShowCamera] = useState(false);
|
const [showCamera, setShowCamera] = useState(false);
|
||||||
|
const lastParsedCode = useRef('');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
@@ -73,9 +74,16 @@ function App() {
|
|||||||
style={{minHeight: 320}}
|
style={{minHeight: 320}}
|
||||||
scanBarcode={true}
|
scanBarcode={true}
|
||||||
onReadCode={({nativeEvent: {codeStringValue}}) => {
|
onReadCode={({nativeEvent: {codeStringValue}}) => {
|
||||||
console.log(codeStringValue);
|
// 防止重复扫码
|
||||||
parseTestPayload(codeStringValue);
|
if (lastParsedCode.current === codeStringValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastParsedCode.current = codeStringValue;
|
||||||
|
setTimeout(() => {
|
||||||
|
lastParsedCode.current = '';
|
||||||
|
}, 1000);
|
||||||
setShowCamera(false);
|
setShowCamera(false);
|
||||||
|
parseTestQrCode(codeStringValue);
|
||||||
}} // optional
|
}} // optional
|
||||||
showFrame={true} // (default false) optional, show frame with transparent layer (qr code or barcode will be read on this area ONLY), start animation for scanner, that stops when a code has been found. Frame always at center of the screen
|
showFrame={true} // (default false) optional, show frame with transparent layer (qr code or barcode will be read on this area ONLY), start animation for scanner, that stops when a code has been found. Frame always at center of the screen
|
||||||
laserColor="red" // (default red) optional, color of laser in scanner frame
|
laserColor="red" // (default red) optional, color of laser in scanner frame
|
||||||
|
@@ -2123,7 +2123,7 @@ buffer-from@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||||
|
|
||||||
buffer@^5.5.0:
|
buffer@^5.4.3, buffer@^5.5.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||||
@@ -6159,7 +6159,7 @@ pump@^3.0.0:
|
|||||||
end-of-stream "^1.1.0"
|
end-of-stream "^1.1.0"
|
||||||
once "^1.3.1"
|
once "^1.3.1"
|
||||||
|
|
||||||
punycode@^2.1.0:
|
punycode@^2.1.0, punycode@^2.1.1:
|
||||||
version "2.3.1"
|
version "2.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
|
||||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||||
@@ -6236,12 +6236,20 @@ react-native-safe-area-context@^4.8.2:
|
|||||||
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz#e6b3d8acf3c6afcb4b5db03a97f9c37df7668f65"
|
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz#e6b3d8acf3c6afcb4b5db03a97f9c37df7668f65"
|
||||||
integrity sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==
|
integrity sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==
|
||||||
|
|
||||||
react-native-update@^10.10.0:
|
react-native-update@^10.11.3:
|
||||||
version "10.10.0"
|
version "10.11.3"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.10.0.tgz#5861f0c217d1ed194e1a8aba81fed5430178795c"
|
resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.11.3.tgz#5fa44fdd12514eb5e7901a5d664f00fd082d6774"
|
||||||
integrity sha512-qZd5kJ9UlNh5Y0zU5vLdIviYwLvTPqdgIynmt4DQ1wEUu2/F6RrI17dICq54em5ValQWB6ua/tdj2lyTVPvADg==
|
integrity sha512-adI3sly0yFt1DfaPqICJ9VwzUoa/XAngv/N7SnICkLxO3jgccBgy0OrXDBxRn43Zeumdq40Z+ADTE5qrY4BWAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.3"
|
nanoid "^3.3.3"
|
||||||
|
react-native-url-polyfill "^2.0.0"
|
||||||
|
|
||||||
|
react-native-url-polyfill@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
|
||||||
|
integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url-without-unicode "8.0.0-3"
|
||||||
|
|
||||||
react-native-vector-icons@^10.0.3:
|
react-native-vector-icons@^10.0.3:
|
||||||
version "10.0.3"
|
version "10.0.3"
|
||||||
@@ -7490,11 +7498,25 @@ webidl-conversions@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||||
|
|
||||||
|
webidl-conversions@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
|
||||||
|
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
|
||||||
|
|
||||||
whatwg-fetch@^3.0.0:
|
whatwg-fetch@^3.0.0:
|
||||||
version "3.6.20"
|
version "3.6.20"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
|
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
|
||||||
integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
|
integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
|
||||||
|
|
||||||
|
whatwg-url-without-unicode@8.0.0-3:
|
||||||
|
version "8.0.0-3"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
|
||||||
|
integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.4.3"
|
||||||
|
punycode "^2.1.1"
|
||||||
|
webidl-conversions "^5.0.0"
|
||||||
|
|
||||||
whatwg-url@^5.0.0:
|
whatwg-url@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
### 优势
|
### 优势
|
||||||
|
|
||||||
1. 基于阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。
|
1. 对中国用户使用阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。对国外用户则智能分流至 cloudflare,同样享受高速更新服务。
|
||||||
2. 基于 bsdiff/hdiff 算法创建的**超小更新包**,通常版本迭代后在几十 KB 级别(其他全量热更新服务所需流量通常在几十 MB 级别)。
|
2. 基于 bsdiff/hdiff 算法创建的**超小更新包**,通常版本迭代后在几十 KB 级别(其他全量热更新服务所需流量通常在几十 MB 级别)。
|
||||||
3. 始终跟进 RN 最新正式版本,第一时间提供支持。支持 hermes 字节码格式。支持新架构。
|
3. 始终跟进 RN 最新正式版本,第一时间提供支持。支持 hermes 字节码格式。支持新架构。
|
||||||
4. 跨越多个版本进行更新时,只需要下载**一个更新包**,不需要逐版本依次更新。
|
4. 跨越多个版本进行更新时,只需要下载**一个更新包**,不需要逐版本依次更新。
|
||||||
@@ -33,4 +33,3 @@ $ yarn start
|
|||||||
本组件由[React Native 中文网](https://reactnative.cn/)独家发布,如有定制需求可以[联系我们](https://reactnative.cn/about.html#content)。
|
本组件由[React Native 中文网](https://reactnative.cn/)独家发布,如有定制需求可以[联系我们](https://reactnative.cn/about.html#content)。
|
||||||
|
|
||||||
关于此插件发现任何问题,可以前往[Issues](https://github.com/reactnativecn/react-native-pushy/issues)发帖提问。
|
关于此插件发现任何问题,可以前往[Issues](https://github.com/reactnativecn/react-native-pushy/issues)发帖提问。
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
["https://update.react-native.cn/api", "https://update.reactnative.cn/api", "https://p.reactnative.cn/api"]
|
["https://pushy-koa-qgbgqmcpis.cn-beijing.fcapp.run", "https://p.reactnative.cn/api"]
|
||||||
|
@@ -75,7 +75,7 @@ RCT_EXPORT_MODULE(RCTPushy);
|
|||||||
if (needClearPushyInfo) {
|
if (needClearPushyInfo) {
|
||||||
[defaults setObject:nil forKey:keyPushyInfo];
|
[defaults setObject:nil forKey:keyPushyInfo];
|
||||||
[defaults setObject:@(YES) forKey:KeyPackageUpdatedMarked];
|
[defaults setObject:@(YES) forKey:KeyPackageUpdatedMarked];
|
||||||
[defaults synchronize];
|
|
||||||
// ...need clear files later
|
// ...need clear files later
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -97,7 +97,7 @@ RCT_EXPORT_MODULE(RCTPushy);
|
|||||||
newInfo[paramIsFirstTime] = @(NO);
|
newInfo[paramIsFirstTime] = @(NO);
|
||||||
[defaults setObject:newInfo forKey:keyPushyInfo];
|
[defaults setObject:newInfo forKey:keyPushyInfo];
|
||||||
[defaults setObject:@(YES) forKey:keyFirstLoadMarked];
|
[defaults setObject:@(YES) forKey:keyFirstLoadMarked];
|
||||||
[defaults synchronize];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString *downloadDir = [RCTPushy downloadDir];
|
NSString *downloadDir = [RCTPushy downloadDir];
|
||||||
@@ -137,7 +137,7 @@ RCT_EXPORT_MODULE(RCTPushy);
|
|||||||
[defaults setObject:nil forKey:keyPushyInfo];
|
[defaults setObject:nil forKey:keyPushyInfo];
|
||||||
}
|
}
|
||||||
[defaults setObject:curVersion forKey:keyRolledBackMarked];
|
[defaults setObject:curVersion forKey:keyRolledBackMarked];
|
||||||
[defaults synchronize];
|
|
||||||
return lastVersion;
|
return lastVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ RCT_EXPORT_MODULE(RCTPushy);
|
|||||||
[defaults setObject:nil forKey:KeyPackageUpdatedMarked];
|
[defaults setObject:nil forKey:KeyPackageUpdatedMarked];
|
||||||
[self clearInvalidFiles];
|
[self clearInvalidFiles];
|
||||||
}
|
}
|
||||||
[defaults synchronize];
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ RCT_EXPORT_METHOD(setUuid:(NSString *)uuid resolver:(RCTPromiseResolveBlock)res
|
|||||||
@try {
|
@try {
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
[defaults setObject:uuid forKey:keyUuid];
|
[defaults setObject:uuid forKey:keyUuid];
|
||||||
[defaults synchronize];
|
|
||||||
resolve(@true);
|
resolve(@true);
|
||||||
}
|
}
|
||||||
@catch (NSException *exception) {
|
@catch (NSException *exception) {
|
||||||
@@ -214,7 +214,7 @@ RCT_EXPORT_METHOD(setLocalHashInfo:(NSString *)hash
|
|||||||
if (object && [object isKindOfClass:[NSDictionary class]]) {
|
if (object && [object isKindOfClass:[NSDictionary class]]) {
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
[defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]];
|
[defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]];
|
||||||
[defaults synchronize];
|
|
||||||
resolve(@true);
|
resolve(@true);
|
||||||
} else {
|
} else {
|
||||||
reject(@"json格式校验报错", nil, nil);
|
reject(@"json格式校验报错", nil, nil);
|
||||||
@@ -295,7 +295,7 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options
|
|||||||
newInfo[paramPackageVersion] = [RCTPushy packageVersion];
|
newInfo[paramPackageVersion] = [RCTPushy packageVersion];
|
||||||
[defaults setObject:newInfo forKey:keyPushyInfo];
|
[defaults setObject:newInfo forKey:keyPushyInfo];
|
||||||
|
|
||||||
[defaults synchronize];
|
|
||||||
resolve(@true);
|
resolve(@true);
|
||||||
}else{
|
}else{
|
||||||
reject(@"执行报错", nil, nil);
|
reject(@"执行报错", nil, nil);
|
||||||
@@ -329,8 +329,7 @@ RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(markSuccess:
|
RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
|
||||||
resolver:(RCTPromiseResolveBlock)resolve
|
|
||||||
rejecter:(RCTPromiseRejectBlock)reject)
|
rejecter:(RCTPromiseRejectBlock)reject)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -347,7 +346,7 @@ RCT_EXPORT_METHOD(markSuccess:
|
|||||||
[pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
|
[pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
|
||||||
}
|
}
|
||||||
[defaults setObject:pushyInfo forKey:keyPushyInfo];
|
[defaults setObject:pushyInfo forKey:keyPushyInfo];
|
||||||
[defaults synchronize];
|
|
||||||
|
|
||||||
// clear other package dir
|
// clear other package dir
|
||||||
[self clearInvalidFiles];
|
[self clearInvalidFiles];
|
||||||
@@ -610,7 +609,7 @@ RCT_EXPORT_METHOD(markSuccess:
|
|||||||
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
||||||
(const facebook::react::ObjCTurboModule::InitParams &)params
|
(const facebook::react::ObjCTurboModule::InitParams &)params
|
||||||
{
|
{
|
||||||
return std::make_shared<facebook::react::NativeUpdateSpecJSI>(params);
|
return std::make_shared<facebook::react::NativePushySpecJSI>(params);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-native-update",
|
"name": "react-native-update",
|
||||||
"version": "10.10.1",
|
"version": "10.13.2",
|
||||||
"description": "react-native hot update",
|
"description": "react-native hot update",
|
||||||
"main": "src/index",
|
"main": "src/index",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -45,7 +45,8 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
|
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.3"
|
"nanoid": "^3.3.3",
|
||||||
|
"react-native-url-polyfill": "^2.0.0"
|
||||||
},
|
},
|
||||||
"codegenConfig": {
|
"codegenConfig": {
|
||||||
"name": "RCTPushySpec",
|
"name": "RCTPushySpec",
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { CheckResult, PushyOptions, ProgressData, EventType } from './type';
|
import { CheckResult, PushyOptions, ProgressData, EventType } from './type';
|
||||||
import { log, testUrls } from './utils';
|
import { joinUrls, log, testUrls } from './utils';
|
||||||
import { EmitterSubscription, Platform } from 'react-native';
|
import { EmitterSubscription, Platform } from 'react-native';
|
||||||
import { PermissionsAndroid } from './permissions';
|
import { PermissionsAndroid } from './permissions';
|
||||||
import {
|
import {
|
||||||
@@ -17,8 +17,10 @@ import {
|
|||||||
const defaultServer = {
|
const defaultServer = {
|
||||||
main: 'https://update.react-native.cn/api',
|
main: 'https://update.react-native.cn/api',
|
||||||
backups: ['https://update.reactnative.cn/api'],
|
backups: ['https://update.reactnative.cn/api'],
|
||||||
queryUrl:
|
queryUrls: [
|
||||||
|
'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json',
|
||||||
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json',
|
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const empty = {};
|
const empty = {};
|
||||||
@@ -62,8 +64,7 @@ export class Pushy {
|
|||||||
setOptions = (options: Partial<PushyOptions>) => {
|
setOptions = (options: Partial<PushyOptions>) => {
|
||||||
for (const [key, value] of Object.entries(options)) {
|
for (const [key, value] of Object.entries(options)) {
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
// @ts-expect-error
|
(this.options as any)[key] = value;
|
||||||
this.options[key] = value;
|
|
||||||
if (key === 'logger') {
|
if (key === 'logger') {
|
||||||
if (isRolledBack) {
|
if (isRolledBack) {
|
||||||
this.report({
|
this.report({
|
||||||
@@ -124,7 +125,7 @@ export class Pushy {
|
|||||||
PushyModule.markSuccess();
|
PushyModule.markSuccess();
|
||||||
this.report({ type: 'markSuccess' });
|
this.report({ type: 'markSuccess' });
|
||||||
};
|
};
|
||||||
switchVersion = (hash: string) => {
|
switchVersion = async (hash: string) => {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'您调用了switchVersion方法,但是当前是开发环境,不会进行任何操作。',
|
'您调用了switchVersion方法,但是当前是开发环境,不会进行任何操作。',
|
||||||
@@ -134,11 +135,11 @@ export class Pushy {
|
|||||||
if (this.assertHash(hash) && !this.applyingUpdate) {
|
if (this.assertHash(hash) && !this.applyingUpdate) {
|
||||||
log('switchVersion: ' + hash);
|
log('switchVersion: ' + hash);
|
||||||
this.applyingUpdate = true;
|
this.applyingUpdate = true;
|
||||||
PushyModule.reloadUpdate({ hash });
|
return PushyModule.reloadUpdate({ hash });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
switchVersionLater = (hash: string) => {
|
switchVersionLater = async (hash: string) => {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
console.warn(
|
console.warn(
|
||||||
'您调用了switchVersionLater方法,但是当前是开发环境,不会进行任何操作。',
|
'您调用了switchVersionLater方法,但是当前是开发环境,不会进行任何操作。',
|
||||||
@@ -147,7 +148,7 @@ export class Pushy {
|
|||||||
}
|
}
|
||||||
if (this.assertHash(hash)) {
|
if (this.assertHash(hash)) {
|
||||||
log('switchVersionLater: ' + hash);
|
log('switchVersionLater: ' + hash);
|
||||||
PushyModule.setNeedUpdate({ hash });
|
return PushyModule.setNeedUpdate({ hash });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
checkUpdate = async (extra?: Record<string, any>) => {
|
checkUpdate = async (extra?: Record<string, any>) => {
|
||||||
@@ -161,6 +162,13 @@ export class Pushy {
|
|||||||
console.warn('web 端不支持热更新检查');
|
console.warn('web 端不支持热更新检查');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
this.options.beforeCheckUpdate &&
|
||||||
|
(await this.options.beforeCheckUpdate()) === false
|
||||||
|
) {
|
||||||
|
log('beforeCheckUpdate 返回 false, 忽略检查');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (
|
if (
|
||||||
this.lastRespJson &&
|
this.lastRespJson &&
|
||||||
@@ -170,7 +178,6 @@ export class Pushy {
|
|||||||
return await this.lastRespJson;
|
return await this.lastRespJson;
|
||||||
}
|
}
|
||||||
this.lastChecking = now;
|
this.lastChecking = now;
|
||||||
this.report({ type: 'checking' });
|
|
||||||
const fetchBody = {
|
const fetchBody = {
|
||||||
packageVersion,
|
packageVersion,
|
||||||
hash: currentVersion,
|
hash: currentVersion,
|
||||||
@@ -181,16 +188,21 @@ export class Pushy {
|
|||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
delete fetchBody.buildTime;
|
delete fetchBody.buildTime;
|
||||||
}
|
}
|
||||||
|
const body = JSON.stringify(fetchBody);
|
||||||
const fetchPayload = {
|
const fetchPayload = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
body: JSON.stringify(fetchBody),
|
body,
|
||||||
};
|
};
|
||||||
let resp;
|
let resp;
|
||||||
try {
|
try {
|
||||||
|
this.report({
|
||||||
|
type: 'checking',
|
||||||
|
message: this.options.appKey + ': ' + body,
|
||||||
|
});
|
||||||
resp = await fetch(this.getCheckUrl(), fetchPayload);
|
resp = await fetch(this.getCheckUrl(), fetchPayload);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.report({
|
this.report({
|
||||||
@@ -219,6 +231,8 @@ export class Pushy {
|
|||||||
|
|
||||||
const result: CheckResult = await this.lastRespJson;
|
const result: CheckResult = await this.lastRespJson;
|
||||||
|
|
||||||
|
log('checking result:', result);
|
||||||
|
|
||||||
if (resp.status !== 200) {
|
if (resp.status !== 200) {
|
||||||
this.report({
|
this.report({
|
||||||
type: 'errorChecking',
|
type: 'errorChecking',
|
||||||
@@ -233,9 +247,11 @@ export class Pushy {
|
|||||||
if (!server) {
|
if (!server) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
if (server.queryUrl) {
|
if (server.queryUrls) {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(server.queryUrl);
|
const resp = await Promise.race(
|
||||||
|
server.queryUrls.map(queryUrl => fetch(queryUrl)),
|
||||||
|
);
|
||||||
const remoteEndpoints = await resp.json();
|
const remoteEndpoints = await resp.json();
|
||||||
log('fetch endpoints:', remoteEndpoints);
|
log('fetch endpoints:', remoteEndpoints);
|
||||||
if (Array.isArray(remoteEndpoints)) {
|
if (Array.isArray(remoteEndpoints)) {
|
||||||
@@ -244,7 +260,7 @@ export class Pushy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
log('failed to fetch endpoints from: ', server.queryUrl);
|
log('failed to fetch endpoints from: ', server.queryUrls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return server.backups;
|
return server.backups;
|
||||||
@@ -255,16 +271,21 @@ export class Pushy {
|
|||||||
) => {
|
) => {
|
||||||
const {
|
const {
|
||||||
hash,
|
hash,
|
||||||
diffUrl: _diffUrl,
|
diff,
|
||||||
diffUrls,
|
pdiff,
|
||||||
pdiffUrl: _pdiffUrl,
|
full,
|
||||||
pdiffUrls,
|
paths = [],
|
||||||
updateUrl: _updateUrl,
|
|
||||||
updateUrls,
|
|
||||||
name,
|
name,
|
||||||
description,
|
description = '',
|
||||||
metaInfo,
|
metaInfo = '',
|
||||||
} = info;
|
} = info;
|
||||||
|
if (
|
||||||
|
this.options.beforeDownloadUpdate &&
|
||||||
|
(await this.options.beforeDownloadUpdate(info)) === false
|
||||||
|
) {
|
||||||
|
log('beforeDownloadUpdate 返回 false, 忽略下载');
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!info.update || !hash) {
|
if (!info.update || !hash) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -289,10 +310,10 @@ export class Pushy {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let succeeded = false;
|
let succeeded = '';
|
||||||
this.report({ type: 'downloading' });
|
this.report({ type: 'downloading' });
|
||||||
let lastError: any;
|
let lastError: any;
|
||||||
const diffUrl = (await testUrls(diffUrls)) || _diffUrl;
|
const diffUrl = await testUrls(joinUrls(paths, diff));
|
||||||
if (diffUrl) {
|
if (diffUrl) {
|
||||||
log('downloading diff');
|
log('downloading diff');
|
||||||
try {
|
try {
|
||||||
@@ -301,17 +322,17 @@ export class Pushy {
|
|||||||
hash,
|
hash,
|
||||||
originHash: currentVersion,
|
originHash: currentVersion,
|
||||||
});
|
});
|
||||||
succeeded = true;
|
succeeded = 'diff';
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
lastError = e;
|
lastError = e;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
succeeded = true;
|
succeeded = 'diff';
|
||||||
} else {
|
} else {
|
||||||
log(`diff error: ${e.message}, try pdiff`);
|
log(`diff error: ${e.message}, try pdiff`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const pdiffUrl = (await testUrls(pdiffUrls)) || _pdiffUrl;
|
const pdiffUrl = await testUrls(joinUrls(paths, pdiff));
|
||||||
if (!succeeded && pdiffUrl) {
|
if (!succeeded && pdiffUrl) {
|
||||||
log('downloading pdiff');
|
log('downloading pdiff');
|
||||||
try {
|
try {
|
||||||
@@ -319,29 +340,29 @@ export class Pushy {
|
|||||||
updateUrl: pdiffUrl,
|
updateUrl: pdiffUrl,
|
||||||
hash,
|
hash,
|
||||||
});
|
});
|
||||||
succeeded = true;
|
succeeded = 'pdiff';
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
lastError = e;
|
lastError = e;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
succeeded = true;
|
succeeded = 'pdiff';
|
||||||
} else {
|
} else {
|
||||||
log(`pdiff error: ${e.message}, try full patch`);
|
log(`pdiff error: ${e.message}, try full patch`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const updateUrl = (await testUrls(updateUrls)) || _updateUrl;
|
const fullUrl = await testUrls(joinUrls(paths, full));
|
||||||
if (!succeeded && updateUrl) {
|
if (!succeeded && fullUrl) {
|
||||||
log('downloading full patch');
|
log('downloading full patch');
|
||||||
try {
|
try {
|
||||||
await PushyModule.downloadFullUpdate({
|
await PushyModule.downloadFullUpdate({
|
||||||
updateUrl: updateUrl,
|
updateUrl: fullUrl,
|
||||||
hash,
|
hash,
|
||||||
});
|
});
|
||||||
succeeded = true;
|
succeeded = 'full';
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
lastError = e;
|
lastError = e;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
succeeded = true;
|
succeeded = 'full';
|
||||||
} else {
|
} else {
|
||||||
log(`full patch error: ${e.message}`);
|
log(`full patch error: ${e.message}`);
|
||||||
}
|
}
|
||||||
@@ -363,8 +384,13 @@ export class Pushy {
|
|||||||
throw lastError;
|
throw lastError;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
this.report({
|
||||||
|
type: 'downloadSuccess',
|
||||||
|
data: { newVersion: hash, diff: succeeded },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
log('downloaded hash:', hash);
|
log(`downloaded ${succeeded} hash:`, hash);
|
||||||
setLocalHashInfo(hash, {
|
setLocalHashInfo(hash, {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
@@ -7,22 +7,22 @@ const asyncNoop = () => Promise.resolve();
|
|||||||
|
|
||||||
export const defaultContext = {
|
export const defaultContext = {
|
||||||
checkUpdate: asyncNoop,
|
checkUpdate: asyncNoop,
|
||||||
switchVersion: noop,
|
switchVersion: asyncNoop,
|
||||||
switchVersionLater: noop,
|
switchVersionLater: asyncNoop,
|
||||||
markSuccess: noop,
|
markSuccess: noop,
|
||||||
dismissError: noop,
|
dismissError: noop,
|
||||||
downloadUpdate: asyncNoop,
|
downloadUpdate: asyncNoop,
|
||||||
downloadAndInstallApk: asyncNoop,
|
downloadAndInstallApk: asyncNoop,
|
||||||
getCurrentVersionInfo: () => Promise.resolve({}),
|
getCurrentVersionInfo: () => Promise.resolve({}),
|
||||||
parseTestPayload: () => Promise.resolve(false),
|
parseTestQrCode: () => false,
|
||||||
currentHash: '',
|
currentHash: '',
|
||||||
packageVersion: '',
|
packageVersion: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PushyContext = createContext<{
|
export const PushyContext = createContext<{
|
||||||
checkUpdate: () => Promise<void>;
|
checkUpdate: () => Promise<void>;
|
||||||
switchVersion: () => void;
|
switchVersion: () => Promise<void>;
|
||||||
switchVersionLater: () => void;
|
switchVersionLater: () => Promise<void>;
|
||||||
markSuccess: () => void;
|
markSuccess: () => void;
|
||||||
dismissError: () => void;
|
dismissError: () => void;
|
||||||
downloadUpdate: () => Promise<void>;
|
downloadUpdate: () => Promise<void>;
|
||||||
@@ -32,7 +32,7 @@ export const PushyContext = createContext<{
|
|||||||
description?: string;
|
description?: string;
|
||||||
metaInfo?: string;
|
metaInfo?: string;
|
||||||
}>;
|
}>;
|
||||||
parseTestPayload: (code: string) => Promise<boolean>;
|
parseTestQrCode: (code: string) => boolean;
|
||||||
currentHash: string;
|
currentHash: string;
|
||||||
packageVersion: string;
|
packageVersion: string;
|
||||||
client?: Pushy;
|
client?: Pushy;
|
||||||
|
@@ -4,9 +4,7 @@ const {
|
|||||||
version: v,
|
version: v,
|
||||||
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
||||||
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
||||||
const isTurboModuleEnabled =
|
const isTurboModuleEnabled = (global as any).__turboModuleProxy != null;
|
||||||
// @ts-expect-error
|
|
||||||
global.__turboModuleProxy != null;
|
|
||||||
|
|
||||||
export const PushyModule =
|
export const PushyModule =
|
||||||
Platform.OS === 'web'
|
Platform.OS === 'web'
|
||||||
|
@@ -21,6 +21,7 @@ import {
|
|||||||
} from './core';
|
} from './core';
|
||||||
import { CheckResult, ProgressData, PushyTestPayload } from './type';
|
import { CheckResult, ProgressData, PushyTestPayload } from './type';
|
||||||
import { PushyContext } from './context';
|
import { PushyContext } from './context';
|
||||||
|
import { URL } from 'react-native-url-polyfill';
|
||||||
|
|
||||||
export const PushyProvider = ({
|
export const PushyProvider = ({
|
||||||
client,
|
client,
|
||||||
@@ -72,18 +73,18 @@ export const PushyProvider = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const switchVersion = useCallback(
|
const switchVersion = useCallback(
|
||||||
(info: CheckResult | undefined = updateInfoRef.current) => {
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
||||||
if (info && info.hash) {
|
if (info && info.hash) {
|
||||||
client.switchVersion(info.hash);
|
return client.switchVersion(info.hash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[client],
|
[client],
|
||||||
);
|
);
|
||||||
|
|
||||||
const switchVersionLater = useCallback(
|
const switchVersionLater = useCallback(
|
||||||
(info: CheckResult | undefined = updateInfoRef.current) => {
|
async (info: CheckResult | undefined = updateInfoRef.current) => {
|
||||||
if (info && info.hash) {
|
if (info && info.hash) {
|
||||||
client.switchVersionLater(info.hash);
|
return client.switchVersionLater(info.hash);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[client],
|
[client],
|
||||||
@@ -146,7 +147,7 @@ export const PushyProvider = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const checkUpdate = useCallback(
|
const checkUpdate = useCallback(
|
||||||
async (extra?: Record<string, any>) => {
|
async ({ extra }: { extra?: Record<string, any> } | undefined = {}) => {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
if (lastChecking.current && now - lastChecking.current < 1000) {
|
if (lastChecking.current && now - lastChecking.current < 1000) {
|
||||||
return;
|
return;
|
||||||
@@ -263,30 +264,65 @@ export const PushyProvider = ({
|
|||||||
}, [checkUpdate, options, dismissError, markSuccess]);
|
}, [checkUpdate, options, dismissError, markSuccess]);
|
||||||
|
|
||||||
const parseTestPayload = useCallback(
|
const parseTestPayload = useCallback(
|
||||||
async (code: string) => {
|
(payload: PushyTestPayload) => {
|
||||||
let payload: PushyTestPayload;
|
if (payload && payload.type && payload.type.startsWith('__rnPushy')) {
|
||||||
try {
|
const logger = options.logger || (() => {});
|
||||||
payload = JSON.parse(code);
|
options.logger = ({ type, data }) => {
|
||||||
} catch {
|
logger({ type, data });
|
||||||
return false;
|
Alert.alert(type, JSON.stringify(data));
|
||||||
}
|
};
|
||||||
if (payload && payload.type) {
|
|
||||||
if (payload.type === '__rnPushyVersionHash') {
|
if (payload.type === '__rnPushyVersionHash') {
|
||||||
await checkUpdate({ toHash: payload.data });
|
checkUpdate({ extra: { toHash: payload.data } }).then(() => {
|
||||||
if (updateInfoRef.current && updateInfoRef.current.upToDate) {
|
if (updateInfoRef.current && updateInfoRef.current.upToDate) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
'提示',
|
'提示',
|
||||||
'当前尚未检测到更新版本,如果是首次扫码,请等待服务器端生成补丁包后再试(约10秒)',
|
'当前尚未检测到更新版本,如果是首次扫码,请等待服务器端生成补丁包后再试(约10秒)',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return true;
|
options.logger = logger;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
[checkUpdate],
|
[checkUpdate, options],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const parseTestQrCode = useCallback(
|
||||||
|
(code: string | PushyTestPayload) => {
|
||||||
|
try {
|
||||||
|
const payload = typeof code === 'string' ? JSON.parse(code) : code;
|
||||||
|
return parseTestPayload(payload);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[parseTestPayload],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const parseLinking = (url: string | null) => {
|
||||||
|
if (!url) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const params = new URL(url).searchParams;
|
||||||
|
const payload = {
|
||||||
|
type: params.get('type'),
|
||||||
|
data: params.get('data'),
|
||||||
|
};
|
||||||
|
parseTestPayload(payload);
|
||||||
|
};
|
||||||
|
|
||||||
|
Linking.getInitialURL().then(parseLinking);
|
||||||
|
const linkingListener = Linking.addEventListener('url', ({ url }) =>
|
||||||
|
parseLinking(url),
|
||||||
|
);
|
||||||
|
return () => {
|
||||||
|
linkingListener.remove();
|
||||||
|
};
|
||||||
|
}, [parseTestPayload]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PushyContext.Provider
|
<PushyContext.Provider
|
||||||
value={{
|
value={{
|
||||||
@@ -304,7 +340,7 @@ export const PushyProvider = ({
|
|||||||
progress,
|
progress,
|
||||||
downloadAndInstallApk,
|
downloadAndInstallApk,
|
||||||
getCurrentVersionInfo,
|
getCurrentVersionInfo,
|
||||||
parseTestPayload,
|
parseTestQrCode,
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
</PushyContext.Provider>
|
</PushyContext.Provider>
|
||||||
|
17
src/type.ts
17
src/type.ts
@@ -7,12 +7,10 @@ export interface CheckResult {
|
|||||||
hash?: string;
|
hash?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
metaInfo?: string;
|
metaInfo?: string;
|
||||||
pdiffUrl?: string;
|
pdiff?: string;
|
||||||
pdiffUrls?: string[];
|
diff?: string;
|
||||||
diffUrl?: string;
|
full?: string;
|
||||||
diffUrls?: string[];
|
paths?: string[];
|
||||||
updateUrl?: string;
|
|
||||||
updateUrls?: string[];
|
|
||||||
paused?: 'app' | 'package';
|
paused?: 'app' | 'package';
|
||||||
message?: string;
|
message?: string;
|
||||||
}
|
}
|
||||||
@@ -28,6 +26,7 @@ export type EventType =
|
|||||||
| 'errorChecking'
|
| 'errorChecking'
|
||||||
| 'checking'
|
| 'checking'
|
||||||
| 'downloading'
|
| 'downloading'
|
||||||
|
| 'downloadSuccess'
|
||||||
| 'errorUpdate'
|
| 'errorUpdate'
|
||||||
| 'markSuccess'
|
| 'markSuccess'
|
||||||
| 'downloadingApk'
|
| 'downloadingApk'
|
||||||
@@ -62,7 +61,7 @@ export type UpdateEventsLogger = ({
|
|||||||
export interface PushyServerConfig {
|
export interface PushyServerConfig {
|
||||||
main: string;
|
main: string;
|
||||||
backups?: string[];
|
backups?: string[];
|
||||||
queryUrl?: string;
|
queryUrls?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PushyOptions {
|
export interface PushyOptions {
|
||||||
@@ -80,9 +79,11 @@ export interface PushyOptions {
|
|||||||
dismissErrorAfter?: number;
|
dismissErrorAfter?: number;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
throwError?: boolean;
|
throwError?: boolean;
|
||||||
|
beforeCheckUpdate?: () => Promise<boolean>;
|
||||||
|
beforeDownloadUpdate?: (info: CheckResult) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PushyTestPayload {
|
export interface PushyTestPayload {
|
||||||
type: '__rnPushyVersionHash';
|
type: '__rnPushyVersionHash' | string | null;
|
||||||
data: any;
|
data: any;
|
||||||
}
|
}
|
||||||
|
11
src/utils.ts
11
src/utils.ts
@@ -31,9 +31,18 @@ const ping =
|
|||||||
|
|
||||||
const canUseGoogle = ping('https://www.google.com');
|
const canUseGoogle = ping('https://www.google.com');
|
||||||
|
|
||||||
|
export function joinUrls(paths: string[], fileName?: string) {
|
||||||
|
if (fileName) {
|
||||||
|
return paths.map(path => 'https://' + path + '/' + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const testUrls = async (urls?: string[]) => {
|
export const testUrls = async (urls?: string[]) => {
|
||||||
if (!urls?.length || (await canUseGoogle)) {
|
if (!urls?.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (await canUseGoogle) {
|
||||||
|
return urls[0];
|
||||||
|
}
|
||||||
return Promise.race(urls.map(ping)).catch(() => null);
|
return Promise.race(urls.map(ping)).catch(() => null);
|
||||||
};
|
};
|
||||||
|
23
yarn.lock
23
yarn.lock
@@ -3198,7 +3198,7 @@ buffer-indexof-polyfill@~1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
|
resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
|
||||||
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
|
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
|
||||||
|
|
||||||
buffer@^5.5.0:
|
buffer@^5.4.3, buffer@^5.5.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||||
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||||
@@ -8604,6 +8604,13 @@ react-is@^17.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||||
|
|
||||||
|
react-native-url-polyfill@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
|
||||||
|
integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url-without-unicode "8.0.0-3"
|
||||||
|
|
||||||
react-native@0.73:
|
react-native@0.73:
|
||||||
version "0.73.2"
|
version "0.73.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.2.tgz#74ee163c8189660d41d1da6560411da7ce41a608"
|
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.2.tgz#74ee163c8189660d41d1da6560411da7ce41a608"
|
||||||
@@ -10174,6 +10181,11 @@ webidl-conversions@^3.0.0:
|
|||||||
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||||
|
|
||||||
|
webidl-conversions@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
|
||||||
|
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
|
||||||
|
|
||||||
whatwg-fetch@^3.0.0:
|
whatwg-fetch@^3.0.0:
|
||||||
version "3.6.19"
|
version "3.6.19"
|
||||||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
|
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
|
||||||
@@ -10184,6 +10196,15 @@ whatwg-fetch@^3.4.1:
|
|||||||
resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
|
resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
|
||||||
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
|
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
|
||||||
|
|
||||||
|
whatwg-url-without-unicode@8.0.0-3:
|
||||||
|
version "8.0.0-3"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
|
||||||
|
integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.4.3"
|
||||||
|
punycode "^2.1.1"
|
||||||
|
webidl-conversions "^5.0.0"
|
||||||
|
|
||||||
whatwg-url@^5.0.0:
|
whatwg-url@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||||
|
Reference in New Issue
Block a user