diff --git a/chuan-next/src/app/HomePage.tsx b/chuan-next/src/app/HomePage.tsx index d7a7151..ba56dfb 100644 --- a/chuan-next/src/app/HomePage.tsx +++ b/chuan-next/src/app/HomePage.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Upload, MessageSquare, Monitor, Users } from 'lucide-react'; import Hero from '@/components/Hero'; @@ -18,8 +18,6 @@ export default function HomePage() { const { activeTab, handleTabChange, - getConnectionInfo, - hasInitialized, confirmDialogState, closeConfirmDialog } = useTabNavigation(); @@ -34,18 +32,6 @@ export default function HomePage() { showUnsupportedModalManually, } = useWebRTCSupport(); - // 桌面共享功能的占位符函数(保持向后兼容) - const handleStartSharing = async () => { - console.log('开始桌面共享'); - }; - - const handleStopSharing = async () => { - console.log('停止桌面共享'); - }; - - const handleJoinSharing = async (code: string) => { - console.log('加入桌面共享:', code); - }; // 处理Tabs组件的字符串参数 const handleTabChangeWrapper = (value: string) => { diff --git a/chuan-next/src/components/ConnectionStatus.tsx b/chuan-next/src/components/ConnectionStatus.tsx index ca0af37..a793336 100644 --- a/chuan-next/src/components/ConnectionStatus.tsx +++ b/chuan-next/src/components/ConnectionStatus.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { cn } from '@/lib/utils'; import { useWebRTCStore } from '@/hooks/index'; @@ -14,7 +14,7 @@ interface ConnectionStatusProps { } // 连接状态枚举 -const getConnectionStatus = (connection: any, currentRoom: any) => { +const getConnectionStatus = (connection: { isWebSocketConnected?: boolean; isPeerConnected?: boolean; isConnecting?: boolean; error?: string | null }, currentRoom: { code: string; role: 'sender' | 'receiver' } | null) => { const isWebSocketConnected = connection?.isWebSocketConnected || false; const isPeerConnected = connection?.isPeerConnected || false; const isConnecting = connection?.isConnecting || false; @@ -116,7 +116,7 @@ const StatusIcon = ({ type, className = 'w-3 h-3' }: { type: string; className?: }; // 获取连接状态文字描述 -const getConnectionStatusText = (connection: any) => { +const getConnectionStatusText = (connection: { isWebSocketConnected?: boolean; isPeerConnected?: boolean; isConnecting?: boolean; error?: string | null }) => { const isWebSocketConnected = connection?.isWebSocketConnected || false; const isPeerConnected = connection?.isPeerConnected || false; const isConnecting = connection?.isConnecting || false; @@ -155,12 +155,14 @@ export function ConnectionStatus(props: ConnectionStatusProps) { error: webrtcState.error, }; + const isConnected = webrtcState.isWebSocketConnected && webrtcState.isPeerConnected; + // 如果是内联模式,只返回状态文字 if (inline) { return {getConnectionStatusText(connection)}; } - const status = getConnectionStatus(connection, currentRoom); + const status = getConnectionStatus(connection, currentRoom ?? null); if (compact) { return ( @@ -244,7 +246,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) { } // 简化版本的 Hook,用于快速集成 - 现在已经不需要了,但保留兼容性 -export function useConnectionStatus(webrtcConnection?: any) { +export function useConnectionStatus(webrtcConnection?: { isWebSocketConnected?: boolean; isPeerConnected?: boolean; isConnecting?: boolean; currentRoom?: { code: string; role: 'sender' | 'receiver' } | null; error?: string | null }) { // 这个hook现在不再需要,因为ConnectionStatus组件直接使用底层连接 // 但为了向后兼容,保留这个接口 return useMemo(() => ({ diff --git a/chuan-next/src/components/DesktopShare.tsx b/chuan-next/src/components/DesktopShare.tsx index e16725c..3091de1 100644 --- a/chuan-next/src/components/DesktopShare.tsx +++ b/chuan-next/src/components/DesktopShare.tsx @@ -6,26 +6,18 @@ import { Button } from '@/components/ui/button'; import { Share, Monitor } from 'lucide-react'; import WebRTCDesktopReceiver from '@/components/webrtc/WebRTCDesktopReceiver'; import WebRTCDesktopSender from '@/components/webrtc/WebRTCDesktopSender'; -import { useWebRTCStore } from '@/hooks/index'; interface DesktopShareProps { // 保留向后兼容性的props(已废弃,但保留接口) - onStartSharing?: () => Promise; - onStopSharing?: () => Promise; onJoinSharing?: (code: string) => Promise; } export default function DesktopShare({ - onStartSharing, - onStopSharing, onJoinSharing }: DesktopShareProps) { const [mode, setMode] = useState<'share' | 'view'>('share'); - // 使用全局WebRTC状态 - const webrtcState = useWebRTCStore(); - // 使用统一的URL处理器,带模式转换 const { updateMode, getCurrentRoomCode } = useURLHandler({ featureType: 'desktop', @@ -44,9 +36,8 @@ export default function DesktopShare({ return code; }, [getCurrentRoomCode]); - // 连接状态变化处理 - 现在不需要了,因为使用全局状态 - const handleConnectionChange = useCallback((connection: any) => { - // 这个函数现在可能不需要了,但为了兼容现有的子组件接口,保留它 + // 连接状态变化处理 - 为了兼容现有的子组件接口,保留它 + const handleConnectionChange = useCallback((connection: { isConnected: boolean; isWebSocketConnected: boolean }) => { console.log('桌面共享连接状态变化:', connection); }, []); diff --git a/chuan-next/src/components/WebRTCFileTransfer.tsx b/chuan-next/src/components/WebRTCFileTransfer.tsx index 02e82ff..db9426c 100644 --- a/chuan-next/src/components/WebRTCFileTransfer.tsx +++ b/chuan-next/src/components/WebRTCFileTransfer.tsx @@ -83,7 +83,7 @@ export const WebRTCFileTransfer: React.FC = () => { isPeerConnected: connection.isPeerConnected }); - const { joinRoom: originalJoinRoom, isJoiningRoom } = useRoomConnection({ + const { joinRoom: originalJoinRoom } = useRoomConnection({ connect, isConnecting, isConnected @@ -264,28 +264,33 @@ export const WebRTCFileTransfer: React.FC = () => { return; } + console.log('当前选中的文件列表:', selectedFiles.map(f => f.name)); + // 在发送方的selectedFiles中查找对应文件 const file = selectedFiles.find(f => f.name === fileName); if (!file) { console.error('找不到匹配的文件:', fileName); + console.log('可用文件:', selectedFiles.map(f => `${f.name} (${f.size} bytes)`)); showToast(`无法找到文件: ${fileName}`, "error"); return; } console.log('找到匹配文件,开始发送:', file.name, 'ID:', fileId, '文件大小:', file.size); - // 更新发送方文件状态为downloading + // 更新发送方文件状态为downloading - 统一使用updateFileStatus updateFileStatus(fileId, 'downloading', 0); // 发送文件 try { sendFile(file, fileId); + + // 移除不必要的Toast - 传输开始状态在UI中已经显示 } catch (sendError) { console.error('发送文件失败:', sendError); showToast(`发送文件失败: ${fileName}`, "error"); - // 重置文件状态 + // 重置文件状态 - 统一使用updateFileStatus updateFileStatus(fileId, 'ready', 0); } } else { @@ -340,86 +345,7 @@ export const WebRTCFileTransfer: React.FC = () => { } }, [error, mode, showToast, lastError]); - // 处理文件接收 - useEffect(() => { - const cleanup = onFileReceived((fileData: { id: string; file: File }) => { - console.log('=== 接收到文件 ==='); - console.log('文件:', fileData.file.name, 'ID:', fileData.id); - - // 更新下载的文件 - setDownloadedFiles(prev => new Map(prev.set(fileData.id, fileData.file))); - - // 更新文件状态 - setFileList(prev => prev.map(item => - item.id === fileData.id - ? { ...item, status: 'completed' as const, progress: 100 } - : item - )); - - // 移除不必要的Toast - 文件完成状态在UI中已经显示 - }); - return cleanup; - }, [onFileReceived]); - - // 处理文件请求(发送方监听) - useEffect(() => { - const cleanup = onFileRequested((fileId: string, fileName: string) => { - console.log('=== 收到文件请求 ==='); - console.log('文件:', fileName, 'ID:', fileId, '当前模式:', mode); - - if (mode === 'send') { - // 检查连接状态 - if (!isConnected || error) { - console.log('连接已断开,无法发送文件'); - showToast('连接已断开,无法发送文件', "error"); - return; - } - - console.log('当前选中的文件列表:', selectedFiles.map(f => f.name)); - - // 在发送方的selectedFiles中查找对应文件 - const file = selectedFiles.find(f => f.name === fileName); - - if (!file) { - console.error('找不到匹配的文件:', fileName); - console.log('可用文件:', selectedFiles.map(f => `${f.name} (${f.size} bytes)`)); - showToast(`无法找到文件: ${fileName}`, "error"); - return; - } - - console.log('找到匹配文件,开始发送:', file.name, 'ID:', fileId, '文件大小:', file.size); - - // 更新发送方文件状态为downloading - setFileList(prev => prev.map(item => - item.id === fileId || item.name === fileName - ? { ...item, status: 'downloading' as const, progress: 0 } - : item - )); - - // 发送文件 - try { - sendFile(file, fileId); - - // 移除不必要的Toast - 传输开始状态在UI中已经显示 - } catch (sendError) { - console.error('发送文件失败:', sendError); - showToast(`发送文件失败: ${fileName}`, "error"); - - // 重置文件状态 - setFileList(prev => prev.map(item => - item.id === fileId || item.name === fileName - ? { ...item, status: 'ready' as const, progress: 0 } - : item - )); - } - } else { - console.warn('接收模式下收到文件请求,忽略'); - } - }); - - return cleanup; - }, [onFileRequested, mode, selectedFiles, sendFile, isConnected, error]); // 监听连接状态变化和清理传输状态 useEffect(() => { diff --git a/chuan-next/src/hooks/file-transfer/useFileStateManager.ts b/chuan-next/src/hooks/file-transfer/useFileStateManager.ts index 56e325a..0583839 100644 --- a/chuan-next/src/hooks/file-transfer/useFileStateManager.ts +++ b/chuan-next/src/hooks/file-transfer/useFileStateManager.ts @@ -115,40 +115,45 @@ export const useFileStateManager = ({ console.log('=== selectedFiles变化,同步文件列表 ===', { selectedFilesCount: selectedFiles.length, - fileListCount: fileList.length, selectedFileNames: selectedFiles.map(f => f.name) }); - // 根据selectedFiles创建新的文件信息列表 - const newFileInfos: FileInfo[] = selectedFiles.map(file => { - // 尝试找到现有的文件信息,保持已有的状态 - const existingFileInfo = fileList.find(info => info.name === file.name && info.size === file.size); - return existingFileInfo || { - id: generateFileId(), - name: file.name, - size: file.size, - type: file.type, - status: 'ready' as const, - progress: 0 - }; - }); - - // 检查文件列表是否真正发生变化 - const fileListChanged = - newFileInfos.length !== fileList.length || - newFileInfos.some(newFile => - !fileList.find(oldFile => oldFile.name === newFile.name && oldFile.size === newFile.size) - ); - - if (fileListChanged) { - console.log('文件列表发生变化,更新:', { - before: fileList.map(f => f.name), - after: newFileInfos.map(f => f.name) + // 使用函数式更新获取当前fileList,避免依赖fileList + setFileList(currentFileList => { + // 根据selectedFiles创建新的文件信息列表 + const newFileInfos: FileInfo[] = selectedFiles.map(file => { + // 尝试在当前fileList中找到现有的文件信息,保持已有的状态 + const existingFileInfo = currentFileList.find(info => info.name === file.name && info.size === file.size); + return existingFileInfo || { + id: generateFileId(), + name: file.name, + size: file.size, + type: file.type, + status: 'ready' as const, + progress: 0 + }; }); - - setFileList(newFileInfos); - } - }, [selectedFiles, mode, pickupCode, fileList, generateFileId]); + + // 检查文件列表是否真正发生变化 + const fileListChanged = + newFileInfos.length !== currentFileList.length || + newFileInfos.some(newFile => + !currentFileList.find(oldFile => oldFile.name === newFile.name && oldFile.size === newFile.size) + ); + + if (fileListChanged) { + console.log('文件列表发生变化,更新:', { + before: currentFileList.map(f => f.name), + after: newFileInfos.map(f => f.name) + }); + + return newFileInfos; + } + + // 如果没有变化,返回当前的fileList + return currentFileList; + }); + }, [selectedFiles, mode, pickupCode, generateFileId]); // 移除fileList依赖,避免无限循环 return { selectedFiles, diff --git a/chuan-next/src/hooks/webrtc/WebSocketManager.ts b/chuan-next/src/hooks/webrtc/WebSocketManager.ts index 117eb4a..f6df874 100644 --- a/chuan-next/src/hooks/webrtc/WebSocketManager.ts +++ b/chuan-next/src/hooks/webrtc/WebSocketManager.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events'; -import { WebRTCError, WebRTCMessage, ConnectionEvent, EventHandler } from './types'; +import { WebRTCError, ConnectionEvent, EventHandler } from './types'; interface WebSocketManagerConfig { url: string; diff --git a/chuan-next/src/lib/webrtc-support.ts b/chuan-next/src/lib/webrtc-support.ts index 80840ee..5ffbce4 100644 --- a/chuan-next/src/lib/webrtc-support.ts +++ b/chuan-next/src/lib/webrtc-support.ts @@ -43,6 +43,7 @@ export function detectWebRTCSupport(): WebRTCSupport { pc.close(); } } catch (error) { + console.warn(error); missing.push('DataChannel'); }