You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.8 KiB
193 lines
4.8 KiB
|
1 month ago
|
import { useState } from 'react';
|
||
|
|
import { StyleSheet, TouchableOpacity, Alert, ActivityIndicator } from 'react-native';
|
||
|
|
import * as Updates from 'expo-updates';
|
||
|
|
|
||
|
|
import { Text, View } from '@/components/Themed';
|
||
|
|
|
||
|
|
export default function TabOneScreen() {
|
||
|
|
const [isChecking, setIsChecking] = useState(false);
|
||
|
|
const [updateInfo, setUpdateInfo] = useState<string>('');
|
||
|
|
|
||
|
|
const checkForUpdates = async () => {
|
||
|
|
if (__DEV__) {
|
||
|
|
Alert.alert('提示', '开发模式下无法检查更新,请使用生产构建测试热更新功能');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
setIsChecking(true);
|
||
|
|
setUpdateInfo('正在检查更新...');
|
||
|
|
|
||
|
|
try {
|
||
|
|
const update = await Updates.checkForUpdateAsync();
|
||
|
|
|
||
|
|
if (update.isAvailable) {
|
||
|
|
setUpdateInfo('发现新版本,正在下载...');
|
||
|
|
await Updates.fetchUpdateAsync();
|
||
|
|
|
||
|
|
Alert.alert(
|
||
|
|
'更新完成',
|
||
|
|
'新版本已下载完成,是否立即重启应用?',
|
||
|
|
[
|
||
|
|
{
|
||
|
|
text: '稍后',
|
||
|
|
style: 'cancel',
|
||
|
|
onPress: () => setUpdateInfo('更新已下载,稍后重启应用即可应用'),
|
||
|
|
},
|
||
|
|
{
|
||
|
|
text: '立即重启',
|
||
|
|
onPress: async () => {
|
||
|
|
await Updates.reloadAsync();
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]
|
||
|
|
);
|
||
|
|
} else {
|
||
|
|
setUpdateInfo('当前已是最新版本');
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
setUpdateInfo('检查更新失败: ' + (error as Error).message);
|
||
|
|
Alert.alert('错误', '检查更新失败,请稍后重试');
|
||
|
|
} finally {
|
||
|
|
setIsChecking(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const getUpdateInfo = () => {
|
||
|
|
const {
|
||
|
|
isEmbeddedLaunch,
|
||
|
|
isEmergencyLaunch,
|
||
|
|
updateId,
|
||
|
|
channel,
|
||
|
|
runtimeVersion,
|
||
|
|
} = Updates.useUpdates();
|
||
|
|
|
||
|
|
return `
|
||
|
|
运行模式: ${__DEV__ ? '开发模式' : '生产模式'}
|
||
|
|
是否为内嵌启动: ${isEmbeddedLaunch ? '是' : '否'}
|
||
|
|
是否为紧急启动: ${isEmergencyLaunch ? '是' : '否'}
|
||
|
|
更新 ID: ${updateId || '无'}
|
||
|
|
更新通道: ${channel || '无'}
|
||
|
|
运行时版本: ${runtimeVersion || '无'}
|
||
|
|
`.trim();
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<View style={styles.container}>
|
||
|
|
<Text style={styles.title}>🚀 热更新演示</Text>
|
||
|
|
<View style={styles.separator} lightColor="#eee" darkColor="rgba(255,255,255,0.1)" />
|
||
|
|
|
||
|
|
<View style={styles.infoContainer}>
|
||
|
|
<Text style={styles.infoTitle}>当前版本信息:</Text>
|
||
|
|
<Text style={styles.infoText}>{getUpdateInfo()}</Text>
|
||
|
|
</View>
|
||
|
|
|
||
|
|
<TouchableOpacity
|
||
|
|
style={[styles.button, isChecking && styles.buttonDisabled]}
|
||
|
|
onPress={checkForUpdates}
|
||
|
|
disabled={isChecking}
|
||
|
|
>
|
||
|
|
{isChecking ? (
|
||
|
|
<ActivityIndicator color="#fff" />
|
||
|
|
) : (
|
||
|
|
<Text style={styles.buttonText}>检查更新</Text>
|
||
|
|
)}
|
||
|
|
</TouchableOpacity>
|
||
|
|
|
||
|
|
{updateInfo ? (
|
||
|
|
<View style={styles.updateInfoContainer}>
|
||
|
|
<Text style={styles.updateInfoText}>{updateInfo}</Text>
|
||
|
|
</View>
|
||
|
|
) : null}
|
||
|
|
|
||
|
|
<View style={styles.instructionsContainer}>
|
||
|
|
<Text style={styles.instructionsTitle}>📝 使用说明:</Text>
|
||
|
|
<Text style={styles.instructionsText}>
|
||
|
|
1. 使用 EAS Build 构建生产版本{'\n'}
|
||
|
|
2. 修改代码后运行 eas update 发布更新{'\n'}
|
||
|
|
3. 打开应用点击"检查更新"按钮{'\n'}
|
||
|
|
4. 应用会自动下载并提示重启
|
||
|
|
</Text>
|
||
|
|
</View>
|
||
|
|
</View>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const styles = StyleSheet.create({
|
||
|
|
container: {
|
||
|
|
flex: 1,
|
||
|
|
alignItems: 'center',
|
||
|
|
justifyContent: 'center',
|
||
|
|
padding: 20,
|
||
|
|
},
|
||
|
|
title: {
|
||
|
|
fontSize: 28,
|
||
|
|
fontWeight: 'bold',
|
||
|
|
marginBottom: 10,
|
||
|
|
},
|
||
|
|
separator: {
|
||
|
|
marginVertical: 20,
|
||
|
|
height: 1,
|
||
|
|
width: '80%',
|
||
|
|
},
|
||
|
|
infoContainer: {
|
||
|
|
backgroundColor: 'rgba(0, 122, 255, 0.1)',
|
||
|
|
padding: 15,
|
||
|
|
borderRadius: 10,
|
||
|
|
marginBottom: 20,
|
||
|
|
width: '100%',
|
||
|
|
},
|
||
|
|
infoTitle: {
|
||
|
|
fontSize: 16,
|
||
|
|
fontWeight: 'bold',
|
||
|
|
marginBottom: 10,
|
||
|
|
},
|
||
|
|
infoText: {
|
||
|
|
fontSize: 12,
|
||
|
|
fontFamily: 'monospace',
|
||
|
|
lineHeight: 18,
|
||
|
|
},
|
||
|
|
button: {
|
||
|
|
backgroundColor: '#007AFF',
|
||
|
|
paddingHorizontal: 30,
|
||
|
|
paddingVertical: 15,
|
||
|
|
borderRadius: 10,
|
||
|
|
marginBottom: 20,
|
||
|
|
minWidth: 200,
|
||
|
|
alignItems: 'center',
|
||
|
|
},
|
||
|
|
buttonDisabled: {
|
||
|
|
backgroundColor: '#999',
|
||
|
|
},
|
||
|
|
buttonText: {
|
||
|
|
color: '#fff',
|
||
|
|
fontSize: 16,
|
||
|
|
fontWeight: 'bold',
|
||
|
|
},
|
||
|
|
updateInfoContainer: {
|
||
|
|
backgroundColor: 'rgba(52, 199, 89, 0.1)',
|
||
|
|
padding: 15,
|
||
|
|
borderRadius: 10,
|
||
|
|
marginBottom: 20,
|
||
|
|
width: '100%',
|
||
|
|
},
|
||
|
|
updateInfoText: {
|
||
|
|
fontSize: 14,
|
||
|
|
textAlign: 'center',
|
||
|
|
},
|
||
|
|
instructionsContainer: {
|
||
|
|
backgroundColor: 'rgba(255, 149, 0, 0.1)',
|
||
|
|
padding: 15,
|
||
|
|
borderRadius: 10,
|
||
|
|
width: '100%',
|
||
|
|
},
|
||
|
|
instructionsTitle: {
|
||
|
|
fontSize: 16,
|
||
|
|
fontWeight: 'bold',
|
||
|
|
marginBottom: 10,
|
||
|
|
},
|
||
|
|
instructionsText: {
|
||
|
|
fontSize: 13,
|
||
|
|
lineHeight: 20,
|
||
|
|
},
|
||
|
|
});
|