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:
@@ -10,12 +10,10 @@ import { PaginatedData } from '../services/api';
|
||||
import {
|
||||
authService,
|
||||
postService,
|
||||
commentService,
|
||||
notificationService,
|
||||
} from '../services';
|
||||
import { userManager } from './userManager';
|
||||
import { messageManager } from './messageManager';
|
||||
import { createOptimisticUpdaterFactory } from '../utils/optimisticUpdate';
|
||||
|
||||
interface UserState {
|
||||
// 状态
|
||||
@@ -42,17 +40,10 @@ interface UserState {
|
||||
markAllNotificationsAsRead: () => Promise<void>;
|
||||
fetchNotificationBadge: () => Promise<void>;
|
||||
setMessageUnreadCount: (count: number) => void;
|
||||
fetchMessageUnreadCount: () => Promise<void>;
|
||||
addSearchHistory: (keyword: string) => void;
|
||||
clearSearchHistory: () => void;
|
||||
|
||||
// 互动操作
|
||||
likePost: (postId: string) => Promise<void>;
|
||||
unlikePost: (postId: string) => Promise<void>;
|
||||
favoritePost: (postId: string) => Promise<void>;
|
||||
unfavoritePost: (postId: string) => Promise<void>;
|
||||
likeComment: (commentId: string) => Promise<void>;
|
||||
unlikeComment: (commentId: string) => Promise<void>;
|
||||
// 关注用户操作(authService 不管理状态,所以保留在 store)
|
||||
followUser: (userId: string) => Promise<void>;
|
||||
unfollowUser: (userId: string) => Promise<void>;
|
||||
|
||||
@@ -61,9 +52,6 @@ interface UserState {
|
||||
}
|
||||
|
||||
export const useUserStore = create<UserState>((set, get) => {
|
||||
// 创建乐观更新器
|
||||
const optimisticUpdater = createOptimisticUpdaterFactory<UserState>(set, get);
|
||||
|
||||
return {
|
||||
// 初始状态
|
||||
users: [],
|
||||
@@ -252,19 +240,6 @@ export const useUserStore = create<UserState>((set, get) => {
|
||||
set({ messageUnreadCount: count });
|
||||
},
|
||||
|
||||
// 从后端拉取最新消息未读数
|
||||
// @deprecated 请使用 messageManager.fetchUnreadCount() 代替
|
||||
// 此方法保留用于向后兼容
|
||||
fetchMessageUnreadCount: async () => {
|
||||
try {
|
||||
await messageManager.fetchUnreadCount();
|
||||
const unread = messageManager.getUnreadCount();
|
||||
set({ messageUnreadCount: unread.total + unread.system });
|
||||
} catch (error) {
|
||||
console.error('获取消息未读数失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 添加搜索历史
|
||||
addSearchHistory: (keyword: string) => {
|
||||
set(state => {
|
||||
@@ -278,153 +253,7 @@ export const useUserStore = create<UserState>((set, get) => {
|
||||
set({ searchHistory: [] });
|
||||
},
|
||||
|
||||
// 点赞帖子 - 使用乐观更新工具
|
||||
likePost: async (postId: string) => {
|
||||
const originalPosts = get().posts;
|
||||
|
||||
// 乐观更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? { ...p, is_liked: true, likes_count: p.likes_count + 1 } : p
|
||||
)
|
||||
}));
|
||||
|
||||
try {
|
||||
const updatedPost = await postService.likePost(postId);
|
||||
if (updatedPost) {
|
||||
// 使用服务器返回的数据更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? updatedPost : p
|
||||
)
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('点赞帖子失败:', error);
|
||||
// 回滚
|
||||
set({ posts: originalPosts });
|
||||
}
|
||||
},
|
||||
|
||||
// 取消点赞 - 使用乐观更新工具
|
||||
unlikePost: async (postId: string) => {
|
||||
const originalPosts = get().posts;
|
||||
|
||||
// 乐观更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? { ...p, is_liked: false, likes_count: Math.max(0, p.likes_count - 1) } : p
|
||||
)
|
||||
}));
|
||||
|
||||
try {
|
||||
const updatedPost = await postService.unlikePost(postId);
|
||||
if (updatedPost) {
|
||||
// 使用服务器返回的数据更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? updatedPost : p
|
||||
)
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('取消点赞帖子失败:', error);
|
||||
// 回滚
|
||||
set({ posts: originalPosts });
|
||||
}
|
||||
},
|
||||
|
||||
// 收藏帖子 - 使用乐观更新工具
|
||||
favoritePost: async (postId: string) => {
|
||||
const originalPosts = get().posts;
|
||||
|
||||
// 乐观更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? { ...p, is_favorited: true, favorites_count: p.favorites_count + 1 } : p
|
||||
)
|
||||
}));
|
||||
|
||||
try {
|
||||
const updatedPost = await postService.favoritePost(postId);
|
||||
if (updatedPost) {
|
||||
// 使用服务器返回的数据更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? updatedPost : p
|
||||
)
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('收藏帖子失败:', error);
|
||||
// 回滚
|
||||
set({ posts: originalPosts });
|
||||
}
|
||||
},
|
||||
|
||||
// 取消收藏 - 使用乐观更新工具
|
||||
unfavoritePost: async (postId: string) => {
|
||||
const originalPosts = get().posts;
|
||||
|
||||
// 乐观更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? { ...p, is_favorited: false, favorites_count: Math.max(0, p.favorites_count - 1) } : p
|
||||
)
|
||||
}));
|
||||
|
||||
try {
|
||||
const updatedPost = await postService.unfavoritePost(postId);
|
||||
if (updatedPost) {
|
||||
// 使用服务器返回的数据更新
|
||||
set(state => ({
|
||||
posts: state.posts.map(p =>
|
||||
p.id === postId ? updatedPost : p
|
||||
)
|
||||
}));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('取消收藏帖子失败:', error);
|
||||
// 回滚
|
||||
set({ posts: originalPosts });
|
||||
}
|
||||
},
|
||||
|
||||
// 点赞评论 - 使用乐观更新工具
|
||||
likeComment: async (commentId: string) => {
|
||||
await optimisticUpdater({
|
||||
key: 'posts',
|
||||
optimisticUpdate: (posts) =>
|
||||
posts.map(p => ({
|
||||
...p,
|
||||
top_comment: p.top_comment && p.top_comment.id === commentId
|
||||
? { ...p.top_comment, is_liked: true, likes_count: p.top_comment.likes_count + 1 }
|
||||
: p.top_comment
|
||||
})),
|
||||
rollbackState: (original) => original,
|
||||
apiCall: () => commentService.likeComment(commentId),
|
||||
errorMessage: '点赞评论失败',
|
||||
});
|
||||
},
|
||||
|
||||
// 取消点赞评论 - 使用乐观更新工具
|
||||
unlikeComment: async (commentId: string) => {
|
||||
await optimisticUpdater({
|
||||
key: 'posts',
|
||||
optimisticUpdate: (posts) =>
|
||||
posts.map(p => ({
|
||||
...p,
|
||||
top_comment: p.top_comment && p.top_comment.id === commentId
|
||||
? { ...p.top_comment, is_liked: false, likes_count: Math.max(0, p.top_comment.likes_count - 1) }
|
||||
: p.top_comment
|
||||
})),
|
||||
rollbackState: (original) => original,
|
||||
apiCall: () => commentService.unlikeComment(commentId),
|
||||
errorMessage: '取消点赞评论失败',
|
||||
});
|
||||
},
|
||||
|
||||
// 关注用户 - 使用乐观更新工具
|
||||
// 关注用户 - authService 不管理状态,所以由 store 管理
|
||||
followUser: async (userId: string) => {
|
||||
const originalUsers = get().users;
|
||||
const originalUserCache = get().userCache;
|
||||
@@ -462,7 +291,7 @@ export const useUserStore = create<UserState>((set, get) => {
|
||||
}
|
||||
},
|
||||
|
||||
// 取消关注 - 使用乐观更新工具
|
||||
// 取消关注 - authService 不管理状态,所以由 store 管理
|
||||
unfollowUser: async (userId: string) => {
|
||||
const originalUsers = get().users;
|
||||
const originalUserCache = get().userCache;
|
||||
|
||||
Reference in New Issue
Block a user