1
0
mirror of https://gitcode.com/gh_mirrors/re/react-native-pushy.git synced 2025-09-16 13:01:38 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Compare commits

...

25 Commits

Author SHA1 Message Date
sunnylqm
6d980a4c04 v10.11.6 2024-08-06 13:13:05 +08:00
sunnylqm
084fbf35ee fix typo 2024-08-06 13:12:32 +08:00
sunnylqm
d666e8c0f3 v10.11.5 2024-08-01 11:00:39 +08:00
sunnylqm
5e89fb4a25 v10.11.4 2024-07-31 18:06:05 +08:00
sunnylqm
ab01b6010a update example 2024-07-30 09:42:33 +08:00
sunnylqm
92bc830d98 update example 2024-07-29 23:25:33 +08:00
sunnylqm
7531e8ca3a v10.11.3 2024-07-29 22:40:55 +08:00
sunnylqm
b2305cff3f v10.11.2 2024-07-29 00:57:30 +08:00
sunnylqm
c5cdb6031b v10.11.1 2024-07-29 00:45:30 +08:00
sunnylqm
20ebf8979e fix url params 2024-07-29 00:45:10 +08:00
sunnylqm
3929fc2f8e add crunchPngs false 2024-07-28 22:22:21 +08:00
sunnylqm
31ee269717 fix qrcode 2024-07-28 22:20:33 +08:00
sunnylqm
adcd57b6b5 update example 2024-07-28 21:57:33 +08:00
sunnylqm
c595e4e54a v10.11.0 2024-07-28 21:30:26 +08:00
sunnylqm
4f80f96a8d parseTestPayload 2024-07-28 21:26:21 +08:00
Sunny Luo
a77c3c85f3 Update endpoints.json 2024-07-27 22:06:59 +08:00
sunnylqm
2357a0b78d update queryurls 2024-07-27 17:37:54 +08:00
sunnylqm
88bacdfb15 v10.10.3 2024-07-27 17:37:43 +08:00
sunnylqm
90fee03c45 v10.10.2 2024-07-27 16:55:36 +08:00
sunnylqm
7243512d3c v10.10.2 2024-07-27 16:54:24 +08:00
sunnylqm
11b383d10b v10.10.1 2024-07-25 23:45:12 +08:00
sunnylqm
af65b2660c update example 2024-07-25 22:56:44 +08:00
sunnylqm
28b8e122af v10.10.0 2024-07-25 22:52:18 +08:00
sunnylqm
0fdb33ab10 v10.9.0 2024-07-25 22:05:18 +08:00
sunnylqm
a5893d8022 feat: extra param for checkupdate 2024-07-25 22:04:52 +08:00
17 changed files with 313 additions and 117 deletions

View File

