refactor(message): replace MessageStateManager with zustand store
Some checks failed
Frontend CI / ota-android (push) Successful in 11m15s
Frontend CI / build-and-push-web (push) Successful in 29m13s
Frontend CI / build-android-apk (push) Has been cancelled

- Remove MessageStateManager wrapper layer in favor of direct zustand store
- Move service modules to services/ subdirectory (ConversationOperations, MessageDeduplication, MessageSendService, MessageSyncService, ReadReceiptManager, UserCacheService, WSMessageHandler)
- Add new zustand-based store with subscriptionManager for event handling
- Introduce React hooks for message state (useConversations, useMessages, useUnreadCount, etc.)
- Update exports in index.ts to reflect new module structure
- Deprecate messageManager.ts entry point in favor of message/index.ts
- Maintain backward compatibility with existing MessageManager API
This commit is contained in:
lafay
2026-03-31 18:22:24 +08:00
parent 1bee7ea551
commit 94c11062f0
15 changed files with 1488 additions and 706 deletions

View File

@@ -0,0 +1,136 @@
/**
* 消息发送服务
* 处理消息发送相关逻辑
*
* 重构说明:直接使用 zustand store 替代 IMessageStateManager
*/
import type { MessageResponse, MessageSegment, ConversationResponse } from '../../../types/dto';
import { messageService } from '../../../services/messageService';
import { saveMessage } from '../../../services/database';
import type { IMessageSendService } from '../types';
import { useMessageStore, subscriptionManager, mergeMessagesById } from '../store';
export class MessageSendService implements IMessageSendService {
private getCurrentUserId: () => string | null;
constructor(getCurrentUserId: () => string | null) {
this.getCurrentUserId = getCurrentUserId;
}
/**
* 发送消息
*/
async sendMessage(
conversationId: string,
segments: MessageSegment[],
options?: { replyToId?: string }
): Promise<MessageResponse | null> {
const store = useMessageStore.getState();
try {
// 调用API发送
const response = await messageService.sendMessage(conversationId, {
segments,
reply_to_id: options?.replyToId,
});
if (response) {
const currentUserId = this.getCurrentUserId();
// 添加到本地消息列表
const existingMessages = store.getMessages(conversationId);
const newMessage: MessageResponse = {
id: response.id,
conversation_id: conversationId,
sender_id: currentUserId || '',
seq: response.seq,
segments,
created_at: new Date().toISOString(),
status: 'normal',
};
const updatedMessages = mergeMessagesById(existingMessages, [newMessage]);
store.setMessages(conversationId, updatedMessages);
// 关键:立即广播消息列表更新
subscriptionManager.notifySubscribers({
type: 'messages_updated',
payload: {
conversationId,
messages: updatedMessages,
newMessage,
source: 'send',
},
timestamp: Date.now(),
});
// 更新会话最后消息
this.updateConversationWithNewMessage(conversationId, newMessage);
// 通知消息已发送
subscriptionManager.notifySubscribers({
type: 'message_sent',
payload: { conversationId, message: newMessage },
timestamp: Date.now(),
});
// 保存到本地数据库
const textContent = segments
?.filter((s: any) => s.type === 'text')
.map((s: any) => s.data?.text || '')
.join('') || '';
saveMessage({
id: response.id,
conversationId,
senderId: currentUserId || '',
content: textContent,
type: segments?.find((s: any) => s.type === 'image') ? 'image' : 'text',
isRead: true,
createdAt: newMessage.created_at,
seq: response.seq,
status: 'normal',
segments,
}).catch(console.error);
return newMessage;
}
return null;
} catch (error) {
console.error('[MessageSendService] 发送消息失败:', error);
subscriptionManager.notifySubscribers({
type: 'error',
payload: { error, context: 'sendMessage' },
timestamp: Date.now(),
});
return null;
}
}
/**
* 更新会话的最后消息信息
*/
private updateConversationWithNewMessage(
conversationId: string,
message: MessageResponse
): void {
const store = useMessageStore.getState();
const conversation = store.getConversation(conversationId);
const createdAt = message.created_at || new Date().toISOString();
if (conversation) {
// 更新现有会话
const updatedConv: ConversationResponse = {
...conversation,
last_seq: message.seq,
last_message: message,
last_message_at: createdAt,
updated_at: createdAt,
};
store.updateConversation(updatedConv);
}
}
}