Initial frontend repository commit.
Include app source and update .gitignore to exclude local release artifacts and signing files. Made-with: Cursor
This commit is contained in:
147
src/components/business/NotificationItem.tsx
Normal file
147
src/components/business/NotificationItem.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* NotificationItem 通知项组件
|
||||
* 根据通知类型显示不同图标和内容
|
||||
*
|
||||
* @deprecated 请使用 SystemMessageItem 组件代替
|
||||
* 该组件使用旧的 Notification 类型,新功能请使用 SystemMessageItem
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { zhCN } from 'date-fns/locale';
|
||||
import { colors, spacing, borderRadius } from '../../theme';
|
||||
import { Notification, NotificationType } from '../../types';
|
||||
import Text from '../common/Text';
|
||||
import Avatar from '../common/Avatar';
|
||||
|
||||
interface NotificationItemProps {
|
||||
notification: Notification;
|
||||
onPress: () => void;
|
||||
}
|
||||
|
||||
// 通知类型到图标和颜色的映射
|
||||
const getNotificationIcon = (type: NotificationType): { icon: string; color: string } => {
|
||||
switch (type) {
|
||||
case 'like_post':
|
||||
return { icon: 'heart', color: colors.error.main };
|
||||
case 'like_comment':
|
||||
return { icon: 'heart', color: colors.error.main };
|
||||
case 'comment':
|
||||
return { icon: 'comment', color: colors.info.main };
|
||||
case 'reply':
|
||||
return { icon: 'reply', color: colors.info.main };
|
||||
case 'follow':
|
||||
return { icon: 'account-plus', color: colors.primary.main };
|
||||
case 'mention':
|
||||
return { icon: 'at', color: colors.warning.main };
|
||||
case 'system':
|
||||
return { icon: 'information', color: colors.text.secondary };
|
||||
default:
|
||||
return { icon: 'bell', color: colors.text.secondary };
|
||||
}
|
||||
};
|
||||
|
||||
const NotificationItem: React.FC<NotificationItemProps> = ({
|
||||
notification,
|
||||
onPress,
|
||||
}) => {
|
||||
// 格式化时间
|
||||
const formatTime = (dateString: string): string => {
|
||||
try {
|
||||
return formatDistanceToNow(new Date(dateString), {
|
||||
addSuffix: true,
|
||||
locale: zhCN,
|
||||
});
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const { icon, color } = getNotificationIcon(notification.type);
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.container, !notification.isRead && styles.unread]}
|
||||
onPress={onPress}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
{/* 通知图标/头像 */}
|
||||
<View style={styles.iconContainer}>
|
||||
{notification.type === 'follow' && notification.data.userId ? (
|
||||
<Avatar
|
||||
source={null}
|
||||
size={40}
|
||||
name={notification.title}
|
||||
/>
|
||||
) : (
|
||||
<View style={[styles.iconWrapper, { backgroundColor: color + '20' }]}>
|
||||
<MaterialCommunityIcons name={icon as any} size={20} color={color} />
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 通知内容 */}
|
||||
<View style={styles.content}>
|
||||
<View style={styles.textContainer}>
|
||||
<Text
|
||||
variant="body"
|
||||
numberOfLines={2}
|
||||
style={!notification.isRead ? styles.unreadText : undefined}
|
||||
>
|
||||
{notification.content}
|
||||
</Text>
|
||||
</View>
|
||||
<Text variant="caption" color={colors.text.secondary}>
|
||||
{formatTime(notification.createdAt)}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* 未读标记 */}
|
||||
{!notification.isRead && <View style={styles.unreadDot} />}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: spacing.lg,
|
||||
backgroundColor: colors.background.paper,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: colors.divider,
|
||||
},
|
||||
unread: {
|
||||
backgroundColor: colors.primary.light + '10',
|
||||
},
|
||||
iconContainer: {
|
||||
marginRight: spacing.md,
|
||||
},
|
||||
iconWrapper: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
},
|
||||
textContainer: {
|
||||
marginBottom: spacing.xs,
|
||||
},
|
||||
unreadText: {
|
||||
fontWeight: '600',
|
||||
},
|
||||
unreadDot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: colors.primary.main,
|
||||
marginLeft: spacing.sm,
|
||||
},
|
||||
});
|
||||
|
||||
export default NotificationItem;
|
||||
Reference in New Issue
Block a user