@zero-bits/react-native-hot-update 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +159 -0
- package/es/constants.d.ts +20 -0
- package/es/constants.js +20 -0
- package/es/index.d.ts +4 -0
- package/es/index.js +3 -0
- package/es/initialize.d.ts +14 -0
- package/es/initialize.js +32 -0
- package/es/updateProvider.d.ts +75 -0
- package/es/updateProvider.js +74 -0
- package/es/updateState.d.ts +25 -0
- package/es/updateState.js +166 -0
- package/es/usePushyUpdate.d.ts +17 -0
- package/es/usePushyUpdate.js +108 -0
- package/es/widget/animated.overlay.d.ts +12 -0
- package/es/widget/animated.overlay.js +96 -0
- package/es/widget/content.widget.d.ts +5 -0
- package/es/widget/content.widget.js +55 -0
- package/es/widget/description.widget.d.ts +5 -0
- package/es/widget/description.widget.js +33 -0
- package/es/widget/download.modal.widget.d.ts +5 -0
- package/es/widget/download.modal.widget.js +130 -0
- package/es/widget/footer.widget.d.ts +5 -0
- package/es/widget/footer.widget.js +153 -0
- package/es/widget/title.widget.d.ts +5 -0
- package/es/widget/title.widget.js +27 -0
- package/es/widget/update.modal.widget.d.ts +5 -0
- package/es/widget/update.modal.widget.js +50 -0
- package/lib/constants.d.ts +20 -0
- package/lib/constants.js +26 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +36 -0
- package/lib/initialize.d.ts +14 -0
- package/lib/initialize.js +38 -0
- package/lib/updateProvider.d.ts +75 -0
- package/lib/updateProvider.js +83 -0
- package/lib/updateState.d.ts +25 -0
- package/lib/updateState.js +176 -0
- package/lib/usePushyUpdate.d.ts +17 -0
- package/lib/usePushyUpdate.js +114 -0
- package/lib/widget/animated.overlay.d.ts +12 -0
- package/lib/widget/animated.overlay.js +104 -0
- package/lib/widget/content.widget.d.ts +5 -0
- package/lib/widget/content.widget.js +63 -0
- package/lib/widget/description.widget.d.ts +5 -0
- package/lib/widget/description.widget.js +41 -0
- package/lib/widget/download.modal.widget.d.ts +5 -0
- package/lib/widget/download.modal.widget.js +138 -0
- package/lib/widget/footer.widget.d.ts +5 -0
- package/lib/widget/footer.widget.js +161 -0
- package/lib/widget/title.widget.d.ts +5 -0
- package/lib/widget/title.widget.js +35 -0
- package/lib/widget/update.modal.widget.d.ts +5 -0
- package/lib/widget/update.modal.widget.js +59 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# react-native-hot-update
|
|
2
|
+
|
|
3
|
+
一个基于 `react-native-update` (Pushy) 深度封装、开箱即用的 React Native 热更新高阶 UI 组件库。
|
|
4
|
+
|
|
5
|
+
通过最先进的 React Context 数据流驱动与彻底的解耦架构,它不仅为你提供了“拿来即用”的精美默认弹窗,还赋予了你**100% 控制反转 (IoC)** 的能力,让你可以轻松定制从文案到界面的所有细节。
|
|
6
|
+
|
|
7
|
+
## 🌟 核心特性
|
|
8
|
+
|
|
9
|
+
- **🚀 开箱即用**:内置了美观的更新提示弹窗、进度条、应用商店跳转流,一键式集成。
|
|
10
|
+
- **📦 极致纯净 (Zero Dependencies)**:彻底抛弃 `react-native-root-siblings` 和其它庞大 UI 库,无环境限制,绝不污染宿主代码。
|
|
11
|
+
- **✨ 高级动画体验**:内置基于物理弹簧(Spring)的柔和入场动画,告别生硬闪现。
|
|
12
|
+
- **🎨 100% UI 控制反转**:利用 Render Props,随时可将默认 UI 替换成你自己业务的 UI,而底层严谨的下载与安装逻辑(Controller)依然为你服务。
|
|
13
|
+
- **🌍 国际化与文案重写**:所有内置弹窗文案支持完全重写或国际化扩展。
|
|
14
|
+
|
|
15
|
+
## 📦 安装
|
|
16
|
+
|
|
17
|
+
首先,你需要安装本库以及其底层核心依赖 `react-native-update`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install react-native-hot-update react-native-update
|
|
21
|
+
# 或
|
|
22
|
+
yarn add react-native-hot-update react-native-update
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> **注意**:请确保按照 `react-native-update` 官方文档完成了原生端的必要配置。
|
|
26
|
+
|
|
27
|
+
## 📖 基础使用 (Basic Usage)
|
|
28
|
+
|
|
29
|
+
### 1. 挂载 Provider
|
|
30
|
+
在你的应用最顶层(如 `App.tsx`),使用 `UpdateProvider` 包裹你的应用:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import React from 'react'
|
|
34
|
+
import { UpdateProvider } from 'react-native-hot-update'
|
|
35
|
+
import MainApp from './MainApp'
|
|
36
|
+
|
|
37
|
+
export default function App() {
|
|
38
|
+
return (
|
|
39
|
+
<UpdateProvider
|
|
40
|
+
appKey="<你的酷传 AppKey>"
|
|
41
|
+
iosAppId="<你的苹果商店 AppID>" // 可选,过期时提供跳转
|
|
42
|
+
themeColor="#FF4D4F" // 可选,自定义默认 UI 的主题色
|
|
43
|
+
>
|
|
44
|
+
<MainApp />
|
|
45
|
+
</UpdateProvider>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. 触发更新检查
|
|
51
|
+
在你需要触发检查的地方(例如首页加载时,或设置里的“检查更新”按钮),引入 `usePushyUpdate`:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import React, { useEffect } from 'react'
|
|
55
|
+
import { Button, View, ActivityIndicator } from 'react-native'
|
|
56
|
+
import { usePushyUpdate } from 'react-native-hot-update'
|
|
57
|
+
|
|
58
|
+
export default function HomeScreen() {
|
|
59
|
+
const { checkUpdateApp, isChecking } = usePushyUpdate()
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// 静默检查(flag=false,默认值):有更新才弹窗,已是最新版时不打扰用户
|
|
63
|
+
checkUpdateApp()
|
|
64
|
+
}, [])
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
68
|
+
{isChecking ? <ActivityIndicator /> : null}
|
|
69
|
+
<Button
|
|
70
|
+
title="手动检查更新"
|
|
71
|
+
// 手动触发(flag=true):无论是否最新版,都给用户反馈
|
|
72
|
+
onPress={() => checkUpdateApp(true)}
|
|
73
|
+
/>
|
|
74
|
+
</View>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 🛠 高阶使用 (Advanced Usage)
|
|
80
|
+
|
|
81
|
+
### 自定义文案 (Localization)
|
|
82
|
+
|
|
83
|
+
你可以通过 `localeText` 覆盖任何你不满意的默认文案,或者接入 i18n 字典:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
<UpdateProvider
|
|
87
|
+
appKey="YOUR_APP_KEY"
|
|
88
|
+
localeText={{
|
|
89
|
+
updateTitle: '🎉 发现新版本',
|
|
90
|
+
btnUpdateNow: '立刻升级',
|
|
91
|
+
alertDownloadCompleteDesc: '新包已经准备就绪,重启以生效!'
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<MainApp />
|
|
95
|
+
</UpdateProvider>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 100% 自定义 UI 渲染 (Render Props)
|
|
99
|
+
|
|
100
|
+
如果你觉得默认的弹窗不符合你们 App 的设计风格,你可以利用 `renderUpdateModal` 完全接管 UI 渲染。
|
|
101
|
+
我们的底层已经为你封装好了极具健壮性的 `startDownloadFlow` 逻辑流,你只需要负责画 UI 即可。
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { UpdateProvider, UpdateInfo } from 'react-native-hot-update'
|
|
105
|
+
import CustomUpdateUI from './my-components/CustomUpdateUI'
|
|
106
|
+
import CustomProgressUI from './my-components/CustomProgressUI'
|
|
107
|
+
|
|
108
|
+
export default function App() {
|
|
109
|
+
return (
|
|
110
|
+
<UpdateProvider
|
|
111
|
+
appKey="YOUR_APP_KEY"
|
|
112
|
+
renderUpdateModal={(updateInfo: UpdateInfo, { hideModal, doUpdate }) => (
|
|
113
|
+
// 完全自定义的“发现更新”界面
|
|
114
|
+
<CustomUpdateUI
|
|
115
|
+
version={updateInfo.name}
|
|
116
|
+
desc={updateInfo.description}
|
|
117
|
+
onCancel={hideModal}
|
|
118
|
+
onConfirm={doUpdate} // 这里的 doUpdate 是极其安全的底层流,内部会自动调起下载条和安装包逻辑
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
renderDownloadModal={(progress: { received: number; total: number }, { hideModal }) => (
|
|
122
|
+
// 完全自定义的“下载进度”界面
|
|
123
|
+
<CustomProgressUI
|
|
124
|
+
percent={Math.floor((progress.received / (progress.total || 1)) * 100)}
|
|
125
|
+
/>
|
|
126
|
+
)}
|
|
127
|
+
>
|
|
128
|
+
<MainApp />
|
|
129
|
+
</UpdateProvider>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 📚 API Reference
|
|
135
|
+
|
|
136
|
+
### `HotUpdateConfig` (UpdateProvider Props)
|
|
137
|
+
|
|
138
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
139
|
+
| --- | --- | --- | --- |
|
|
140
|
+
| `appKey` | `string` | 是 | `react-native-update` 的 AppKey |
|
|
141
|
+
| `iosAppId` | `string` | 否 | App Store 上的应用 ID,用于整包更新时跳转 |
|
|
142
|
+
| `themeColor` | `string` | 否 | 默认 UI 的按钮和进度条主题色 |
|
|
143
|
+
| `localeText` | `Partial<LocaleText>` | 否 | 用于覆盖自带的词条文案 |
|
|
144
|
+
| `renderUpdateModal` | `(info, handlers) => ReactElement` | 否 | 自定义“发现更新”的视图组件 |
|
|
145
|
+
| `renderDownloadModal`| `(progress, handlers) => ReactElement`| 否 | 自定义“下载中”的视图组件 |
|
|
146
|
+
|
|
147
|
+
### `usePushyUpdate()` 返回值
|
|
148
|
+
|
|
149
|
+
| 属性/方法 | 类型 | 说明 |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| `checkUpdateApp(flag?)` | `(boolean) => Promise<UpdateInfo>` | 核心方法:向服务器发起检查,若有更新将自动拉起弹窗 |
|
|
152
|
+
| `isChecking` | `boolean` | 是否正在请求接口检查中(可用于 Loading UI) |
|
|
153
|
+
| `error` | `Error \| null` | 检查过程中的错误对象 |
|
|
154
|
+
| `updateInfo` | `UpdateInfo` | 更新包的详细内容元数据 |
|
|
155
|
+
| `startDownloadFlow()` | `() => Promise<void>` | **核心控制器**:触发下载并自动处理安装流程的底层流 |
|
|
156
|
+
|
|
157
|
+
## 📄 License
|
|
158
|
+
|
|
159
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const defaultLocaleText: {
|
|
2
|
+
updateTitle: string;
|
|
3
|
+
downloadingTitle: string;
|
|
4
|
+
downloadedBytes: string;
|
|
5
|
+
totalBytes: string;
|
|
6
|
+
updateExpired: string;
|
|
7
|
+
updateUpToDate: string;
|
|
8
|
+
updateAvailable: string;
|
|
9
|
+
btnUpdateLater: string;
|
|
10
|
+
btnUpdateNow: string;
|
|
11
|
+
btnGotIt: string;
|
|
12
|
+
btnAppStore: string;
|
|
13
|
+
btnDownload: string;
|
|
14
|
+
alertDownloadComplete: string;
|
|
15
|
+
alertDownloadCompleteDesc: string;
|
|
16
|
+
alertMissingAppId: string;
|
|
17
|
+
alertMissingDownloadUrl: string;
|
|
18
|
+
alertCantOpenDownloadUrl: string;
|
|
19
|
+
alertDownloadUrlFailed: string;
|
|
20
|
+
};
|
package/es/constants.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export var defaultLocaleText = {
|
|
2
|
+
updateTitle: '应用更新提示',
|
|
3
|
+
downloadingTitle: '正在下载资源,请稍后...',
|
|
4
|
+
downloadedBytes: '已下载:',
|
|
5
|
+
totalBytes: '总大小:',
|
|
6
|
+
updateExpired: '应用有新的安装包,请下载安装包或前往应用市场进行更新,或联系运营人员进行下载更新。',
|
|
7
|
+
updateUpToDate: '当前应用版本已是最新版本,无需进行更新!如需下载新的安装包请前往应用市场或自行下载安装',
|
|
8
|
+
updateAvailable: '当前有需要更新的应用版本',
|
|
9
|
+
btnUpdateLater: '稍后更新',
|
|
10
|
+
btnUpdateNow: '立即更新',
|
|
11
|
+
btnGotIt: '我知道了',
|
|
12
|
+
btnAppStore: '应用市场',
|
|
13
|
+
btnDownload: '下载更新',
|
|
14
|
+
alertDownloadComplete: '系统提示',
|
|
15
|
+
alertDownloadCompleteDesc: '资源文件下载完成,是否立即更新?',
|
|
16
|
+
alertMissingAppId: '未配置苹果应用商店ID',
|
|
17
|
+
alertMissingDownloadUrl: '未配置应用下载地址,请先进行配置!',
|
|
18
|
+
alertCantOpenDownloadUrl: '无法打开应用下载地址,请前往应用市场更新!',
|
|
19
|
+
alertDownloadUrlFailed: '应用下载地址打开失败,请前往应用市场更新!'
|
|
20
|
+
};
|
package/es/index.d.ts
ADDED
package/es/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Pushy } from 'react-native-update';
|
|
2
|
+
import { HotUpdateConfig } from './updateProvider';
|
|
3
|
+
/**
|
|
4
|
+
* @description 热更新初始化配置
|
|
5
|
+
* @param config 热更新配置对象
|
|
6
|
+
* - appKey: 您的App的Key,请在Pushy后台获取
|
|
7
|
+
* - debug: 是否开启调试模式
|
|
8
|
+
* - checkStrategy: 检查更新策略
|
|
9
|
+
* - updateStrategy: 更新策略
|
|
10
|
+
* - autoMarkSuccess: 是否自动标记更新成功
|
|
11
|
+
* - notifyInterval: 同一版本最短通知间隔(ms)
|
|
12
|
+
* @returns 返回更新类实例
|
|
13
|
+
*/
|
|
14
|
+
export default function initialize(config: HotUpdateConfig): Pushy;
|
package/es/initialize.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
import { Pushy } from 'react-native-update';
|
|
8
|
+
/**
|
|
9
|
+
* @description 热更新初始化配置
|
|
10
|
+
* @param config 热更新配置对象
|
|
11
|
+
* - appKey: 您的App的Key,请在Pushy后台获取
|
|
12
|
+
* - debug: 是否开启调试模式
|
|
13
|
+
* - checkStrategy: 检查更新策略
|
|
14
|
+
* - updateStrategy: 更新策略
|
|
15
|
+
* - autoMarkSuccess: 是否自动标记更新成功
|
|
16
|
+
* - notifyInterval: 同一版本最短通知间隔(ms)
|
|
17
|
+
* @returns 返回更新类实例
|
|
18
|
+
*/
|
|
19
|
+
export default function initialize(config) {
|
|
20
|
+
var _config$checkStrategy, _config$updateStrateg;
|
|
21
|
+
if (!config.appKey) return;
|
|
22
|
+
return new Pushy(_objectSpread(_objectSpread({
|
|
23
|
+
appKey: config.appKey,
|
|
24
|
+
debug: __DEV__,
|
|
25
|
+
checkStrategy: (_config$checkStrategy = config.checkStrategy) !== null && _config$checkStrategy !== void 0 ? _config$checkStrategy : null,
|
|
26
|
+
updateStrategy: (_config$updateStrateg = config.updateStrategy) !== null && _config$updateStrateg !== void 0 ? _config$updateStrateg : null
|
|
27
|
+
}, config.autoMarkSuccess !== undefined && {
|
|
28
|
+
autoMarkSuccess: config.autoMarkSuccess
|
|
29
|
+
}), config.notifyInterval !== undefined && {
|
|
30
|
+
notifyInterval: config.notifyInterval
|
|
31
|
+
}));
|
|
32
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { defaultLocaleText } from './constants';
|
|
3
|
+
export type LocaleText = typeof defaultLocaleText;
|
|
4
|
+
/**
|
|
5
|
+
* @description 更新信息类型
|
|
6
|
+
* - upToDate: 是否已是最新版本
|
|
7
|
+
* - update: 是否有更新
|
|
8
|
+
* - expired: 版本是否已过期
|
|
9
|
+
* - name: 版本名称
|
|
10
|
+
* - hash: 版本哈希
|
|
11
|
+
* - description: 版本描述
|
|
12
|
+
* - metaInfo: 版本元信息
|
|
13
|
+
* - downloadUrl: 版本下载地址
|
|
14
|
+
*/
|
|
15
|
+
export interface UpdateInfo {
|
|
16
|
+
upToDate?: boolean;
|
|
17
|
+
update?: boolean;
|
|
18
|
+
expired?: boolean;
|
|
19
|
+
name?: string;
|
|
20
|
+
hash?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
metaInfo?: string;
|
|
23
|
+
downloadUrl?: string;
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @description 热更新配置类型
|
|
28
|
+
* - appKey: 您的App的Key,请在Pushy后台获取
|
|
29
|
+
* - iosAppId: 苹果商店ID
|
|
30
|
+
* - themeColor: 主题颜色
|
|
31
|
+
* - checkStrategy: 检查更新策略
|
|
32
|
+
* - updateStrategy: 更新策略
|
|
33
|
+
* - autoMarkSuccess: 是否自动标记更新成功,默认 true;设为 false 时需用户手动调用 markSuccess()
|
|
34
|
+
* - notifyInterval: 同一版本最短通知间隔(ms),默认 300000 (5分钟)
|
|
35
|
+
* - localeText: 国际化/自定义文案配置
|
|
36
|
+
* - renderUpdateModal: 自定义更新弹窗渲染
|
|
37
|
+
* - renderDownloadModal: 自定义下载弹窗渲染
|
|
38
|
+
*/
|
|
39
|
+
export interface HotUpdateConfig {
|
|
40
|
+
appKey: string;
|
|
41
|
+
iosAppId?: string;
|
|
42
|
+
themeColor?: string;
|
|
43
|
+
checkStrategy?: 'onAppStart' | 'both' | null;
|
|
44
|
+
updateStrategy?: 'alertUpdateAndIgnoreError' | 'silentAndNow' | null;
|
|
45
|
+
autoMarkSuccess?: boolean;
|
|
46
|
+
notifyInterval?: number;
|
|
47
|
+
localeText?: Partial<LocaleText>;
|
|
48
|
+
renderUpdateModal?: (updateInfo: UpdateInfo, handlers: {
|
|
49
|
+
hideModal: () => void;
|
|
50
|
+
doUpdate: () => void;
|
|
51
|
+
}) => React.ReactElement | null;
|
|
52
|
+
renderDownloadModal?: (progress: {
|
|
53
|
+
received: number;
|
|
54
|
+
total: number;
|
|
55
|
+
}, handlers: {
|
|
56
|
+
hideModal: () => void;
|
|
57
|
+
}) => React.ReactElement | null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* @description 热更新提供者组件属性类型
|
|
61
|
+
*/
|
|
62
|
+
interface IProps extends HotUpdateConfig {
|
|
63
|
+
children?: React.ReactNode;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* @description 热更新上下文类型
|
|
67
|
+
*/
|
|
68
|
+
export declare const HotUpdateContext: any;
|
|
69
|
+
/**
|
|
70
|
+
* @description 热更新提供者组件,每个业务的入口页引入即可
|
|
71
|
+
* @param props 包含appKey, iosAppId, themeColor等配置
|
|
72
|
+
* @returns 热更新提供者组件
|
|
73
|
+
*/
|
|
74
|
+
export default function UpdateProvider({ children, ...config }: IProps): any;
|
|
75
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
var _excluded = ["children"];
|
|
3
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
7
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
8
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
9
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
10
|
+
import React, { createContext, useMemo } from 'react';
|
|
11
|
+
import { UpdateProvider as PushyUpdateProvider } from 'react-native-update';
|
|
12
|
+
import UpdateClient from "./initialize";
|
|
13
|
+
import { defaultLocaleText } from "./constants";
|
|
14
|
+
import { UpdateStateProvider } from "./updateState";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @description 更新信息类型
|
|
18
|
+
* - upToDate: 是否已是最新版本
|
|
19
|
+
* - update: 是否有更新
|
|
20
|
+
* - expired: 版本是否已过期
|
|
21
|
+
* - name: 版本名称
|
|
22
|
+
* - hash: 版本哈希
|
|
23
|
+
* - description: 版本描述
|
|
24
|
+
* - metaInfo: 版本元信息
|
|
25
|
+
* - downloadUrl: 版本下载地址
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @description 热更新配置类型
|
|
30
|
+
* - appKey: 您的App的Key,请在Pushy后台获取
|
|
31
|
+
* - iosAppId: 苹果商店ID
|
|
32
|
+
* - themeColor: 主题颜色
|
|
33
|
+
* - checkStrategy: 检查更新策略
|
|
34
|
+
* - updateStrategy: 更新策略
|
|
35
|
+
* - autoMarkSuccess: 是否自动标记更新成功,默认 true;设为 false 时需用户手动调用 markSuccess()
|
|
36
|
+
* - notifyInterval: 同一版本最短通知间隔(ms),默认 300000 (5分钟)
|
|
37
|
+
* - localeText: 国际化/自定义文案配置
|
|
38
|
+
* - renderUpdateModal: 自定义更新弹窗渲染
|
|
39
|
+
* - renderDownloadModal: 自定义下载弹窗渲染
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @description 热更新提供者组件属性类型
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @description 热更新上下文类型
|
|
48
|
+
*/
|
|
49
|
+
export var HotUpdateContext = /*#__PURE__*/createContext({});
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @description 热更新提供者组件,每个业务的入口页引入即可
|
|
53
|
+
* @param props 包含appKey, iosAppId, themeColor等配置
|
|
54
|
+
* @returns 热更新提供者组件
|
|
55
|
+
*/
|
|
56
|
+
export default function UpdateProvider(_ref) {
|
|
57
|
+
var children = _ref.children,
|
|
58
|
+
config = _objectWithoutProperties(_ref, _excluded);
|
|
59
|
+
if (!config.appKey) return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
60
|
+
var client = useMemo(function () {
|
|
61
|
+
return UpdateClient(config);
|
|
62
|
+
}, [config.appKey]);
|
|
63
|
+
var finalConfig = useMemo(function () {
|
|
64
|
+
return _objectSpread(_objectSpread({}, config), {}, {
|
|
65
|
+
localeText: _objectSpread(_objectSpread({}, defaultLocaleText), config.localeText)
|
|
66
|
+
});
|
|
67
|
+
}, [config.appKey, config.iosAppId, config.themeColor, config.localeText, config.renderUpdateModal, config.renderDownloadModal]);
|
|
68
|
+
return /*#__PURE__*/React.createElement(HotUpdateContext.Provider, {
|
|
69
|
+
value: finalConfig
|
|
70
|
+
}, /*#__PURE__*/React.createElement(PushyUpdateProvider, {
|
|
71
|
+
client: client,
|
|
72
|
+
children: /*#__PURE__*/React.createElement(UpdateStateProvider, null, children)
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @description 更新状态上下文类型
|
|
4
|
+
* - isUpdateVisible: 更新弹窗是否可见
|
|
5
|
+
* - isDownloadVisible: 下载弹窗是否可见
|
|
6
|
+
* - showUpdateModal: 显示更新弹窗
|
|
7
|
+
* - hideUpdateModal: 隐藏更新弹窗
|
|
8
|
+
* - showDownloadModal: 显示下载弹窗
|
|
9
|
+
* - hideDownloadModal: 隐藏下载弹窗
|
|
10
|
+
* - startDownloadFlow: 开始下载更新
|
|
11
|
+
*/
|
|
12
|
+
export declare const UpdateStateContext: any;
|
|
13
|
+
/**
|
|
14
|
+
* @description 更新状态钩子
|
|
15
|
+
* @returns 更新状态钩子
|
|
16
|
+
*/
|
|
17
|
+
export declare function useUpdateState(): any;
|
|
18
|
+
/**
|
|
19
|
+
* @description 更新状态提供者
|
|
20
|
+
* @param children
|
|
21
|
+
* @returns 更新状态提供者
|
|
22
|
+
*/
|
|
23
|
+
export declare function UpdateStateProvider({ children }: {
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
}): any;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
3
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
4
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
5
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
6
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
7
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
8
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
9
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
10
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
11
|
+
import React, { createContext, useContext, useState, Fragment, useMemo, useCallback } from 'react';
|
|
12
|
+
import { Alert } from 'react-native';
|
|
13
|
+
import { useUpdate } from 'react-native-update';
|
|
14
|
+
import { HotUpdateContext } from "./updateProvider";
|
|
15
|
+
import UpdateModalWidget from "./widget/update.modal.widget";
|
|
16
|
+
import DownloadModalWidget from "./widget/download.modal.widget";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @description 更新状态上下文类型
|
|
20
|
+
* - isUpdateVisible: 更新弹窗是否可见
|
|
21
|
+
* - isDownloadVisible: 下载弹窗是否可见
|
|
22
|
+
* - showUpdateModal: 显示更新弹窗
|
|
23
|
+
* - hideUpdateModal: 隐藏更新弹窗
|
|
24
|
+
* - showDownloadModal: 显示下载弹窗
|
|
25
|
+
* - hideDownloadModal: 隐藏下载弹窗
|
|
26
|
+
* - startDownloadFlow: 开始下载更新
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @description 更新状态上下文类型
|
|
31
|
+
* - isUpdateVisible: 更新弹窗是否可见
|
|
32
|
+
* - isDownloadVisible: 下载弹窗是否可见
|
|
33
|
+
* - showUpdateModal: 显示更新弹窗
|
|
34
|
+
* - hideUpdateModal: 隐藏更新弹窗
|
|
35
|
+
* - showDownloadModal: 显示下载弹窗
|
|
36
|
+
* - hideDownloadModal: 隐藏下载弹窗
|
|
37
|
+
* - startDownloadFlow: 开始下载更新
|
|
38
|
+
*/
|
|
39
|
+
export var UpdateStateContext = /*#__PURE__*/createContext(null);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @description 更新状态钩子
|
|
43
|
+
* @returns 更新状态钩子
|
|
44
|
+
*/
|
|
45
|
+
export function useUpdateState() {
|
|
46
|
+
var context = useContext(UpdateStateContext);
|
|
47
|
+
if (!context) {
|
|
48
|
+
throw new Error('useUpdateState must be used within an UpdateStateProvider');
|
|
49
|
+
}
|
|
50
|
+
return context;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @description 更新状态提供者
|
|
55
|
+
* @param children
|
|
56
|
+
* @returns 更新状态提供者
|
|
57
|
+
*/
|
|
58
|
+
export function UpdateStateProvider(_ref) {
|
|
59
|
+
var children = _ref.children;
|
|
60
|
+
var _useUpdate = useUpdate(),
|
|
61
|
+
downloadUpdate = _useUpdate.downloadUpdate,
|
|
62
|
+
switchVersion = _useUpdate.switchVersion,
|
|
63
|
+
switchVersionLater = _useUpdate.switchVersionLater,
|
|
64
|
+
updateInfo = _useUpdate.updateInfo;
|
|
65
|
+
var config = useContext(HotUpdateContext);
|
|
66
|
+
var locale = config.localeText || {};
|
|
67
|
+
var isForceUpdate = useMemo(function () {
|
|
68
|
+
try {
|
|
69
|
+
if (!(updateInfo !== null && updateInfo !== void 0 && updateInfo.metaInfo)) return false;
|
|
70
|
+
var meta = JSON.parse(updateInfo.metaInfo);
|
|
71
|
+
return meta.force === true || meta.forceUpdate === true;
|
|
72
|
+
} catch (_unused) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}, [updateInfo === null || updateInfo === void 0 ? void 0 : updateInfo.metaInfo]);
|
|
76
|
+
var _useState = useState(false),
|
|
77
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
78
|
+
isUpdateVisible = _useState2[0],
|
|
79
|
+
setIsUpdateVisible = _useState2[1];
|
|
80
|
+
var _useState3 = useState(false),
|
|
81
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
82
|
+
isDownloadVisible = _useState4[0],
|
|
83
|
+
setIsDownloadVisible = _useState4[1];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @description 开始下载更新
|
|
87
|
+
* @returns Promise<void>
|
|
88
|
+
*/
|
|
89
|
+
var startDownloadFlow = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
90
|
+
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
91
|
+
while (1) switch (_context.prev = _context.next) {
|
|
92
|
+
case 0:
|
|
93
|
+
setIsUpdateVisible(false);
|
|
94
|
+
setIsDownloadVisible(true);
|
|
95
|
+
_context.prev = 2;
|
|
96
|
+
_context.next = 5;
|
|
97
|
+
return downloadUpdate();
|
|
98
|
+
case 5:
|
|
99
|
+
setIsDownloadVisible(false);
|
|
100
|
+
Alert.alert(locale.alertDownloadComplete || '系统提示', locale.alertDownloadCompleteDesc || '资源文件下载完成,是否立即更新?', isForceUpdate ? [{
|
|
101
|
+
text: locale.btnUpdateNow || '立即更新',
|
|
102
|
+
onPress: switchVersion
|
|
103
|
+
}] : [{
|
|
104
|
+
text: locale.btnUpdateLater || '稍后更新',
|
|
105
|
+
onPress: switchVersionLater
|
|
106
|
+
}, {
|
|
107
|
+
text: locale.btnUpdateNow || '立即更新',
|
|
108
|
+
onPress: switchVersion
|
|
109
|
+
}], {
|
|
110
|
+
cancelable: !isForceUpdate
|
|
111
|
+
});
|
|
112
|
+
_context.next = 14;
|
|
113
|
+
break;
|
|
114
|
+
case 9:
|
|
115
|
+
_context.prev = 9;
|
|
116
|
+
_context.t0 = _context["catch"](2);
|
|
117
|
+
setIsDownloadVisible(false);
|
|
118
|
+
if (isForceUpdate) {
|
|
119
|
+
setIsUpdateVisible(true);
|
|
120
|
+
}
|
|
121
|
+
Alert.alert('提示', locale.alertDownloadUrlFailed || '下载失败,请检查网络或稍后重试');
|
|
122
|
+
case 14:
|
|
123
|
+
case "end":
|
|
124
|
+
return _context.stop();
|
|
125
|
+
}
|
|
126
|
+
}, _callee, null, [[2, 9]]);
|
|
127
|
+
})), [downloadUpdate, switchVersion, switchVersionLater, locale, isForceUpdate]);
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @description 更新状态提供者
|
|
131
|
+
* @returns 更新状态提供者
|
|
132
|
+
*/
|
|
133
|
+
var value = useMemo(function () {
|
|
134
|
+
return {
|
|
135
|
+
isUpdateVisible: isUpdateVisible,
|
|
136
|
+
isDownloadVisible: isDownloadVisible,
|
|
137
|
+
showUpdateModal: function showUpdateModal() {
|
|
138
|
+
return setIsUpdateVisible(true);
|
|
139
|
+
},
|
|
140
|
+
hideUpdateModal: function hideUpdateModal() {
|
|
141
|
+
return setIsUpdateVisible(false);
|
|
142
|
+
},
|
|
143
|
+
showDownloadModal: function showDownloadModal() {
|
|
144
|
+
return setIsDownloadVisible(true);
|
|
145
|
+
},
|
|
146
|
+
hideDownloadModal: function hideDownloadModal() {
|
|
147
|
+
return setIsDownloadVisible(false);
|
|
148
|
+
},
|
|
149
|
+
startDownloadFlow: startDownloadFlow
|
|
150
|
+
};
|
|
151
|
+
}, [isUpdateVisible, isDownloadVisible, startDownloadFlow]);
|
|
152
|
+
return /*#__PURE__*/React.createElement(UpdateStateContext.Provider, {
|
|
153
|
+
value: value
|
|
154
|
+
}, children, /*#__PURE__*/React.createElement(UpdatePortalManager, null));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @description 更新弹窗管理器
|
|
159
|
+
* @returns 更新弹窗管理器
|
|
160
|
+
*/
|
|
161
|
+
function UpdatePortalManager() {
|
|
162
|
+
var _useUpdateState = useUpdateState(),
|
|
163
|
+
isUpdateVisible = _useUpdateState.isUpdateVisible,
|
|
164
|
+
isDownloadVisible = _useUpdateState.isDownloadVisible;
|
|
165
|
+
return /*#__PURE__*/React.createElement(Fragment, null, isUpdateVisible && /*#__PURE__*/React.createElement(UpdateModalWidget, null), isDownloadVisible && /*#__PURE__*/React.createElement(DownloadModalWidget, null));
|
|
166
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { UpdateInfo } from './updateProvider';
|
|
2
|
+
/**
|
|
3
|
+
* @description 更新检查钩子
|
|
4
|
+
* @returns 更新检查钩子
|
|
5
|
+
*/
|
|
6
|
+
export default function usePushyUpdate(): {
|
|
7
|
+
checkUpdateApp: (flag?: boolean) => Promise<UpdateInfo | void>;
|
|
8
|
+
updateInfo: any;
|
|
9
|
+
isChecking: any;
|
|
10
|
+
error: any;
|
|
11
|
+
startDownloadFlow: any;
|
|
12
|
+
downloadUpdate: any;
|
|
13
|
+
switchVersion: any;
|
|
14
|
+
switchVersionLater: any;
|
|
15
|
+
progress: any;
|
|
16
|
+
markSuccess: any;
|
|
17
|
+
};
|