Files
life-echo/app-ios/app/chat/[id].tsx
penghanyuan 748f252c2f add ios app
2026-01-31 21:20:50 +01:00

187 lines
4.9 KiB
TypeScript

import { ChatBubble, TimeSeparator, TypingIndicator } from '@/components/chat/ChatBubble';
import { ChatInput } from '@/components/chat/ChatInput';
import { AppColors } from '@/constants/theme';
import {
getCurrentTimeString,
getRandomAIResponse,
Message,
mockConversations,
mockMessages,
} from '@/data/mockData';
import { Ionicons } from '@expo/vector-icons';
import { router, useLocalSearchParams } from 'expo-router';
import React, { useEffect, useRef, useState } from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
export default function ChatDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
const scrollViewRef = useRef<ScrollView>(null);
const [messages, setMessages] = useState<Message[]>(mockMessages);
const [isTyping, setIsTyping] = useState(false);
// Find conversation info
const conversation = mockConversations.find(c => c.id === id) || mockConversations[0];
// Scroll to bottom when messages change
useEffect(() => {
setTimeout(() => {
scrollViewRef.current?.scrollToEnd({ animated: true });
}, 100);
}, [messages, isTyping]);
const handleSendMessage = (text: string) => {
// Add user message
const userMessage: Message = {
id: `m${Date.now()}`,
conversationId: id || '1',
senderType: 'user',
contentType: 'text',
content: text,
timestamp: getCurrentTimeString(),
};
setMessages(prev => [...prev, userMessage]);
// Simulate AI typing
setTimeout(() => {
setIsTyping(true);
}, 500);
// Add AI response after delay
setTimeout(() => {
setIsTyping(false);
const aiMessage: Message = {
id: `m${Date.now() + 1}`,
conversationId: id || '1',
senderType: 'ai',
contentType: 'text',
content: getRandomAIResponse(),
timestamp: getCurrentTimeString(),
};
setMessages(prev => [...prev, aiMessage]);
}, 1500 + Math.random() * 1000);
};
const handleBack = () => {
router.back();
};
return (
<SafeAreaView style={styles.container} edges={['top']}>
{/* Header */}
<View style={styles.header}>
<TouchableOpacity
style={styles.backButton}
onPress={handleBack}
activeOpacity={0.7}
>
<Ionicons name="chevron-back" size={24} color={AppColors.white} />
</TouchableOpacity>
<View style={styles.headerTitleArea}>
<Text style={styles.headerTitle}>{conversation.title}</Text>
<Text style={styles.headerStatus}>线</Text>
</View>
</View>
{/* Messages */}
<KeyboardAvoidingView
style={styles.messageContainer}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={0}
>
<ScrollView
ref={scrollViewRef}
style={styles.messageList}
contentContainerStyle={styles.messageListContent}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps="handled"
>
<TimeSeparator time="今天 14:30" />
{messages.map((message) => (
<ChatBubble key={message.id} message={message} />
))}
{isTyping && <TypingIndicator />}
</ScrollView>
{/* Input Area */}
<ChatInput
onSendMessage={handleSendMessage}
onVoicePress={() => {
// Voice input placeholder
console.log('Voice input pressed');
}}
onEmojiPress={() => {
// Emoji picker placeholder
console.log('Emoji picker pressed');
}}
onMorePress={() => {
// More options placeholder
console.log('More options pressed');
}}
/>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: AppColors.mediumPurple,
},
header: {
height: 62,
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
backgroundColor: AppColors.mediumPurple,
},
backButton: {
width: 40,
height: 40,
borderRadius: 12,
backgroundColor: 'rgba(255, 255, 255, 0.2)',
alignItems: 'center',
justifyContent: 'center',
},
headerTitleArea: {
flex: 1,
alignItems: 'center',
marginRight: 40, // Balance the back button
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
color: AppColors.white,
},
headerStatus: {
fontSize: 12,
color: 'rgba(255, 255, 255, 0.8)',
marginTop: 2,
},
messageContainer: {
flex: 1,
backgroundColor: AppColors.cream,
},
messageList: {
flex: 1,
backgroundColor: AppColors.cream,
},
messageListContent: {
paddingVertical: 16,
},
});