refactor(core): introduce EventBus and refactor store infrastructure
- Add EventBus for decoupled event-driven communication between services - Add EventSubscriber component for centralized event handling - Add requestDedupe utility for shared request deduplication - Refactor api/wsService to use eventBus instead of direct router navigation - Extract MessageMapper.toCachedMessages for consistent message mapping - Remove deprecated BaseManager and CacheBus classes - Improve @mention rendering with memberMap support in segment rendering - Update hooks to use useRef instead of useState for fetch tracking
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
import type { ConversationResponse, MessageResponse } from '../../../types/dto';
|
||||
import { messageService } from '../../../services/messageService';
|
||||
import { messageRepository, conversationRepository } from '@/database';
|
||||
import { MessageMapper } from '@/data/mappers';
|
||||
import {
|
||||
type IConversationListPagedSource,
|
||||
SqliteConversationListPagedSource,
|
||||
@@ -242,19 +243,9 @@ export class MessageSyncService implements IMessageSyncService {
|
||||
const mergedSnapshot = mergeMessagesById(existingMessages, snapshotMessages);
|
||||
store.setMessages(conversationId, mergedSnapshot);
|
||||
|
||||
// 持久化到本地
|
||||
messageRepository.saveMessagesBatch(snapshotMessages.map((m: any) => ({
|
||||
id: m.id,
|
||||
conversationId: m.conversation_id || conversationId,
|
||||
senderId: m.sender_id,
|
||||
content: m.content,
|
||||
type: m.type || 'text',
|
||||
isRead: m.is_read || false,
|
||||
createdAt: m.created_at,
|
||||
seq: m.seq,
|
||||
status: m.status || 'normal',
|
||||
segments: m.segments,
|
||||
}))).catch(error => {
|
||||
messageRepository.saveMessagesBatch(
|
||||
MessageMapper.toCachedMessages(snapshotMessages, conversationId)
|
||||
).catch(error => {
|
||||
console.error('[MessageSyncService] 保存快照消息到本地失败:', error);
|
||||
});
|
||||
}
|
||||
@@ -270,18 +261,9 @@ export class MessageSyncService implements IMessageSyncService {
|
||||
const mergedMessages = mergeMessagesById(existingMessages, newMessages);
|
||||
store.setMessages(conversationId, mergedMessages);
|
||||
|
||||
messageRepository.saveMessagesBatch(newMessages.map((m: any) => ({
|
||||
id: m.id,
|
||||
conversationId: m.conversation_id || conversationId,
|
||||
senderId: m.sender_id,
|
||||
content: m.content,
|
||||
type: m.type || 'text',
|
||||
isRead: m.is_read || false,
|
||||
createdAt: m.created_at,
|
||||
seq: m.seq,
|
||||
status: m.status || 'normal',
|
||||
segments: m.segments,
|
||||
}))).catch(error => {
|
||||
messageRepository.saveMessagesBatch(
|
||||
MessageMapper.toCachedMessages(newMessages, conversationId)
|
||||
).catch(error => {
|
||||
console.error('[MessageSyncService] 保存增量消息到本地失败:', error);
|
||||
});
|
||||
}
|
||||
@@ -300,18 +282,9 @@ export class MessageSyncService implements IMessageSyncService {
|
||||
|
||||
store.setMessages(conversationId, mergedMessages);
|
||||
|
||||
messageRepository.saveMessagesBatch(newMessages.map((m: any) => ({
|
||||
id: m.id,
|
||||
conversationId: m.conversation_id || conversationId,
|
||||
senderId: m.sender_id,
|
||||
content: m.content,
|
||||
type: m.type || 'text',
|
||||
isRead: m.is_read || false,
|
||||
createdAt: m.created_at,
|
||||
seq: m.seq,
|
||||
status: m.status || 'normal',
|
||||
segments: m.segments,
|
||||
}))).catch(error => {
|
||||
messageRepository.saveMessagesBatch(
|
||||
MessageMapper.toCachedMessages(newMessages, conversationId)
|
||||
).catch(error => {
|
||||
console.error('[MessageSyncService] 保存消息到本地失败:', error);
|
||||
});
|
||||
}
|
||||
@@ -368,18 +341,9 @@ export class MessageSyncService implements IMessageSyncService {
|
||||
if (response?.messages && response.messages.length > 0) {
|
||||
const serverMessages = response.messages;
|
||||
|
||||
await messageRepository.saveMessagesBatch(serverMessages.map((m: any) => ({
|
||||
id: m.id,
|
||||
conversationId: m.conversation_id || conversationId,
|
||||
senderId: m.sender_id,
|
||||
content: m.content,
|
||||
type: m.type || 'text',
|
||||
isRead: m.is_read || false,
|
||||
createdAt: m.created_at,
|
||||
seq: m.seq,
|
||||
status: m.status || 'normal',
|
||||
segments: m.segments,
|
||||
})));
|
||||
await messageRepository.saveMessagesBatch(
|
||||
MessageMapper.toCachedMessages(serverMessages, conversationId)
|
||||
);
|
||||
|
||||
const existingMessages = store.getMessages(conversationId);
|
||||
const mergedMessages = this.mergeOlderMessages(existingMessages, serverMessages);
|
||||
|
||||
@@ -18,7 +18,7 @@ import type {
|
||||
WSGroupNoticeMessage,
|
||||
} from '../../../services/wsService';
|
||||
import { wsService, GroupNoticeType } from '../../../services/wsService';
|
||||
import { vibrateOnMessage } from '../../../services/messageVibrationService';
|
||||
import { eventBus } from '@/core/events/EventBus';
|
||||
import { messageRepository } from '@/database';
|
||||
import type { MessageResponse, ConversationResponse } from '../../../types/dto';
|
||||
import type {
|
||||
@@ -75,29 +75,24 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
this.sseUnsubscribe();
|
||||
}
|
||||
|
||||
const store = useMessageStore.getState();
|
||||
|
||||
// 监听私聊消息
|
||||
wsService.on('chat', (message: WSChatMessage) => {
|
||||
if (!store.getState().isInitialized || this.isBootstrapping) {
|
||||
if (!useMessageStore.getState().isInitialized || this.isBootstrapping) {
|
||||
this.bufferedChatMessages.push(message);
|
||||
return;
|
||||
}
|
||||
this.handleNewMessage(message);
|
||||
});
|
||||
|
||||
// 监听群聊消息
|
||||
wsService.on('group_message', (message: WSGroupChatMessage) => {
|
||||
if (!store.getState().isInitialized || this.isBootstrapping) {
|
||||
if (!useMessageStore.getState().isInitialized || this.isBootstrapping) {
|
||||
this.bufferedChatMessages.push(message);
|
||||
return;
|
||||
}
|
||||
this.handleNewMessage(message);
|
||||
});
|
||||
|
||||
// 监听私聊已读回执
|
||||
wsService.on('read', (message: WSReadMessage) => {
|
||||
if (!store.getState().isInitialized || this.isBootstrapping) {
|
||||
if (!useMessageStore.getState().isInitialized || this.isBootstrapping) {
|
||||
this.bufferedReadReceipts.push(message);
|
||||
return;
|
||||
}
|
||||
@@ -106,7 +101,7 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
|
||||
// 监听群聊已读回执
|
||||
wsService.on('group_read', (message: WSGroupReadMessage) => {
|
||||
if (!store.getState().isInitialized || this.isBootstrapping) {
|
||||
if (!useMessageStore.getState().isInitialized || this.isBootstrapping) {
|
||||
this.bufferedReadReceipts.push(message);
|
||||
return;
|
||||
}
|
||||
@@ -135,13 +130,13 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
|
||||
// 监听连接状态
|
||||
wsService.onConnect(() => {
|
||||
store.setSSEConnected(true);
|
||||
useMessageStore.getState().setSSEConnected(true);
|
||||
|
||||
// 冷启动/重连兜底
|
||||
const now = Date.now();
|
||||
if (now - this.lastReconnectSyncAt > 1500) {
|
||||
this.lastReconnectSyncAt = now;
|
||||
const activeConversation = store.getActiveConversation();
|
||||
const activeConversation = useMessageStore.getState().getActiveConversation();
|
||||
|
||||
if (!activeConversation) {
|
||||
this.fetchConversationsCallback(true, 'sse-reconnect').catch(error => {
|
||||
@@ -162,7 +157,7 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
});
|
||||
|
||||
wsService.onDisconnect(() => {
|
||||
store.setSSEConnected(false);
|
||||
useMessageStore.getState().setSSEConnected(false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -305,8 +300,8 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
|
||||
if (shouldIncrementUnread) {
|
||||
if (!suppressVibration) {
|
||||
const vibrationType = message.type === 'group_message' ? 'group_message' : 'chat';
|
||||
vibrateOnMessage(vibrationType).catch(() => {});
|
||||
const vibrationType = message.type === 'group_message' ? 'group_message' : 'message';
|
||||
eventBus.emit({ type: 'VIBRATE', payload: { type: vibrationType } });
|
||||
}
|
||||
this.incrementUnreadCount(normalizedConversationId);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ export interface ReadStateRecord {
|
||||
/** 已上报的已读序号(用于去重) */
|
||||
lastReadSeq: number;
|
||||
/** 清除保护的定时器ID */
|
||||
clearTimer?: NodeJS.Timeout;
|
||||
clearTimer?: ReturnType<typeof setTimeout>;
|
||||
}
|
||||
|
||||
// ==================== 依赖注入接口 ====================
|
||||
|
||||
Reference in New Issue
Block a user