/** * CreateGroupScreen 创建群聊界面 * 允许用户创建新的群聊,设置群名称、描述,并选择初始成员 * 支持响应式布局 */ import React, { useState, useMemo } from 'react'; import { View, StyleSheet, ScrollView, TouchableOpacity, Alert, TextInput, FlatList, Image, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useRouter } from 'expo-router'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import * as ImagePicker from 'expo-image-picker'; import { spacing, fontSizes, borderRadius, shadows, useAppColors, type AppColors } from '../../theme'; import { groupService } from '../../services/groupService'; import { uploadService } from '../../services/uploadService'; import { Avatar, Text, Button, Loading } from '../../components/common'; import { User } from '../../types'; import MutualFollowSelectorModal from './components/MutualFollowSelectorModal'; const CreateGroupScreen: React.FC = () => { const colors = useAppColors(); const styles = useMemo(() => createCreateGroupStyles(colors), [colors]); const router = useRouter(); // 表单状态 const [groupName, setGroupName] = useState(''); const [groupDescription, setGroupDescription] = useState(''); const [groupAvatar, setGroupAvatar] = useState(null); const [selectedMembers, setSelectedMembers] = useState([]); const [selectedMemberIds, setSelectedMemberIds] = useState>(new Set()); // 提交状态 const [submitting, setSubmitting] = useState(false); const [uploadingAvatar, setUploadingAvatar] = useState(false); // 邀请成员模态框状态 const [inviteModalVisible, setInviteModalVisible] = useState(false); // 移除已选成员 const removeSelectedMember = (userId: string) => { const newSelectedIds = new Set(selectedMemberIds); newSelectedIds.delete(userId); setSelectedMemberIds(newSelectedIds); setSelectedMembers(prev => prev.filter(m => m.id !== userId)); }; // 选择群头像 const handleSelectAvatar = async () => { try { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (status !== 'granted') { Alert.alert('提示', '需要访问相册权限才能选择头像'); return; } const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: 'images', allowsEditing: true, aspect: [1, 1], quality: 0.8, }); if (!result.canceled && result.assets && result.assets.length > 0) { const selectedAsset = result.assets[0]; setUploadingAvatar(true); try { const uploadResult = await uploadService.uploadGroupAvatar({ uri: selectedAsset.uri, type: selectedAsset.mimeType || 'image/jpeg', }); if (uploadResult && uploadResult.url) { setGroupAvatar(uploadResult.url); } else { Alert.alert('上传失败', '头像上传失败,请重试'); } } catch (error) { console.error('上传头像失败:', error); Alert.alert('上传失败', '头像上传失败,请重试'); } finally { setUploadingAvatar(false); } } } catch (error) { console.error('选择头像失败:', error); Alert.alert('错误', '选择头像时发生错误'); } }; // 创建群组 const handleCreateGroup = async () => { // 验证群名称 if (!groupName.trim()) { Alert.alert('提示', '请输入群名称'); return; } if (groupName.length > 50) { Alert.alert('提示', '群名称最多50个字符'); return; } if (groupDescription.length > 500) { Alert.alert('提示', '群描述最多500个字符'); return; } setSubmitting(true); try { const memberIds = selectedMembers.map(m => m.id); const response = await groupService.createGroup({ name: groupName.trim(), description: groupDescription.trim() || undefined, member_ids: memberIds.length > 0 ? memberIds : undefined, }); // 如果设置了头像,更新群头像 if (groupAvatar && response.id) { try { await groupService.setGroupAvatar(response.id, groupAvatar); } catch (avatarError) { console.error('设置群头像失败:', avatarError); } } Alert.alert('成功', '群组创建成功', [ { text: '确定', onPress: () => router.back(), }, ]); } catch (error: any) { console.error('创建群组失败:', error); Alert.alert('创建失败', error.message || '创建群组时发生错误,请重试'); } finally { setSubmitting(false); } }; // 渲染已选成员 const renderSelectedMember = ({ item }: { item: User }) => ( removeSelectedMember(item.id)} > {item.nickname} ); const handleConfirmMembers = (users: User[]) => { setSelectedMembers(users); setSelectedMemberIds(new Set(users.map(user => user.id))); setInviteModalVisible(false); }; return ( {/* 群头像和名称区域 */} {uploadingAvatar ? ( ) : groupAvatar ? ( ) : ( )} 群名称 * {groupName.length}/50 {/* 群描述输入 */} 群描述 {groupDescription.length}/500 {/* 已选成员 */} {selectedMembers.length > 0 && ( 已选成员 {selectedMembers.length}人 item.id} horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.selectedMembersList} /> )} {/* 邀请成员按钮 */} setInviteModalVisible(true)} activeOpacity={0.8} > 邀请成员 仅可从互关好友中选择成员加入群聊 {/* 创建按钮 */}