refactor(message): replace SubscriptionManager with Zustand selectors
Remove custom SubscriptionManager class and adopt Zustand's built-in selector mechanism for reactive state updates. This simplifies the architecture by eliminating manual subscription management and relying on Zustand's automatic dependency tracking for component re-renders. Key changes: - Remove SubscriptionManager class from store.ts - Replace all notifySubscribers calls with direct store updates - Update hooks to use Zustand selectors with useShallow for complex data - Remove subscribe/unsubscribe patterns from MessageManager - Simplify EmbeddedChat to use selector instead of local state - Rename requestConversationListRefresh to refreshConversations
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
* - useChatScreen.ts: 自定义Hook,管理所有状态和逻辑
|
||||
* - EmojiPanel.tsx: 表情面板组件
|
||||
* - MorePanel.tsx: 更多功能面板组件
|
||||
* - MentionPanel.tsx: @成员选择面板组件
|
||||
* - MentionPanel.tsx: @成员选择 面板组件
|
||||
* - LongPressMenu.tsx: 长按菜单组件
|
||||
* - ChatHeader.tsx: 聊天头部组件
|
||||
* - MessageBubble.tsx: 消息气泡组件
|
||||
@@ -258,10 +258,7 @@ export const ChatScreen: React.FC = () => {
|
||||
useEffect(() => {
|
||||
const unsubscribe = navigation.addListener('beforeRemove', () => {
|
||||
// 刷新会话列表,确保已读状态正确显示
|
||||
messageManager.requestConversationListRefresh('chat-before-remove', {
|
||||
force: true,
|
||||
allowDefer: false,
|
||||
});
|
||||
messageManager.refreshConversations(true, 'chat-before-remove');
|
||||
});
|
||||
return unsubscribe;
|
||||
}, [navigation]);
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Image as ExpoImage } from 'expo-image';
|
||||
import { spacing, fontSizes, shadows, useAppColors, type AppColors } from '../../../theme';
|
||||
import { ConversationResponse, MessageResponse, MessageSegment, GroupMemberResponse, ImageSegmentData } from '../../../types/dto';
|
||||
import { Avatar, Text, ImageGallery, AppBackButton } from '../../../components/common';
|
||||
import { useAuthStore, messageManager, MessageEvent, MessageSubscriber } from '../../../stores';
|
||||
import { useAuthStore, messageManager, useMessageStore } from '../../../stores';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { zhCN } from 'date-fns/locale';
|
||||
import { extractTextFromSegments } from '../../../types/dto';
|
||||
@@ -302,8 +302,8 @@ export const EmbeddedChat: React.FC<EmbeddedChatProps> = ({ conversation, onBack
|
||||
// 使用 markAsRead hook
|
||||
const { markAsRead } = useMarkAsRead(String(conversation.id));
|
||||
|
||||
// 状态
|
||||
const [messages, setMessages] = useState<MessageResponse[]>([]);
|
||||
// 状态 - 使用 Zustand selector 直接订阅消息
|
||||
const messages = useMessageStore(state => state.messagesMap.get(String(conversation.id)) || []);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [sending, setSending] = useState(false);
|
||||
const [inputText, setInputText] = useState('');
|
||||
@@ -490,7 +490,6 @@ export const EmbeddedChat: React.FC<EmbeddedChatProps> = ({ conversation, onBack
|
||||
try {
|
||||
setLoading(true);
|
||||
await messageManager.fetchMessages(String(conversation.id));
|
||||
setMessages(messageManager.getMessages(String(conversation.id)));
|
||||
} catch (error: any) {
|
||||
// 检查是否是权限错误或会话不存在错误
|
||||
const errorMessage = error?.message || String(error);
|
||||
@@ -501,8 +500,6 @@ export const EmbeddedChat: React.FC<EmbeddedChatProps> = ({ conversation, onBack
|
||||
error?.code === 'FORBIDDEN'
|
||||
) {
|
||||
console.warn('[EmbeddedChat] 会话不存在或无权限访问:', conversation.id);
|
||||
// 设置空消息列表,让 UI 显示"暂无消息"而不是崩溃
|
||||
setMessages([]);
|
||||
} else {
|
||||
console.error('[EmbeddedChat] 加载消息失败:', error);
|
||||
}
|
||||
@@ -514,25 +511,6 @@ export const EmbeddedChat: React.FC<EmbeddedChatProps> = ({ conversation, onBack
|
||||
// 初始加载
|
||||
useEffect(() => {
|
||||
loadMessages();
|
||||
|
||||
// 订阅消息事件
|
||||
const subscriber: MessageSubscriber = (event: MessageEvent) => {
|
||||
if (
|
||||
event.type === 'messages_updated' &&
|
||||
String(event.payload?.conversationId) === String(conversation.id)
|
||||
) {
|
||||
setMessages(event.payload.messages || []);
|
||||
setTimeout(() => {
|
||||
flatListRef.current?.scrollToEnd({ animated: true });
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
const unsubscribe = messageManager.subscribe(subscriber);
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [conversation.id, loadMessages]);
|
||||
|
||||
// 自动标记已读 - 当有新消息时
|
||||
|
||||
Reference in New Issue
Block a user