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

add expoUsePushy demo (#495)

* add expoUsePushy demo

* update
This commit is contained in:
波仔糕
2025-04-26 21:36:02 +08:00
committed by GitHub
parent c771672fcd
commit 37849b1730
16 changed files with 6182 additions and 0 deletions

36
Example/expoUsePushy/.gitignore vendored Normal file
View File

@@ -0,0 +1,36 @@
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
# dependencies
node_modules/
# Expo
.expo/
dist/
web-build/
expo-env.d.ts
# Native
*.orig.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
# Metro
.metro-health-check*
# debug
npm-debug.*
yarn-debug.*
yarn-error.*
# macOS
.DS_Store
*.pem
# local env files
.env*.local
# typescript
*.tsbuildinfo

View File

@@ -0,0 +1,221 @@
/* eslint-disable react/no-unstable-nested-components */
/* eslint-disable react-native/no-inline-styles */
import React, {useState} from 'react';
import {StyleSheet, Text, View, TouchableOpacity, Image} from 'react-native';
import TestConsole from './TestConsole';
import _updateConfig from './update.json';
import {PushyProvider, Pushy, usePushy} from 'react-native-update';
const {appKey} = _updateConfig.android;
function Home() {
const {
client,
checkUpdate,
downloadUpdate,
switchVersionLater,
switchVersion,
updateInfo,
packageVersion,
currentHash,
progress: {received, total} = {},
} = usePushy();
const [useDefaultAlert, setUseDefaultAlert] = useState(false);
const [showTestConsole, setShowTestConsole] = useState(false);
const [showUpdateBanner, setShowUpdateBanner] = useState(false);
const [showUpdateSnackbar, setShowUpdateSnackbar] = useState(false);
// if (updateInfo) {
// updateInfo!.name = 'name';
// updateInfo!.update = true;
// }
const snackbarVisible =
!useDefaultAlert && showUpdateSnackbar && updateInfo?.update;
if (showTestConsole) {
return (
<TestConsole visible={true} onClose={() => setShowTestConsole(false)} />
);
}
return (
<View style={styles.container}>
<Text style={styles.welcome}>使Pushy热更新服务</Text>
{/* <Text style={styles.welcome}>😁hdiffFromAPP更新成功</Text> */}
{/* <Text style={styles.welcome}>😁hdiffFromPPk更新成功</Text> */}
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={() => {
client?.setOptions({
updateStrategy: !useDefaultAlert ? null : 'alwaysAlert',
});
setShowUpdateSnackbar(useDefaultAlert);
setUseDefaultAlert(!useDefaultAlert);
}}
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
<View
style={{
width: 20,
height: 20,
borderWidth: 1,
borderColor: '#999',
backgroundColor: useDefaultAlert ? 'blue' : 'white',
justifyContent: 'center',
alignItems: 'center',
}}>
{useDefaultAlert && <Text style={{color: 'white'}}></Text>}
</View>
<Text style={{marginLeft: 8}}>
{' '}
{useDefaultAlert ? '当前使用' : '当前不使用'}alert更新提示
</Text>
</TouchableOpacity>
</View>
<Image
resizeMode={'contain'}
source={require('./assets/shezhi.png')}
style={styles.image}
/>
<Text style={styles.instructions}>
{'\n'}
: {packageVersion}
{'\n'}
Hash: {currentHash || '(空)'}
{'\n'}
</Text>
<Text>
{received} / {total}
</Text>
<TouchableOpacity
onPress={() => {
checkUpdate();
setShowUpdateSnackbar(true);
}}>
<Text style={styles.instructions}></Text>
</TouchableOpacity>
<TouchableOpacity
testID="testcase"
style={{marginTop: 15}}
onPress={() => {
setShowTestConsole(true);
}}>
<Text style={styles.instructions}>
react-native-update版本{client?.version}
</Text>
</TouchableOpacity>
{snackbarVisible && (
<View style={styles.overlay}>
<View
style={{
width: '100%',
backgroundColor: '#333',
padding: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<Text style={{color: 'white'}}>
({updateInfo.name})
</Text>
<View style={{flexDirection: 'row'}}>
<TouchableOpacity
onPress={() => setShowUpdateSnackbar(false)}
style={{marginRight: 10}}>
<Text style={{color: 'white'}}></Text>
</TouchableOpacity>
<TouchableOpacity
onPress={async () => {
setShowUpdateSnackbar(false);
await downloadUpdate();
setShowUpdateBanner(true);
}}>
<Text style={{color: '#2196F3'}}></Text>
</TouchableOpacity>
</View>
</View>
</View>
)}
{showUpdateBanner && (
<View style={styles.overlay}>
<View
style={{
width: '100%',
backgroundColor: '#fff',
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#eee',
}}>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<Text></Text>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'flex-end',
marginTop: 10,
}}>
<TouchableOpacity
onPress={() => {
switchVersionLater();
setShowUpdateBanner(false);
}}
style={{marginRight: 20}}>
<Text style={{color: '#2196F3'}}></Text>
</TouchableOpacity>
<TouchableOpacity onPress={switchVersion}>
<Text style={{color: '#2196F3'}}></Text>
</TouchableOpacity>
</View>
</View>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
overlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
image: {},
});
const pushyClient = new Pushy({
appKey,
debug: true,
});
export default function HomeScreen() {
return (
<PushyProvider client={pushyClient}>
<Home />
</PushyProvider>
);
}

View File

@@ -0,0 +1,274 @@
/* eslint-disable react-native/no-inline-styles */
/* eslint-disable react/react-in-jsx-scope */
import {useCallback, useMemo, useState} from 'react';
import {
ActivityIndicator,
TextInput,
Button,
StyleSheet,
SafeAreaView,
Text,
View,
TouchableOpacity,
} from 'react-native';
import {PushyModule} from 'react-native-update';
const Hash = '9D5CE6EBA420717BE7E7D308B11F8207681B066C951D68F3994D19828F342474';
const UUID = '00000000-0000-0000-0000-000000000000';
const DownloadUrl = 'https://localhost:3000/diff.ppk-patch';
const AppPatchDownloadUrl = 'https://github.com/bozaigao/test_pushy_server/raw/refs/heads/main/hdiff.app-patch';
const AppPatchHash = 'f5ba92c7c04250d4b8a446c8267ef459';
const PPKDownloadUrl = 'https://github.com/bozaigao/test_pushy_server/raw/refs/heads/main/hdiff.ppk-patch';
const PPKPatchHash = '6b3d26b7d868d1f67aedadb7f0b342d9';
const OriginHash = 'f5ba92c7c04250d4b8a446c8267ef459';
const CustomDialog = ({title, visible, onConfirm}) => {
if (!visible) {
return null;
}
return (
<View style={styles.overlay}>
<View style={styles.dialog}>
<Text style={styles.title}>{title}</Text>
<TouchableOpacity
testID="done"
style={styles.button}
onPress={onConfirm}>
<Text style={styles.buttonText}>确认</Text>
</TouchableOpacity>
</View>
</View>
);
};
export default function TestConsole({visible, onClose}) {
const [text, setText] = useState('');
const [running, setRunning] = useState(false);
const [options, setOptions] = useState();
const [alertVisible, setAlertVisible] = useState(false);
const [alertMsg, setAlertMsg] = useState('');
const NativeTestMethod = useMemo(() => {
return [
{
name: 'setLocalHashInfo',
invoke: () => {
setText(
`setLocalHashInfo\n${Hash}\n{\"version\":\"1.0.0\",\"size\":\"19M\"}`,
);
},
},
{
name: 'getLocalHashInfo',
invoke: () => {
setText(`getLocalHashInfo\n${Hash}`);
},
},
{
name: 'setUuid',
invoke: () => {
setText(`setUuid\n${UUID}`);
},
},
{
name: 'reloadUpdate',
invoke: () => {
setText('reloadUpdate');
setOptions({hash: Hash});
},
},
{
name: 'setNeedUpdateForApp',
invoke: () => {
setText('setNeedUpdate');
setOptions({hash: AppPatchHash});
},
},
{
name: 'setNeedUpdateForPPK',
invoke: () => {
setText('setNeedUpdate');
setOptions({hash: PPKPatchHash});
},
},
{
name: 'markSuccess',
invoke: () => {
setText('markSuccess');
setOptions(undefined);
},
},
{
name: 'downloadPatchFromPpk',
invoke: () => {
setText('downloadPatchFromPpk');
setOptions({updateUrl: PPKDownloadUrl, hash: PPKPatchHash, originHash: OriginHash});
},
},
{
name: 'downloadPatchFromPackage',
invoke: () => {
setText('downloadPatchFromPackage');
setOptions({updateUrl: AppPatchDownloadUrl, hash: AppPatchHash});
},
},
{
name: 'downloadFullUpdate',
invoke: () => {
setText('downloadFullUpdate');
setOptions({updateUrl: DownloadUrl, hash: Hash});
},
},
{
name: 'downloadAndInstallApk',
invoke: () => {
setText('downloadAndInstallApk');
setOptions({url: DownloadUrl, target: Hash, hash: Hash});
},
},
];
}, []);
const renderTestView = useCallback(() => {
const views = [];
for (let i = 0; i < NativeTestMethod.length; i++) {
views.push(
<TouchableOpacity
key={i}
testID={NativeTestMethod[i].name}
onPress={() => {
NativeTestMethod[i].invoke();
}}>
<Text>{NativeTestMethod[i].name}</Text>
</TouchableOpacity>,
);
}
return <View>{views}</View>;
}, [NativeTestMethod]);
if (!visible) {
return null;
}
return (
<SafeAreaView style={{flex: 1, padding: 10}}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 10,
}}>
<Text>调试Pushy方法方法名参数值换行</Text>
<Button title="关闭" onPress={() => onClose()} />
</View>
<TextInput
autoCorrect={false}
autoCapitalize="none"
style={{
borderWidth: StyleSheet.hairlineWidth * 4,
borderColor: 'black',
height: '30%',
marginTop: 20,
marginBottom: 20,
padding: 10,
fontSize: 20,
}}
textAlignVertical="top"
multiline={true}
value={text}
onChangeText={setText}
/>
{running && <ActivityIndicator />}
<TouchableOpacity
style={{
backgroundColor: 'rgb(0,140,237)',
justifyContent: 'center',
alignItems: 'center',
paddingTop: 10,
paddingBottom: 10,
marginBottom: 5,
}}
testID="submit"
onPress={async () => {
setRunning(true);
try {
const inputs = text.split('\n');
const methodName = inputs[0];
let params = [];
if (inputs.length === 1) {
if (options) {
await PushyModule[methodName](options);
} else {
await PushyModule[methodName]();
}
} else {
if (inputs.length === 2) {
params = [inputs[1]];
} else {
params = [inputs[1], inputs[2]];
console.log({inputs, params});
}
await PushyModule[methodName](...params);
}
setAlertVisible(true);
setAlertMsg('done');
} catch (e) {
setAlertVisible(true);
setAlertMsg(e.message);
}
setRunning(false);
}}>
<Text style={{color: 'white'}}>执行</Text>
</TouchableOpacity>
<Button title="重置" onPress={() => setText('')} />
{renderTestView()}
<CustomDialog
title={alertMsg}
visible={alertVisible}
onConfirm={() => {
setAlertVisible(false);
}}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
overlay: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
},
dialog: {
backgroundColor: 'white',
borderRadius: 10,
padding: 20,
width: '80%',
alignItems: 'center',
},
title: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 20,
},
button: {
backgroundColor: '#2196F3',
borderRadius: 5,
paddingVertical: 10,
paddingHorizontal: 20,
},
buttonText: {
color: 'white',
fontWeight: 'bold',
},
});

View File

@@ -0,0 +1,29 @@
{
"expo": {
"name": "expoUsePushy",
"slug": "expoUsePushy",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash-icon.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.anonymous.expoUsePushy"
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"favicon": "./assets/favicon.png"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,8 @@
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in Expo Go or in a native build,
// the environment is set up appropriately
registerRootComponent(App);

View File

@@ -0,0 +1,24 @@
{
"name": "expousepushy",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web"
},
"dependencies": {
"expo": "~52.0.46",
"expo-status-bar": "~2.0.1",
"react": "18.3.1",
"react-native": "0.76.9",
"react-native-update": "^10.28.5"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~18.3.12",
"typescript": "^5.3.3"
},
"private": true
}

View File

@@ -0,0 +1,6 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
}
}

View File

@@ -0,0 +1,14 @@
{
"ios": {
"appId": 29439,
"appKey": "jNA71vpFHTDpEqeZd9yx87zj"
},
"android": {
"appId": 29413,
"appKey": "vdZWPXU6eyaPE6Avk96-YvwK"
},
"harmony": {
"appId": 29140,
"appKey": "JLklGflGIRbY-cMebjQwm1J1"
}
}

File diff suppressed because it is too large Load Diff