refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
This commit is contained in:
@@ -1,147 +0,0 @@
|
||||
/**
|
||||
* 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;
|
||||
@@ -5,7 +5,6 @@
|
||||
export { default as PostCard } from './PostCard';
|
||||
export { default as CommentItem } from './CommentItem';
|
||||
export { default as UserProfileHeader } from './UserProfileHeader';
|
||||
export { default as NotificationItem } from './NotificationItem';
|
||||
export { default as SystemMessageItem } from './SystemMessageItem';
|
||||
export { default as SearchBar } from './SearchBar';
|
||||
export { default as TabBar } from './TabBar';
|
||||
|
||||
Reference in New Issue
Block a user