2026-03-09 21:29:03 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* PrivateChatInfoScreen 私聊聊天管理页面
|
|
|
|
|
|
* 胡萝卜BBS - 私聊设置界面
|
|
|
|
|
|
* 参考QQ和微信的实现,提供聊天管理功能
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
View,
|
|
|
|
|
|
StyleSheet,
|
|
|
|
|
|
ScrollView,
|
|
|
|
|
|
TouchableOpacity,
|
|
|
|
|
|
Alert,
|
|
|
|
|
|
Switch,
|
|
|
|
|
|
} from 'react-native';
|
|
|
|
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
2026-03-24 14:21:31 +08:00
|
|
|
|
import { useRouter, useLocalSearchParams } from 'expo-router';
|
2026-03-09 21:29:03 +08:00
|
|
|
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
|
|
|
|
|
import { colors, spacing, fontSizes, borderRadius, shadows } from '../../theme';
|
|
|
|
|
|
import { useAuthStore } from '../../stores';
|
|
|
|
|
|
import { authService } from '../../services/authService';
|
|
|
|
|
|
import { messageService } from '../../services/messageService';
|
|
|
|
|
|
import { ApiError } from '../../services/api';
|
|
|
|
|
|
import {
|
|
|
|
|
|
clearConversationMessages,
|
|
|
|
|
|
getConversationCache,
|
|
|
|
|
|
} from '../../services/database';
|
|
|
|
|
|
import { messageManager } from '../../stores/messageManager';
|
|
|
|
|
|
import { userManager } from '../../stores/userManager';
|
|
|
|
|
|
import { Avatar, Text, Button, Loading, Divider } from '../../components/common';
|
|
|
|
|
|
import { User } from '../../types';
|
2026-03-24 14:21:31 +08:00
|
|
|
|
import * as hrefs from '../../navigation/hrefs';
|
2026-03-24 15:39:28 +08:00
|
|
|
|
import { AppBackButton } from '../../components/common';
|
2026-03-09 21:29:03 +08:00
|
|
|
|
|
|
|
|
|
|
const PrivateChatInfoScreen: React.FC = () => {
|
2026-03-24 14:21:31 +08:00
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const raw = useLocalSearchParams<{
|
|
|
|
|
|
conversationId?: string;
|
|
|
|
|
|
userId?: string;
|
|
|
|
|
|
userName?: string;
|
|
|
|
|
|
userAvatar?: string;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
const conversationId = raw.conversationId ?? '';
|
|
|
|
|
|
const userId = raw.userId ?? '';
|
|
|
|
|
|
const userName = raw.userName;
|
|
|
|
|
|
const userAvatar = raw.userAvatar;
|
2026-03-09 21:29:03 +08:00
|
|
|
|
const { currentUser } = useAuthStore();
|
|
|
|
|
|
|
|
|
|
|
|
// 用户信息状态
|
|
|
|
|
|
const [user, setUser] = useState<User | null>(null);
|
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
|
const [isBlocked, setIsBlocked] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 聊天设置状态
|
|
|
|
|
|
const [isMuted, setIsMuted] = useState(false);
|
|
|
|
|
|
const [isPinned, setIsPinned] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载用户信息
|
|
|
|
|
|
const loadUserInfo = useCallback(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
const userData = await userManager.getUserById(userId);
|
|
|
|
|
|
setUser(userData || null);
|
|
|
|
|
|
const blockStatus = await authService.getBlockStatus(userId);
|
|
|
|
|
|
setIsBlocked(blockStatus);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载用户信息失败:', error);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [userId]);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载聊天设置
|
|
|
|
|
|
const loadChatSettings = useCallback(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const currentConv = messageManager.getConversation(conversationId);
|
|
|
|
|
|
if (currentConv) {
|
|
|
|
|
|
setIsPinned(Boolean(currentConv.is_pinned));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const cached = await getConversationCache(conversationId);
|
|
|
|
|
|
if (cached) {
|
|
|
|
|
|
setIsPinned(Boolean((cached as any).is_pinned));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const detail = await messageService.getConversationById(conversationId);
|
|
|
|
|
|
setIsPinned(Boolean(detail.is_pinned));
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('加载聊天设置失败:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [conversationId]);
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
loadUserInfo();
|
|
|
|
|
|
loadChatSettings();
|
|
|
|
|
|
}, [loadUserInfo, loadChatSettings]);
|
|
|
|
|
|
|
|
|
|
|
|
// 切换免打扰(仅本地状态,实际需要API支持)
|
|
|
|
|
|
const toggleMute = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const newValue = !isMuted;
|
|
|
|
|
|
setIsMuted(newValue);
|
|
|
|
|
|
// TODO: 调用API更新免打扰状态
|
|
|
|
|
|
// await conversationService.updateConversationMute(conversationId, newValue);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
setIsMuted(!isMuted);
|
|
|
|
|
|
Alert.alert('错误', '设置免打扰失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 切换置顶
|
|
|
|
|
|
const togglePin = async () => {
|
|
|
|
|
|
const nextValue = !isPinned;
|
|
|
|
|
|
setIsPinned(nextValue);
|
|
|
|
|
|
try {
|
|
|
|
|
|
await messageService.setConversationPinned(conversationId, nextValue);
|
|
|
|
|
|
messageManager.updateConversation(conversationId, { is_pinned: nextValue });
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
setIsPinned(!nextValue);
|
|
|
|
|
|
Alert.alert('错误', '设置置顶失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 清空聊天记录
|
|
|
|
|
|
const handleClearHistory = () => {
|
|
|
|
|
|
Alert.alert(
|
|
|
|
|
|
'清空聊天记录',
|
|
|
|
|
|
'确定要清空与该用户的所有聊天记录吗?此操作不可恢复。',
|
|
|
|
|
|
[
|
|
|
|
|
|
{ text: '取消', style: 'cancel' },
|
|
|
|
|
|
{
|
|
|
|
|
|
text: '清空',
|
|
|
|
|
|
style: 'destructive',
|
|
|
|
|
|
onPress: async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await clearConversationMessages(conversationId);
|
|
|
|
|
|
Alert.alert('成功', '聊天记录已清空');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
Alert.alert('错误', '清空聊天记录失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 查找聊天记录
|
|
|
|
|
|
const handleSearchMessages = () => {
|
|
|
|
|
|
// TODO: 实现聊天记录搜索功能
|
|
|
|
|
|
Alert.alert('提示', '聊天记录搜索功能开发中');
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 查看用户资料
|
|
|
|
|
|
const handleViewProfile = () => {
|
2026-03-24 14:21:31 +08:00
|
|
|
|
router.push(hrefs.hrefUserProfile(userId));
|
2026-03-09 21:29:03 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 举报/投诉
|
|
|
|
|
|
const handleReport = () => {
|
|
|
|
|
|
Alert.alert(
|
|
|
|
|
|
'举报用户',
|
|
|
|
|
|
'请选择举报原因',
|
|
|
|
|
|
[
|
|
|
|
|
|
{ text: '取消', style: 'cancel' },
|
|
|
|
|
|
{ text: '骚扰信息', onPress: () => submitReport('harassment') },
|
|
|
|
|
|
{ text: '欺诈行为', onPress: () => submitReport('fraud') },
|
|
|
|
|
|
{ text: '不当内容', onPress: () => submitReport('inappropriate') },
|
|
|
|
|
|
{ text: '其他原因', onPress: () => submitReport('other') },
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const submitReport = async (reason: string) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// TODO: 实现举报API
|
|
|
|
|
|
Alert.alert('举报已提交', '我们会尽快处理您的举报,感谢您的反馈');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
Alert.alert('错误', '举报提交失败,请稍后重试');
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const handleBlockUser = () => {
|
|
|
|
|
|
if (isBlocked) {
|
|
|
|
|
|
Alert.alert(
|
|
|
|
|
|
'取消拉黑',
|
|
|
|
|
|
'确定取消拉黑该用户吗?',
|
|
|
|
|
|
[
|
|
|
|
|
|
{ text: '取消', style: 'cancel' },
|
|
|
|
|
|
{
|
|
|
|
|
|
text: '确定',
|
|
|
|
|
|
onPress: async () => {
|
|
|
|
|
|
const ok = await authService.unblockUser(userId);
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
|
Alert.alert('错误', '取消拉黑失败,请稍后重试');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setIsBlocked(false);
|
|
|
|
|
|
Alert.alert('成功', '已取消拉黑');
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Alert.alert(
|
|
|
|
|
|
'拉黑用户',
|
|
|
|
|
|
'拉黑后,对方将无法给你发送私聊消息,且你们会互相移除关注关系。',
|
|
|
|
|
|
[
|
|
|
|
|
|
{ text: '取消', style: 'cancel' },
|
|
|
|
|
|
{
|
|
|
|
|
|
text: '确认拉黑',
|
|
|
|
|
|
style: 'destructive',
|
|
|
|
|
|
onPress: async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const ok = await authService.blockUser(userId);
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
|
Alert.alert('错误', '拉黑失败,请稍后重试');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
setIsBlocked(true);
|
|
|
|
|
|
messageManager.removeConversation(conversationId);
|
2026-03-24 14:21:31 +08:00
|
|
|
|
router.replace(hrefs.hrefMessages());
|
2026-03-09 21:29:03 +08:00
|
|
|
|
Alert.alert('已拉黑', '你已成功拉黑该用户');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
Alert.alert('错误', '拉黑失败,请稍后重试');
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 删除并退出聊天
|
|
|
|
|
|
const handleDeleteAndExit = () => {
|
|
|
|
|
|
Alert.alert(
|
|
|
|
|
|
'删除聊天',
|
|
|
|
|
|
'确定要删除与该用户的聊天吗?聊天记录将被清空。',
|
|
|
|
|
|
[
|
|
|
|
|
|
{ text: '取消', style: 'cancel' },
|
|
|
|
|
|
{
|
|
|
|
|
|
text: '删除',
|
|
|
|
|
|
style: 'destructive',
|
|
|
|
|
|
onPress: async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await messageService.deleteConversationForSelf(conversationId);
|
|
|
|
|
|
messageManager.removeConversation(conversationId);
|
|
|
|
|
|
// 返回消息列表
|
2026-03-24 14:21:31 +08:00
|
|
|
|
router.replace(hrefs.hrefMessages());
|
2026-03-09 21:29:03 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const msg = error instanceof ApiError ? error.message : '删除聊天失败';
|
|
|
|
|
|
Alert.alert('错误', msg);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染设置项(带开关)
|
|
|
|
|
|
const renderSwitchItem = (
|
|
|
|
|
|
icon: string,
|
|
|
|
|
|
title: string,
|
|
|
|
|
|
value: boolean,
|
|
|
|
|
|
onValueChange: () => void
|
|
|
|
|
|
) => (
|
|
|
|
|
|
<View style={styles.settingItem}>
|
|
|
|
|
|
<View style={styles.settingIconContainer}>
|
|
|
|
|
|
<MaterialCommunityIcons name={icon as any} size={20} color={colors.primary.main} />
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<Text variant="body" style={styles.settingTitle}>
|
|
|
|
|
|
{title}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<Switch
|
|
|
|
|
|
value={value}
|
|
|
|
|
|
onValueChange={onValueChange}
|
|
|
|
|
|
trackColor={{ false: '#E0E0E0', true: colors.primary.light }}
|
|
|
|
|
|
thumbColor={value ? colors.primary.main : '#F5F5F5'}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染设置项(带箭头)
|
|
|
|
|
|
const renderActionItem = (
|
|
|
|
|
|
icon: string,
|
|
|
|
|
|
title: string,
|
|
|
|
|
|
onPress: () => void,
|
|
|
|
|
|
danger: boolean = false
|
|
|
|
|
|
) => (
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={styles.settingItem}
|
|
|
|
|
|
onPress={onPress}
|
|
|
|
|
|
activeOpacity={0.7}
|
|
|
|
|
|
>
|
|
|
|
|
|
<View style={[styles.settingIconContainer, danger && styles.settingIconDanger]}>
|
|
|
|
|
|
<MaterialCommunityIcons
|
|
|
|
|
|
name={icon as any}
|
|
|
|
|
|
size={20}
|
|
|
|
|
|
color={danger ? colors.error.main : colors.primary.main}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<Text variant="body" style={danger ? [styles.settingTitle, styles.dangerText] : styles.settingTitle}>
|
|
|
|
|
|
{title}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<MaterialCommunityIcons name="chevron-right" size={22} color={colors.text.hint} />
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (loading) {
|
|
|
|
|
|
return (
|
2026-03-24 15:39:28 +08:00
|
|
|
|
<SafeAreaView style={styles.container} edges={['top', 'bottom']}>
|
|
|
|
|
|
<View style={styles.pageHeader}>
|
|
|
|
|
|
<AppBackButton onPress={() => router.back()} />
|
|
|
|
|
|
<Text variant="h3" style={styles.pageTitle}>私聊信息</Text>
|
|
|
|
|
|
<View style={styles.pageHeaderPlaceholder} />
|
|
|
|
|
|
</View>
|
2026-03-09 21:29:03 +08:00
|
|
|
|
<Loading />
|
|
|
|
|
|
</SafeAreaView>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const displayUser = user || {
|
|
|
|
|
|
id: userId,
|
|
|
|
|
|
nickname: userName,
|
|
|
|
|
|
avatar: userAvatar,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2026-03-24 15:39:28 +08:00
|
|
|
|
<SafeAreaView style={styles.container} edges={['top', 'bottom']}>
|
|
|
|
|
|
<View style={styles.pageHeader}>
|
|
|
|
|
|
<AppBackButton onPress={() => router.back()} />
|
|
|
|
|
|
<Text variant="h3" style={styles.pageTitle}>私聊信息</Text>
|
|
|
|
|
|
<View style={styles.pageHeaderPlaceholder} />
|
|
|
|
|
|
</View>
|
2026-03-09 21:29:03 +08:00
|
|
|
|
<ScrollView
|
|
|
|
|
|
style={styles.scrollView}
|
|
|
|
|
|
contentContainerStyle={styles.scrollContent}
|
|
|
|
|
|
showsVerticalScrollIndicator={false}
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* 用户基本信息卡片 */}
|
|
|
|
|
|
<View style={styles.headerCard}>
|
|
|
|
|
|
<TouchableOpacity
|
|
|
|
|
|
style={styles.userHeader}
|
|
|
|
|
|
onPress={handleViewProfile}
|
|
|
|
|
|
activeOpacity={0.7}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Avatar
|
|
|
|
|
|
source={displayUser.avatar}
|
|
|
|
|
|
size={90}
|
|
|
|
|
|
name={displayUser.nickname || ''}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<View style={styles.userInfo}>
|
|
|
|
|
|
<Text variant="h3" style={styles.userName} numberOfLines={1}>
|
|
|
|
|
|
{displayUser.nickname || userName || '用户'}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
{(displayUser as any).username && (
|
|
|
|
|
|
<Text variant="caption" color={colors.text.secondary}>
|
|
|
|
|
|
@{(displayUser as any).username}
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</View>
|
|
|
|
|
|
<MaterialCommunityIcons name="chevron-right" size={24} color={colors.text.hint} />
|
|
|
|
|
|
</TouchableOpacity>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 聊天设置 */}
|
|
|
|
|
|
<View style={styles.section}>
|
|
|
|
|
|
<Text variant="caption" color={colors.text.secondary} style={styles.sectionTitle}>
|
|
|
|
|
|
聊天设置
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={styles.card}>
|
|
|
|
|
|
{renderSwitchItem('bell-off-outline', '消息免打扰', isMuted, toggleMute)}
|
|
|
|
|
|
<Divider style={styles.divider} />
|
|
|
|
|
|
{renderSwitchItem('pin-outline', '置顶聊天', isPinned, togglePin)}
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 聊天记录管理 */}
|
|
|
|
|
|
<View style={styles.section}>
|
|
|
|
|
|
<Text variant="caption" color={colors.text.secondary} style={styles.sectionTitle}>
|
|
|
|
|
|
聊天记录
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={styles.card}>
|
|
|
|
|
|
{renderActionItem('magnify', '查找聊天记录', handleSearchMessages)}
|
|
|
|
|
|
<Divider style={styles.divider} />
|
|
|
|
|
|
{renderActionItem('delete-sweep-outline', '清空聊天记录', handleClearHistory, true)}
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 其他操作 */}
|
|
|
|
|
|
<View style={styles.section}>
|
|
|
|
|
|
<Text variant="caption" color={colors.text.secondary} style={styles.sectionTitle}>
|
|
|
|
|
|
其他
|
|
|
|
|
|
</Text>
|
|
|
|
|
|
<View style={styles.card}>
|
|
|
|
|
|
{renderActionItem('shield-alert-outline', '投诉', handleReport, true)}
|
|
|
|
|
|
<Divider style={styles.divider} />
|
|
|
|
|
|
{renderActionItem(
|
|
|
|
|
|
isBlocked ? 'account-check-outline' : 'account-cancel-outline',
|
|
|
|
|
|
isBlocked ? '取消拉黑' : '拉黑用户',
|
|
|
|
|
|
handleBlockUser,
|
|
|
|
|
|
true
|
|
|
|
|
|
)}
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 删除聊天按钮 */}
|
|
|
|
|
|
<View style={styles.section}>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
title="删除并退出聊天"
|
|
|
|
|
|
onPress={handleDeleteAndExit}
|
|
|
|
|
|
variant="danger"
|
|
|
|
|
|
style={styles.deleteButton}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</View>
|
|
|
|
|
|
</ScrollView>
|
|
|
|
|
|
</SafeAreaView>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
|
|
container: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
backgroundColor: colors.background.default,
|
|
|
|
|
|
},
|
2026-03-24 15:39:28 +08:00
|
|
|
|
pageHeader: {
|
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
|
|
paddingHorizontal: spacing.md,
|
|
|
|
|
|
paddingVertical: spacing.sm,
|
|
|
|
|
|
backgroundColor: colors.background.paper,
|
|
|
|
|
|
borderBottomWidth: 1,
|
|
|
|
|
|
borderBottomColor: colors.divider,
|
|
|
|
|
|
},
|
|
|
|
|
|
pageTitle: {
|
|
|
|
|
|
fontWeight: '600',
|
|
|
|
|
|
},
|
|
|
|
|
|
pageHeaderPlaceholder: {
|
|
|
|
|
|
width: 40,
|
|
|
|
|
|
height: 40,
|
|
|
|
|
|
},
|
2026-03-09 21:29:03 +08:00
|
|
|
|
scrollView: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
scrollContent: {
|
|
|
|
|
|
paddingBottom: spacing.xl,
|
|
|
|
|
|
},
|
|
|
|
|
|
headerCard: {
|
|
|
|
|
|
backgroundColor: colors.background.paper,
|
|
|
|
|
|
marginHorizontal: spacing.md,
|
|
|
|
|
|
marginTop: spacing.md,
|
|
|
|
|
|
borderRadius: borderRadius.lg,
|
|
|
|
|
|
padding: spacing.lg,
|
|
|
|
|
|
...shadows.sm,
|
|
|
|
|
|
},
|
|
|
|
|
|
userHeader: {
|
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
},
|
|
|
|
|
|
userInfo: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
marginLeft: spacing.md,
|
|
|
|
|
|
},
|
|
|
|
|
|
userName: {
|
|
|
|
|
|
fontWeight: '600',
|
|
|
|
|
|
marginBottom: spacing.xs,
|
|
|
|
|
|
},
|
|
|
|
|
|
section: {
|
|
|
|
|
|
marginTop: spacing.lg,
|
|
|
|
|
|
paddingHorizontal: spacing.md,
|
|
|
|
|
|
},
|
|
|
|
|
|
sectionTitle: {
|
|
|
|
|
|
marginBottom: spacing.sm,
|
|
|
|
|
|
marginLeft: spacing.sm,
|
|
|
|
|
|
fontWeight: '500',
|
|
|
|
|
|
},
|
|
|
|
|
|
card: {
|
|
|
|
|
|
backgroundColor: colors.background.paper,
|
|
|
|
|
|
borderRadius: borderRadius.lg,
|
|
|
|
|
|
...shadows.sm,
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
},
|
|
|
|
|
|
settingItem: {
|
|
|
|
|
|
flexDirection: 'row',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
paddingVertical: spacing.sm,
|
|
|
|
|
|
paddingHorizontal: spacing.md,
|
|
|
|
|
|
},
|
|
|
|
|
|
settingIconContainer: {
|
|
|
|
|
|
width: 36,
|
|
|
|
|
|
height: 36,
|
|
|
|
|
|
borderRadius: borderRadius.md,
|
|
|
|
|
|
backgroundColor: colors.primary.light + '20',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
marginRight: spacing.md,
|
|
|
|
|
|
},
|
|
|
|
|
|
settingIconDanger: {
|
|
|
|
|
|
backgroundColor: colors.error.light + '20',
|
|
|
|
|
|
},
|
|
|
|
|
|
settingTitle: {
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
dangerText: {
|
|
|
|
|
|
color: colors.error.main,
|
|
|
|
|
|
},
|
|
|
|
|
|
divider: {
|
|
|
|
|
|
marginLeft: spacing.xl + 36,
|
|
|
|
|
|
width: 'auto',
|
|
|
|
|
|
marginVertical: spacing.xs,
|
|
|
|
|
|
},
|
|
|
|
|
|
deleteButton: {
|
|
|
|
|
|
marginTop: spacing.sm,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export default PrivateChatInfoScreen;
|