@@ -94,7 +94,7 @@ apply from: "../../node_modules/react-native/react.gradle"
* Upload all the APKs to the Play Store and people will download
* 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.
@@ -141,7 +141,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
versionName "2.0"
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
@@ -237,6 +237,7 @@ android {
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
crunchPngs false
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

View File

@@ -2,6 +2,8 @@
package="com.awesomeproject">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".MainApplication"
@@ -19,8 +21,14 @@
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</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>
</application>

View File

@@ -5,10 +5,11 @@ import org.apache.tools.ant.taskdefs.condition.Os
buildscript {
ext {
buildToolsVersion = "31.0.0"
minSdkVersion = 21
minSdkVersion = 23
compileSdkVersion = 31
targetSdkVersion = 31
kotlinVersion = '1.6.10'
kotlinVersion = '1.7.20'
kotlin_version = '1.7.20'
if (System.properties['os.arch'] == "aarch64") {
// For M1 Users we need to use the NDK 24 which added support for aarch64

View File

@@ -53,5 +53,10 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSCameraUsageDescription</key>
<string>For taking photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>For saving photos</string>
</dict>
</plist>

View File

@@ -222,17 +222,17 @@ PODS:
- glog
- react-native-safe-area-context (4.8.2):
- React-Core
- react-native-update (10.7.1):
- react-native-update (10.10.0):
- React
- React-Core
- react-native-update/HDiffPatch (= 10.7.1)
- react-native-update/RCTPushy (= 10.7.1)
- react-native-update/HDiffPatch (= 10.10.0)
- react-native-update/RCTPushy (= 10.10.0)
- SSZipArchive
- react-native-update/HDiffPatch (10.7.1):
- react-native-update/HDiffPatch (10.10.0):
- React
- React-Core
- SSZipArchive
- react-native-update/RCTPushy (10.7.1):
- react-native-update/RCTPushy (10.10.0):
- React
- React-Core
- SSZipArchive
@@ -302,6 +302,8 @@ PODS:
- React-jsi (= 0.69.8)
- React-logger (= 0.69.8)
- React-perflogger (= 0.69.8)
- ReactNativeCameraKit (14.0.0-beta9):
- React-Core
- RNVectorIcons (10.0.3):
- React-Core
- SSZipArchive (2.4.3)
@@ -342,6 +344,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- ReactNativeCameraKit (from `../node_modules/react-native-camera-kit`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -417,6 +420,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
ReactNativeCameraKit:
:path: "../node_modules/react-native-camera-kit"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
Yoga:
@@ -444,7 +449,7 @@ SPEC CHECKSUMS:
React-jsinspector: 0eda09e9cf22bbb5dbb1d23143b03a31acf37d67
React-logger: 5997ab008583826c10ffe4e1ff990363e975639d
react-native-safe-area-context: 0ee144a6170530ccc37a0fd9388e28d06f516a89
react-native-update: 04844fca9567508fa79649e23e7209904d9d7a5a
react-native-update: a7f136a3c87183b13c7ff5c4f9d2b614930968ad
React-perflogger: ad1416a715d86b32f456e5d0aed99c3b52f1de37
React-RCTActionSheet: cbf7c6a953982562418ee72a1084ff7b9447b558
React-RCTAnimation: 33df3e25824dd7313edec28dded2745542f9352b
@@ -457,6 +462,7 @@ SPEC CHECKSUMS:
React-RCTVibration: 5462287ee85304ba1a00474665ab292e63a41663
React-runtimeexecutor: 9df680f18497367bcf5c15b6b6406c0f2dfa2b6a
ReactCommon: c10f046f3ef8561e7c8e7e9b9dae2ecc9ffc48ef
ReactNativeCameraKit: 4bec78d688adcd68772af2834d5c30a6a8e2a384
RNVectorIcons: bc7ee28cadf39c77a49232a14738dfce690f66cd
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
Yoga: d3820731e0ca3a4933f061ad29defaf7726e3251

View File

@@ -9,16 +9,18 @@
"test": "jest",
"test:e2e": "detox test --configuration android.emu.debug",
"lint": "eslint .",
"postinstall": "patch-package"
"postinstall": "patch-package",
"apk": "cd android && ./gradlew assembleRelease"
},
"dependencies": {
"patch-package": "^6.5.1",
"postinstall-postinstall": "^2.1.0",
"react": "18.0.0",
"react-native": "0.69.8",
"react-native-camera-kit": "^14.0.0-beta15",
"react-native-paper": "^5.12.1",
"react-native-safe-area-context": "^4.8.2",
"react-native-update": "^10.7.1",
"react-native-update": "^10.11.3",
"react-native-vector-icons": "^10.0.3"
},
"devDependencies": {

View File

@@ -1,6 +1,6 @@
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable react-native/no-inline-styles */
import React, {useState} from 'react';
import React, {useRef, useState} from 'react';
import {
StyleSheet,
Platform,
@@ -10,7 +10,16 @@ import {
Image,
Switch,
} from 'react-native';
import {Icon, PaperProvider, Snackbar, Banner} from 'react-native-paper';
import {
Icon,
PaperProvider,
Snackbar,
Banner,
Button,
Modal,
Portal,
} from 'react-native-paper';
import {Camera} from 'react-native-camera-kit';
import TestConsole from './TestConsole';
@@ -28,6 +37,7 @@ function App() {
updateInfo,
packageVersion,
currentHash,
parseTestQrCode,
progress: {received, total} = {},
} = usePushy();
const [useDefaultAlert, setUseDefaultAlert] = useState(true);
@@ -36,6 +46,8 @@ function App() {
const [showUpdateSnackbar, setShowUpdateSnackbar] = useState(false);
const snackbarVisible =
!useDefaultAlert && showUpdateSnackbar && updateInfo?.update;
const [showCamera, setShowCamera] = useState(false);
const lastParsedCode = useRef('');
return (
<View style={styles.container}>
@@ -55,6 +67,30 @@ function App() {
}}
/>
</View>
<Button onPress={() => setShowCamera(true)}></Button>
<Portal>
<Modal visible={showCamera} onDismiss={() => setShowCamera(false)}>
<Camera
style={{minHeight: 320}}
scanBarcode={true}
onReadCode={({nativeEvent: {codeStringValue}}) => {
// 防止重复扫码
if (lastParsedCode.current === codeStringValue) {
return;
}
lastParsedCode.current = codeStringValue;
setTimeout(() => {
lastParsedCode.current = '';
}, 1000);
setShowCamera(false);
parseTestQrCode(codeStringValue);
}} // 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
laserColor="red" // (default red) optional, color of laser in scanner frame
frameColor="white" // (default white) optional, color of border of scanner frame
/>
</Modal>
</Portal>
<Image
resizeMode={'contain'}
source={require('./assets/shezhi.png')}

View File

@@ -2123,7 +2123,7 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^5.5.0:
buffer@^5.4.3, buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
@@ -6159,7 +6159,7 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
punycode@^2.1.0:
punycode@^2.1.0, punycode@^2.1.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
@@ -6202,6 +6202,11 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-native-camera-kit@^14.0.0-beta15:
version "14.0.0-beta9"
resolved "https://registry.yarnpkg.com/react-native-camera-kit/-/react-native-camera-kit-14.0.0-beta9.tgz#fa00aceeedd4fbc7ab82d94cb7e64de471165554"
integrity sha512-OPRyJMmJibfVxrMvpbDgprhsrKlKWGvtLgkV+tY97HnEmTuW4in7qx/RC5wMKMZDwgBxgLtFhO7rYAMylIpH2A==
react-native-codegen@^0.69.2:
version "0.69.2"
resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.69.2.tgz#e33ac3b1486de59ddae687b731ddbfcef8af0e4e"
@@ -6231,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"
integrity sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==
react-native-update@^10.7.1:
version "10.7.1"
resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.7.1.tgz#f89075b69b4a397ce6d3457837018fb6cfabe0ab"
integrity sha512-Lru/8qunNjggvjzfe6uzWi4HWsFmNjtwdLXC3lD+1hWQpJ8ln5bwQlYoXyz0n8GwNJiS8Z/w8oPXVxs323ls3g==
react-native-update@^10.11.3:
version "10.11.3"
resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.11.3.tgz#5fa44fdd12514eb5e7901a5d664f00fd082d6774"
integrity sha512-adI3sly0yFt1DfaPqICJ9VwzUoa/XAngv/N7SnICkLxO3jgccBgy0OrXDBxRn43Zeumdq40Z+ADTE5qrY4BWAw==
dependencies:
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:
version "10.0.3"
@@ -7485,11 +7498,25 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
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:
version "3.6.20"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
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:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"

View File

@@ -8,7 +8,7 @@
### 优势
1. 基于阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。
1. 对中国用户使用阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。对国外用户则智能分流至 cloudflare同样享受高速更新服务。
2. 基于 bsdiff/hdiff 算法创建的**超小更新包**,通常版本迭代后在几十 KB 级别(其他全量热更新服务所需流量通常在几十 MB 级别)。
3. 始终跟进 RN 最新正式版本,第一时间提供支持。支持 hermes 字节码格式。支持新架构。
4. 跨越多个版本进行更新时,只需要下载**一个更新包**,不需要逐版本依次更新。
@@ -33,4 +33,3 @@ $ yarn start
本组件由[React Native 中文网](https://reactnative.cn/)独家发布,如有定制需求可以[联系我们](https://reactnative.cn/about.html#content)。
关于此插件发现任何问题,可以前往[Issues](https://github.com/reactnativecn/react-native-pushy/issues)发帖提问。

View File

@@ -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"]

View File

@@ -610,7 +610,7 @@ RCT_EXPORT_METHOD(markSuccess:
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeUpdateSpecJSI>(params);
return std::make_shared<facebook::react::NativePushySpecJSI>(params);
}
#endif

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-update",
"version": "10.8.0",
"version": "10.11.6",
"description": "react-native hot update",
"main": "src/index",
"scripts": {
@@ -45,7 +45,8 @@
},
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
"dependencies": {
"nanoid": "^3.3.3"
"nanoid": "^3.3.3",
"react-native-url-polyfill": "^2.0.0"
},
"codegenConfig": {
"name": "RCTPushySpec",

View File

@@ -17,8 +17,10 @@ import {
const defaultServer = {
main: 'https://update.react-native.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',
],
};
const empty = {};
@@ -150,7 +152,7 @@ export class Pushy {
PushyModule.setNeedUpdate({ hash });
}
};
checkUpdate = async () => {
checkUpdate = async (extra?: Record<string, any>) => {
if (__DEV__ && !this.options.debug) {
console.info(
'您当前处于开发环境且未启用 debug不会进行热更检查。如需在开发环境中调试热更请在 client 中设置 debug 为 true',
@@ -170,26 +172,31 @@ export class Pushy {
return await this.lastRespJson;
}
this.lastChecking = now;
this.report({ type: 'checking' });
const fetchBody = {
packageVersion,
hash: currentVersion,
buildTime,
cInfo,
...extra,
};
if (__DEV__) {
delete fetchBody.buildTime;
}
const body = JSON.stringify(fetchBody);
const fetchPayload = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(fetchBody),
body,
};
let resp;
try {
this.report({
type: 'checking',
message: this.options.appKey + ': ' + body,
});
resp = await fetch(this.getCheckUrl(), fetchPayload);
} catch (e: any) {
this.report({
@@ -218,6 +225,8 @@ export class Pushy {
const result: CheckResult = await this.lastRespJson;
log('checking result:', result);
if (resp.status !== 200) {
this.report({
type: 'errorChecking',
@@ -232,9 +241,11 @@ export class Pushy {
if (!server) {
return [];
}
if (server.queryUrl) {
if (server.queryUrls) {
try {
const resp = await fetch(server.queryUrl);
const resp = await Promise.race(
server.queryUrls.map(queryUrl => fetch(queryUrl)),
);
const remoteEndpoints = await resp.json();
log('fetch endpoints:', remoteEndpoints);
if (Array.isArray(remoteEndpoints)) {
@@ -243,7 +254,7 @@ export class Pushy {
);
}
} catch (e: any) {
log('failed to fetch endpoints from: ', server.queryUrl);
log('failed to fetch endpoints from: ', server.queryUrls);
}
}
return server.backups;
@@ -288,7 +299,7 @@ export class Pushy {
},
);
}
let succeeded = false;
let succeeded = '';
this.report({ type: 'downloading' });
let lastError: any;
const diffUrl = (await testUrls(diffUrls)) || _diffUrl;
@@ -300,11 +311,11 @@ export class Pushy {
hash,
originHash: currentVersion,
});
succeeded = true;
succeeded = 'diff';
} catch (e: any) {
lastError = e;
if (__DEV__) {
succeeded = true;
succeeded = 'diff';
} else {
log(`diff error: ${e.message}, try pdiff`);
}
@@ -318,11 +329,11 @@ export class Pushy {
updateUrl: pdiffUrl,
hash,
});
succeeded = true;
succeeded = 'pdiff';
} catch (e: any) {
lastError = e;
if (__DEV__) {
succeeded = true;
succeeded = 'pdiff';
} else {
log(`pdiff error: ${e.message}, try full patch`);
}
@@ -336,11 +347,11 @@ export class Pushy {
updateUrl: updateUrl,
hash,
});
succeeded = true;
succeeded = 'full';
} catch (e: any) {
lastError = e;
if (__DEV__) {
succeeded = true;
succeeded = 'full';
} else {
log(`full patch error: ${e.message}`);
}
@@ -362,8 +373,13 @@ export class Pushy {
throw lastError;
}
return;
} else {
this.report({
type: 'downloadSuccess',
data: { newVersion: hash, diff: succeeded },
});
}
log('downloaded hash:', hash);
log(`downloaded ${succeeded} hash:`, hash);
setLocalHashInfo(hash, {
name,
description,

View File

@@ -14,6 +14,7 @@ export const defaultContext = {
downloadUpdate: asyncNoop,
downloadAndInstallApk: asyncNoop,
getCurrentVersionInfo: () => Promise.resolve({}),
parseTestQrCode: () => false,
currentHash: '',
packageVersion: '',
};
@@ -31,6 +32,7 @@ export const PushyContext = createContext<{
description?: string;
metaInfo?: string;
}>;
parseTestQrCode: (code: string) => boolean;
currentHash: string;
packageVersion: string;
client?: Pushy;

View File

@@ -19,8 +19,9 @@ import {
packageVersion,
getCurrentVersionInfo,
} from './core';
import { CheckResult, ProgressData } from './type';
import { CheckResult, ProgressData, PushyTestPayload } from './type';
import { PushyContext } from './context';
import { URL } from 'react-native-url-polyfill';
export const PushyProvider = ({
client,
@@ -145,81 +146,84 @@ export const PushyProvider = ({
[client],
);
const checkUpdate = useCallback(async () => {
const now = Date.now();
if (lastChecking.current && now - lastChecking.current < 1000) {
return;
}
lastChecking.current = now;
let info: CheckResult;
try {
info = await client.checkUpdate();
} catch (e: any) {
setLastError(e);
alertError('更新检查失败', e.message);
throwErrorIfEnabled(e);
return;
}
if (!info) {
return;
}
updateInfoRef.current = info;
setUpdateInfo(info);
if (info.expired) {
const { downloadUrl } = info;
if (downloadUrl) {
if (options.updateStrategy === 'silentAndNow') {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
const checkUpdate = useCallback(
async ({ extra }: { extra?: Record<string, any> } | undefined = {}) => {
const now = Date.now();
if (lastChecking.current && now - lastChecking.current < 1000) {
return;
}
lastChecking.current = now;
let info: CheckResult;
try {
info = await client.checkUpdate(extra);
} catch (e: any) {
setLastError(e);
alertError('更新检查失败', e.message);
throwErrorIfEnabled(e);
return;
}
if (!info) {
return;
}
updateInfoRef.current = info;
setUpdateInfo(info);
if (info.expired) {
const { downloadUrl } = info;
if (downloadUrl) {
if (options.updateStrategy === 'silentAndNow') {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
return;
}
return;
alertUpdate('提示', '您的应用版本已更新,点击更新下载安装新版本', [
{
text: '更新',
onPress: () => {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
},
},
]);
}
alertUpdate('提示', '您的应用版本已更新,点击更新下载安装新版本', [
{
text: '更新',
onPress: () => {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
} else if (info.update) {
if (
options.updateStrategy === 'silentAndNow' ||
options.updateStrategy === 'silentAndLater'
) {
return downloadUpdate(info);
}
alertUpdate(
'提示',
'检查到新的版本' + info.name + ',是否下载?\n' + info.description,
[
{ text: '取消', style: 'cancel' },
{
text: '确定',
style: 'default',
onPress: () => {
downloadUpdate();
},
},
},
]);
],
);
}
} else if (info.update) {
if (
options.updateStrategy === 'silentAndNow' ||
options.updateStrategy === 'silentAndLater'
) {
return downloadUpdate(info);
}
alertUpdate(
'提示',
'检查到新的版本' + info.name + ',是否下载?\n' + info.description,
[
{ text: '取消', style: 'cancel' },
{
text: '确定',
style: 'default',
onPress: () => {
downloadUpdate();
},
},
],
);
}
}, [
client,
alertError,
throwErrorIfEnabled,
options.updateStrategy,
alertUpdate,
downloadAndInstallApk,
downloadUpdate,
]);
},
[
client,
alertError,
throwErrorIfEnabled,
options.updateStrategy,
alertUpdate,
downloadAndInstallApk,
downloadUpdate,
],
);
const markSuccess = client.markSuccess;
@@ -259,6 +263,66 @@ export const PushyProvider = ({
};
}, [checkUpdate, options, dismissError, markSuccess]);
const parseTestPayload = useCallback(
(payload: PushyTestPayload) => {
if (payload && payload.type && payload.type.startsWith('__rnPushy')) {
const logger = options.logger || (() => {});
options.logger = ({ type, data }) => {
logger({ type, data });
Alert.alert(type, JSON.stringify(data));
};
if (payload.type === '__rnPushyVersionHash') {
checkUpdate({ extra: { toHash: payload.data } }).then(() => {
if (updateInfoRef.current && updateInfoRef.current.upToDate) {
Alert.alert(
'提示',
'当前尚未检测到更新版本如果是首次扫码请等待服务器端生成补丁包后再试约10秒',
);
}
options.logger = logger;
});
}
return true;
}
return false;
},
[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 (
<PushyContext.Provider
value={{
@@ -276,6 +340,7 @@ export const PushyProvider = ({
progress,
downloadAndInstallApk,
getCurrentVersionInfo,
parseTestQrCode,
}}>
{children}
</PushyContext.Provider>

View File

@@ -28,6 +28,7 @@ export type EventType =
| 'errorChecking'
| 'checking'
| 'downloading'
| 'downloadSuccess'
| 'errorUpdate'
| 'markSuccess'
| 'downloadingApk'
@@ -62,7 +63,7 @@ export type UpdateEventsLogger = ({
export interface PushyServerConfig {
main: string;
backups?: string[];
queryUrl?: string;
queryUrls?: string[];
}
export interface PushyOptions {
@@ -81,3 +82,8 @@ export interface PushyOptions {
debug?: boolean;
throwError?: boolean;
}
export interface PushyTestPayload {
type: '__rnPushyVersionHash' | string | null;
data: any;
}

View File

@@ -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"
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
buffer@^5.5.0:
buffer@^5.4.3, buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
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"
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:
version "0.73.2"
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"
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:
version "3.6.19"
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"
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:
version "5.0.0"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"