/** * 已读回执管理器 * 负责处理消息已读状态的同步 */ import { messageService } from '../../services/messageService'; import { messageRepository } from '../../data/repositories/MessageRepository'; import type { MessageStateManager } from './MessageStateManager'; export interface ReadReceiptResult { conversationId: string; lastReadSeq: number; success: boolean; } export class ReadReceiptManager { private pendingOperations: Map> = new Map(); private stateManager: MessageStateManager | null = null; setStateManager(manager: MessageStateManager): void { this.stateManager = manager; } async markAsRead( conversationId: string, lastSeq: number ): Promise { const existing = this.pendingOperations.get(conversationId); if (existing) { await existing; } if (!this.stateManager) { throw new Error('StateManager not set'); } const version = this.stateManager.beginReadOperation(conversationId); const promise = this.executeMarkAsRead(conversationId, lastSeq, version); this.pendingOperations.set(conversationId, promise); try { await promise; return { conversationId, lastReadSeq: lastSeq, success: true }; } catch (error) { console.error('[ReadReceiptManager] Failed to mark as read:', error); return { conversationId, lastReadSeq: lastSeq, success: false }; } finally { this.pendingOperations.delete(conversationId); this.stateManager.endReadOperation(conversationId); } } private async executeMarkAsRead( conversationId: string, lastSeq: number, version: number ): Promise { await messageService.markAsRead(conversationId, lastSeq); await messageRepository.markConversationAsRead(conversationId); if (this.stateManager) { this.stateManager.updateConversation(conversationId, { unreadCount: 0, }); } } async markAllAsRead(): Promise { if (!this.stateManager) return; const conversations = this.stateManager.getConversations(); const unreadConversations = conversations.filter(c => c.unreadCount > 0); await Promise.all( unreadConversations.map(conv => this.markAsRead(conv.id, conv.lastSeq) ) ); } isPending(conversationId: string): boolean { return this.pendingOperations.has(conversationId); } reset(): void { this.pendingOperations.clear(); } } export const readReceiptManager = new ReadReceiptManager();