import { useCallback, useEffect, useRef, useState } from 'react'; import { StatusBar, StyleSheet, View } from 'react-native'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; import ChatArea from './components/ChatArea'; import InputArea from './components/InputArea'; import { fetchHistory, sendMessage, syncHistory } from './api'; import { loadMessages, mergeMessages, saveMessages } from './storage'; import type { Message } from './types'; export default function App() { const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(false); const [synced, setSynced] = useState(false); const [refreshing, setRefreshing] = useState(false); const nextId = useRef(1); // 启动:先读本地缓存,再异步拉远端 useEffect(() => { (async () => { const local = await loadMessages(); if (local.length > 0) { setMessages(local); nextId.current = Math.max(...local.map(m => m.id)) + 1; } const remote = await fetchHistory(); if (remote.length > 0) { const merged = mergeMessages(local, remote); setMessages(merged); nextId.current = Math.max(...merged.map(m => m.id)) + 1; await saveMessages(merged); } else if (local.length > 0) { // 服务端没数据但本地有,把本地推上去 await syncHistory(local); } setSynced(true); })(); }, []); // synced 后,每次 messages 变化同步写本地 + 远端 useEffect(() => { if (!synced || messages.length === 0) return; saveMessages(messages); syncHistory(messages); }, [messages, synced]); const handleSend = useCallback( async (text: string) => { const userMsg: Message = { id: nextId.current++, role: 'user', text, }; const withUser = [...messages, userMsg]; setMessages(withUser); setLoading(true); try { const reply = await sendMessage(withUser); const shenyanMsg: Message = { id: nextId.current++, role: 'shenyan', text: reply, }; setMessages(prev => [...prev, shenyanMsg]); } catch { const errMsg: Message = { id: nextId.current++, role: 'shenyan', text: '连接失败', }; setMessages(prev => [...prev, errMsg]); } finally { setLoading(false); } }, [messages], ); const handleRefresh = useCallback(async () => { setRefreshing(true); const remote = await fetchHistory(); if (remote.length > 0) { setMessages(prev => { const merged = mergeMessages(prev, remote); nextId.current = Math.max(...merged.map(m => m.id)) + 1; return merged; }); } setRefreshing(false); }, []); return ( ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#000', }, });