179 lines
5.0 KiB
TypeScript
179 lines
5.0 KiB
TypeScript
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<void>;
|
|
log(
|
|
level: "log" | "warn" | "error",
|
|
message: string,
|
|
context?: Record<string, any>
|
|
): 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<void> {
|
|
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");
|
|
}
|
|
}
|