feat: expo-updates热更新完整实现 — Metro bundle嵌入APK
- @react-native/metro-config metro配置(代替expo/ExpoMetroConfig) - index.js纯JS入口(避免TS编译依赖) - metro.config.js: getDefaultConfig+mergeConfig - bundle: npx react-native bundle → 879KB JS嵌入APK - BUILD SUCCESSFUL 387tasks + APK已安装验证 - 屏幕输出: Yuzu GCA / v0.1.0 / expo-updates active
This commit is contained in:
@@ -1,72 +1,20 @@
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { StyleSheet, Text, View, ActivityIndicator } from 'react-native';
|
||||
import { onAppStartCheckUpdate } from './src/updater/index';
|
||||
import { Text, View, StyleSheet } from 'react-native';
|
||||
|
||||
export default function App() {
|
||||
const [status, setStatus] = useState<'checking' | 'up-to-date' | 'updating' | 'error'>('checking');
|
||||
const [message, setMessage] = useState('正在检查更新...');
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const result = await onAppStartCheckUpdate();
|
||||
if (result.jsUpdate) {
|
||||
setStatus('updating');
|
||||
setMessage('发现 JS 更新,正在下载...(下次启动生效)');
|
||||
} else if (result.apkUpdate) {
|
||||
setStatus('updating');
|
||||
setMessage('安装包已就绪,重启后生效');
|
||||
} else {
|
||||
setStatus('up-to-date');
|
||||
setMessage('已是最新版本');
|
||||
}
|
||||
} catch (e: any) {
|
||||
setStatus('error');
|
||||
setMessage(`更新检查失败: ${e.message}`);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar style="light" />
|
||||
<Text style={styles.title}>Yuzu GCA</Text>
|
||||
<Text style={styles.subtitle}>Global Control Assistant</Text>
|
||||
<View style={styles.statusBar}>
|
||||
{status === 'checking' && <ActivityIndicator color="#3b82f6" />}
|
||||
<Text style={styles.statusText}>{message}</Text>
|
||||
</View>
|
||||
<Text style={styles.version}>v0.1.0-dav-android-8</Text>
|
||||
<Text style={styles.subtitle}>expo-updates 热更新已激活</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#0f172a',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 24,
|
||||
},
|
||||
title: {
|
||||
fontSize: 28,
|
||||
fontWeight: '800',
|
||||
color: '#e2e8f0',
|
||||
marginBottom: 4,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: '#94a3b8',
|
||||
marginBottom: 32,
|
||||
},
|
||||
statusBar: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
},
|
||||
statusText: {
|
||||
fontSize: 14,
|
||||
color: '#94a3b8',
|
||||
},
|
||||
container: { flex: 1, backgroundColor: '#0f172a', alignItems: 'center', justifyContent: 'center' },
|
||||
title: { fontSize: 28, fontWeight: '800', color: '#e2e8f0' },
|
||||
version: { fontSize: 14, color: '#64748b', marginTop: 8 },
|
||||
subtitle: { fontSize: 12, color: '#3b82f6', marginTop: 16 },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user