import React, { useEffect, useMemo, useState } from 'react';
import { View, StyleSheet, TouchableOpacity, Alert, ScrollView } from 'react-native';
import { useRouter, useLocalSearchParams } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { SafeAreaView } from 'react-native-safe-area-context';
import { spacing, borderRadius, shadows, useAppColors, type AppColors } from '../../theme';
import { Avatar, Text } from '../../components/common';
import * as hrefs from '../../navigation/hrefs';
import { routePayloadCache } from '../../stores';
import { groupService } from '@/services/message';
import { groupManager } from '../../stores/group';
import { userManager } from '../../stores/user';
import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared';
const GroupRequestDetailScreen: React.FC = () => {
const colors = useAppColors();
const styles = useMemo(() => createGroupRequestDetailStyles(colors), [colors]);
const router = useRouter();
const { messageId } = useLocalSearchParams<{ messageId?: string }>();
const message = messageId ? routePayloadCache.getSystemMessage(messageId) : undefined;
if (!message) {
return (
无法加载该消息,请从通知列表重新打开。
router.back()} style={styles.backBtn}>
返回
);
}
const { extra_data } = message;
const [submitting, setSubmitting] = useState(false);
const [memberCount, setMemberCount] = useState(null);
const [loadingGroup, setLoadingGroup] = useState(false);
const requestType = extra_data?.request_type;
const requestStatus = extra_data?.request_status;
const reviewerName = extra_data?.actor_name || extra_data?.operator_name || '管理员';
const canAction =
requestStatus === 'pending' &&
(message.system_type === 'group_join_apply' || message.system_type === 'group_invite');
const processedText =
requestStatus === 'accepted'
? `${reviewerName}已同意`
: requestStatus === 'rejected'
? `${reviewerName}已拒绝`
: '该请求已处理';
const applicantName = useMemo(() => {
if (requestType === 'invite') {
return extra_data?.target_user_name || '被邀请用户';
}
return extra_data?.actor_name || '申请用户';
}, [requestType, extra_data]);
const applicantAvatar = useMemo(() => {
if (requestType === 'invite') {
return extra_data?.target_user_avatar || '';
}
return extra_data?.avatar_url || '';
}, [requestType, extra_data]);
const applicantId = useMemo(() => {
if (requestType === 'invite') {
return extra_data?.target_user_id;
}
return extra_data?.actor_id_str;
}, [requestType, extra_data]);
useEffect(() => {
const loadGroupInfo = async () => {
if (!extra_data?.group_id) return;
setLoadingGroup(true);
try {
const group = await groupManager.getGroup(String(extra_data.group_id));
setMemberCount(group.member_count ?? null);
} catch {
setMemberCount(null);
} finally {
setLoadingGroup(false);
}
};
loadGroupInfo();
}, [extra_data?.group_id]);
const handleDecision = async (approve: boolean) => {
const flag = extra_data?.flag;
const groupId = extra_data?.group_id;
if (!flag) {
Alert.alert('提示', '缺少请求标识,无法处理');
return;
}
if (!groupId) {
Alert.alert('提示', '缺少群组标识,无法处理');
return;
}
setSubmitting(true);
try {
if (message.system_type === 'group_invite') {
await groupService.respondInvite(String(groupId), {
flag,
approve,
});
} else {
await groupService.reviewJoinRequest(String(groupId), {
flag,
approve,
});
}
Alert.alert('成功', approve ? '已同意申请' : '已拒绝申请', [
{ text: '确定', onPress: () => router.back() },
]);
} catch (error) {
Alert.alert('操作失败', '请稍后重试');
} finally {
setSubmitting(false);
}
};
const handleOpenUser = async () => {
if (!applicantId) return;
const user = await userManager.getUserById(applicantId);
if (user?.id) {
router.push(hrefs.hrefUserProfile(String(user.id)));
}
};
return (
用户信息
{applicantName}
{requestType === 'invite' ? '被邀请加入' : '申请加入'}
{applicantId ? (
) : null}
{requestType === 'invite' && (
邀请人:{extra_data?.actor_name || '群成员'}
)}
handleDecision(false)}
onApprove={() => handleDecision(true)}
processedText={processedText}
/>
);
};
function createGroupRequestDetailStyles(colors: AppColors) {
return StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.background.default,
},
emptyWrap: {
flex: 1,
padding: spacing.lg,
justifyContent: 'center',
alignItems: 'center',
gap: spacing.md,
},
backBtn: {
padding: spacing.sm,
},
scrollView: {
flex: 1,
},
scrollContent: {
padding: spacing.lg,
paddingBottom: spacing.xl,
},
card: {
backgroundColor: colors.background.paper,
borderRadius: borderRadius.lg,
padding: spacing.lg,
marginBottom: spacing.md,
...shadows.sm,
},
sectionTitle: {
marginBottom: spacing.sm,
},
row: {
flexDirection: 'row',
alignItems: 'center',
},
meta: {
marginLeft: spacing.md,
flex: 1,
},
name: {
marginBottom: 2,
},
subDesc: {
marginTop: spacing.sm,
},
});
}
export default GroupRequestDetailScreen;