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:
@@ -8,6 +8,7 @@
|
||||
* - 移除了 MessageStateManager 包装层
|
||||
* - 直接使用 zustand store
|
||||
* - 服务层移至 services/ 目录
|
||||
* - 移除了 SubscriptionManager,改用 Zustand selector 进行响应式订阅
|
||||
*/
|
||||
|
||||
import type { ConversationResponse, MessageResponse, MessageSegment, UserDTO } from '../../types/dto';
|
||||
@@ -24,7 +25,7 @@ import { MessageSyncService } from './services/MessageSyncService';
|
||||
import { WSMessageHandler } from './services/WSMessageHandler';
|
||||
|
||||
// 导入 store
|
||||
import { useMessageStore, subscriptionManager, normalizeConversationId } from './store';
|
||||
import { useMessageStore, normalizeConversationId } from './store';
|
||||
|
||||
// 重新导出类型,保持兼容性
|
||||
export type {
|
||||
@@ -164,23 +165,12 @@ class MessageManager {
|
||||
|
||||
this.wsHandler.setBootstrapping(false);
|
||||
|
||||
subscriptionManager.notifySubscribers({
|
||||
type: 'conversations_updated',
|
||||
payload: { conversations: this.getConversations() },
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
if (useMessageStore.getState().currentConversationId) {
|
||||
await this.fetchMessages(useMessageStore.getState().currentConversationId!);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[MessageManager] 初始化失败:', error);
|
||||
this.wsHandler.setBootstrapping(false);
|
||||
subscriptionManager.notifySubscribers({
|
||||
type: 'error',
|
||||
payload: { error, context: 'initialize' },
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -194,7 +184,6 @@ class MessageManager {
|
||||
destroy(): void {
|
||||
this.wsHandler.disconnect();
|
||||
useMessageStore.getState().reset();
|
||||
subscriptionManager.clear();
|
||||
this.syncService.restartSources();
|
||||
this.readReceiptManager.reset();
|
||||
this.deduplication.reset();
|
||||
@@ -339,18 +328,6 @@ class MessageManager {
|
||||
await this.initialize();
|
||||
this.setActiveConversation(normalizedId);
|
||||
|
||||
// 先下发当前内存快照
|
||||
const snapshot = this.getMessages(normalizedId);
|
||||
subscriptionManager.notifySubscribers({
|
||||
type: 'messages_updated',
|
||||
payload: {
|
||||
conversationId: normalizedId,
|
||||
messages: [...snapshot],
|
||||
source: 'activation_snapshot',
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
const existingTask = this.activatingConversationTasks.get(normalizedId);
|
||||
if (existingTask && !options?.forceSync) {
|
||||
await existingTask;
|
||||
@@ -371,81 +348,14 @@ class MessageManager {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 订阅机制 ====================
|
||||
|
||||
subscribe(subscriber: import('./types').MessageSubscriber): () => void {
|
||||
const unsubscribe = subscriptionManager.subscribe(subscriber);
|
||||
|
||||
// 立即发送当前状态给新订阅者(与原始版本保持一致)
|
||||
subscriber({
|
||||
type: 'conversations_updated',
|
||||
payload: { conversations: this.getConversations() },
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
const unreadCount = this.getUnreadCount();
|
||||
subscriber({
|
||||
type: 'unread_count_updated',
|
||||
payload: {
|
||||
totalUnreadCount: unreadCount.total,
|
||||
systemUnreadCount: unreadCount.system,
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
subscriber({
|
||||
type: 'connection_changed',
|
||||
payload: { connected: this.isConnected() },
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
// 如果当前有活动会话,立即发送该会话的消息给新订阅者
|
||||
const activeConversationId = this.getActiveConversation();
|
||||
if (activeConversationId) {
|
||||
const currentMessages = this.getMessages(activeConversationId);
|
||||
if (currentMessages.length > 0) {
|
||||
subscriber({
|
||||
type: 'messages_updated',
|
||||
payload: {
|
||||
conversationId: activeConversationId,
|
||||
messages: [...currentMessages],
|
||||
source: 'initial_sync',
|
||||
},
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return unsubscribe;
|
||||
}
|
||||
|
||||
subscribeToMessages(conversationId: string, callback: (messages: MessageResponse[]) => void): () => void {
|
||||
return subscriptionManager.subscribe((event) => {
|
||||
if (event.type === 'messages_updated' && event.payload.conversationId === conversationId) {
|
||||
callback(event.payload.messages);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 其他方法 ====================
|
||||
|
||||
canLoadMoreConversations(): boolean {
|
||||
return this.syncService.canLoadMoreConversations();
|
||||
}
|
||||
|
||||
invalidateCache(_type?: 'all' | 'list' | 'unread'): void {
|
||||
// 兼容性方法,新架构不需要外部缓存
|
||||
}
|
||||
|
||||
async requestConversationListRefresh(
|
||||
source: string,
|
||||
options?: { force?: boolean; allowDefer?: boolean }
|
||||
): Promise<void> {
|
||||
const forceRefresh = options?.force ?? true;
|
||||
const allowDefer = options?.allowDefer ?? true;
|
||||
|
||||
if (allowDefer && this.shouldDeferConversationRefresh(source, forceRefresh)) {
|
||||
// 延迟刷新逻辑在 syncService 中处理
|
||||
async refreshConversations(forceRefresh: boolean, source: string): Promise<void> {
|
||||
if (this.shouldDeferConversationRefresh(source, forceRefresh)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user