import { WebRTCMessage, FileRequest, FileReceiveComplete, FolderReceiveComplete } from "@/types/webrtc"; import { StateManager } from "./StateManager"; import { postLogToBackend } from "@/app/config/api"; const developmentEnv = process.env.NODE_ENV; /** * ๐Ÿš€ Message handling interface - Communicate with main orchestrator */ export interface MessageHandlerDelegate { handleFileRequest(request: FileRequest, peerId: string): Promise; log( level: "log" | "warn" | "error", message: string, context?: Record ): void; } /** * ๐Ÿš€ Message handler * Responsible for WebRTC message routing and processing logic */ export class MessageHandler { constructor( private stateManager: StateManager, private delegate: MessageHandlerDelegate ) {} /** * ๐ŸŽฏ Handle received signaling message */ handleSignalingMessage(message: WebRTCMessage, peerId: string): void { // Delete frequent message reception logs switch (message.type) { case "fileRequest": this.handleFileRequest(message as FileRequest, peerId); break; case "fileReceiveComplete": this.handleFileReceiveComplete(message as FileReceiveComplete, peerId); break; case "folderReceiveComplete": this.handleFolderReceiveComplete( message as FolderReceiveComplete, peerId ); break; default: this.delegate.log("warn", `Unknown signaling message type received`, { type: message.type, peerId, }); } } /** * ๐Ÿ“„ Handle file request message */ private async handleFileRequest( request: FileRequest, peerId: string ): Promise { const offset = request.offset || 0; this.delegate.log( "log", `Handling file request for ${request.fileId} from ${peerId} with offset ${offset}` ); // Firefox compatibility fix: Add slightly longer delay to ensure receiver is fully ready await new Promise((resolve) => setTimeout(resolve, 10)); // Delegate to main orchestrator for specific file transfer try { await this.delegate.handleFileRequest(request, peerId); } catch (error) { this.delegate.log("error", `Error handling file request`, { fileId: request.fileId, peerId, error: error instanceof Error ? error.message : String(error), }); } } /** * โœ… Handle file receive completion confirmation message */ private handleFileReceiveComplete( message: FileReceiveComplete, peerId: string ): void { // Clean up sending state this.stateManager.updatePeerState(peerId, { isSending: false }); // Get peer state to trigger progress callback const peerState = this.stateManager.getPeerState(peerId); // Trigger single file 100% progress (only for non-folder cases) if (!peerState.currentFolderName) { // Delete frequent progress logs peerState.progressCallback?.(message.fileId, 1, 0); } else { // Delete frequent folder progress logs } this.delegate.log("log", `File reception confirmed by peer ${peerId}`, { fileId: message.fileId, receivedSize: message.receivedSize, storeUpdated: message.storeUpdated, }); } /** * ๐Ÿ“ Handle folder receive completion confirmation message */ private handleFolderReceiveComplete( message: FolderReceiveComplete, peerId: string ): void { if (developmentEnv === "development") { postLogToBackend( `[DEBUG] ๐Ÿ“ฅ Folder complete - folderName: ${message.folderName}, files: ${message.completedFileIds.length}` ); } // Get peer state to trigger progress callback const peerState = this.stateManager.getPeerState(peerId); // Trigger folder 100% progress const folderMeta = this.stateManager.getFolderMeta(message.folderName); if (folderMeta) { postLogToBackend( `[DEBUG] ๐ŸŽฏ Setting folder progress to 100% - ${message.folderName}` ); peerState.progressCallback?.(message.folderName, 1, 0); } else { this.delegate.log( "warn", `Folder metadata not found for completed folder`, { folderName: message.folderName, peerId, } ); } this.delegate.log("log", `Folder reception confirmed by peer ${peerId}`, { folderName: message.folderName, completedFiles: message.completedFileIds.length, allStoreUpdated: message.allStoreUpdated, }); } /** * ๐Ÿ“Š Get message handling statistics */ public getMessageStats(): { handledMessages: number; lastMessageTime: number | null; } { // Message statistics logic can be added here if needed return { handledMessages: 0, // TODO: Implement message counting lastMessageTime: null, // TODO: Record last message time }; } /** * ๐Ÿงน Clean up resources */ public cleanup(): void { if (developmentEnv === "development") postLogToBackend("[DEBUG] ๐Ÿงน MessageHandler cleaned up"); } }