mirror of
https://github.com/MatrixSeven/file-transfer-go.git
synced 2026-02-15 09:44:45 +08:00
Compare commits
1 Commits
main
...
feature/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e16e30681 |
0
chuan-next/build-static.sh
Normal file → Executable file
0
chuan-next/build-static.sh
Normal file → Executable file
@@ -15,16 +15,23 @@ interface ConnectionStatusProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 连接状态枚举
|
// 连接状态枚举
|
||||||
const getConnectionStatus = (currentRoom: { code: string; role: Role } | null) => {
|
const getConnectionStatus = (
|
||||||
|
currentRoom: { code: string; role: Role } | null,
|
||||||
const { getConnectState } = useReadConnectState(); // 确保状态管理器被初始化
|
connection: {
|
||||||
const connection = getConnectState();
|
isWebSocketConnected: boolean;
|
||||||
const isWebSocketConnected = connection?.isWebSocketConnected || false;
|
isPeerConnected: boolean;
|
||||||
const isPeerConnected = connection?.isPeerConnected || false;
|
isConnecting: boolean;
|
||||||
const isConnecting = connection?.isConnecting || false;
|
error: string | null;
|
||||||
const error = connection?.error || null;
|
currentConnectType: 'webrtc' | 'websocket';
|
||||||
const currentConnectType = connection?.currentConnectType || 'webrtc';
|
isJoinedRoom: boolean;
|
||||||
const isJoinedRoom = connection?.isJoinedRoom || false;
|
}
|
||||||
|
) => {
|
||||||
|
const isWebSocketConnected = connection.isWebSocketConnected;
|
||||||
|
const isPeerConnected = connection.isPeerConnected;
|
||||||
|
const isConnecting = connection.isConnecting;
|
||||||
|
const error = connection.error;
|
||||||
|
const currentConnectType = connection.currentConnectType;
|
||||||
|
const isJoinedRoom = connection.isJoinedRoom;
|
||||||
|
|
||||||
if (!currentRoom) {
|
if (!currentRoom) {
|
||||||
return {
|
return {
|
||||||
@@ -198,6 +205,10 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
|
|||||||
// 使用全局WebRTC状态
|
// 使用全局WebRTC状态
|
||||||
const webrtcState = useWebRTCStore();
|
const webrtcState = useWebRTCStore();
|
||||||
|
|
||||||
|
// 获取连接状态
|
||||||
|
const { getConnectState } = useReadConnectState();
|
||||||
|
const connectionState = getConnectState();
|
||||||
|
|
||||||
// 创建connection对象以兼容现有代码
|
// 创建connection对象以兼容现有代码
|
||||||
const connection = {
|
const connection = {
|
||||||
isWebSocketConnected: webrtcState.isWebSocketConnected,
|
isWebSocketConnected: webrtcState.isWebSocketConnected,
|
||||||
@@ -205,6 +216,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
|
|||||||
isConnecting: webrtcState.isConnecting,
|
isConnecting: webrtcState.isConnecting,
|
||||||
error: webrtcState.error,
|
error: webrtcState.error,
|
||||||
currentConnectType: webrtcState.currentConnectType,
|
currentConnectType: webrtcState.currentConnectType,
|
||||||
|
isJoinedRoom: connectionState?.isJoinedRoom || false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const isConnected = webrtcState.isWebSocketConnected && webrtcState.isPeerConnected;
|
const isConnected = webrtcState.isWebSocketConnected && webrtcState.isPeerConnected;
|
||||||
@@ -214,7 +226,7 @@ export function ConnectionStatus(props: ConnectionStatusProps) {
|
|||||||
return <span className={cn('text-sm text-slate-600', className)}>{getConnectionStatusText(connection)}</span>;
|
return <span className={cn('text-sm text-slate-600', className)}>{getConnectionStatusText(connection)}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = getConnectionStatus(currentRoom ?? null);
|
const status = getConnectionStatus(currentRoom ?? null, connection);
|
||||||
|
|
||||||
if (compact) {
|
if (compact) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -385,19 +385,26 @@ export function useFileTransferBusiness(connection: IWebConnection) {
|
|||||||
retryCount = 0
|
retryCount = 0
|
||||||
): Promise<boolean> => {
|
): Promise<boolean> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// 主要检查数据通道状态,因为数据通道是文件传输的实际通道
|
// 改进数据传输前的连接状态检查
|
||||||
const channelState = connection.getConnectState();
|
const channelState = connection.getConnectState();
|
||||||
if (channelState.state === 'closed') {
|
const isChannelUsable =
|
||||||
console.warn(`数据通道已关闭,停止发送文件块 ${chunkIndex}`);
|
channelState.state === 'open' ||
|
||||||
|
channelState.isDataChannelConnected ||
|
||||||
|
channelState.isPeerConnected ||
|
||||||
|
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket');
|
||||||
|
|
||||||
|
if (!isChannelUsable) {
|
||||||
|
console.warn(`数据块发送失败,传输通道不可用 ${chunkIndex}:`, {
|
||||||
|
state: channelState.state,
|
||||||
|
isDataChannelConnected: channelState.isDataChannelConnected,
|
||||||
|
isPeerConnected: channelState.isPeerConnected,
|
||||||
|
isWebSocketConnected: channelState.isWebSocketConnected,
|
||||||
|
currentConnectType: channelState.currentConnectType
|
||||||
|
});
|
||||||
resolve(false);
|
resolve(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果连接暂时断开但数据通道可用,仍然可以尝试发送
|
|
||||||
if (!channelState.isConnected && channelState.state === 'connecting') {
|
|
||||||
console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const chunkKey = `${fileId}-${chunkIndex}`;
|
const chunkKey = `${fileId}-${chunkIndex}`;
|
||||||
|
|
||||||
// 设置确认回调
|
// 设置确认回调
|
||||||
@@ -443,8 +450,27 @@ export function useFileTransferBusiness(connection: IWebConnection) {
|
|||||||
|
|
||||||
// 安全发送文件
|
// 安全发送文件
|
||||||
const sendFileSecure = useCallback(async (file: File, fileId?: string) => {
|
const sendFileSecure = useCallback(async (file: File, fileId?: string) => {
|
||||||
if (connection.getConnectState().state !== 'open') {
|
// 改进连接状态检查 - 使用更全面的连接状态判断
|
||||||
updateState({ error: '连接未就绪' });
|
const connectState = connection.getConnectState();
|
||||||
|
const isReadyToSend =
|
||||||
|
connectState.state === 'open' || // 数据通道已打开
|
||||||
|
connectState.isDataChannelConnected || // 数据通道已连接
|
||||||
|
connectState.isPeerConnected || // P2P连接已建立
|
||||||
|
(connectState.isWebSocketConnected && connectState.currentConnectType === 'websocket'); // WebSocket降级模式
|
||||||
|
|
||||||
|
console.log('发送文件前连接状态检查:', {
|
||||||
|
state: connectState.state,
|
||||||
|
isDataChannelConnected: connectState.isDataChannelConnected,
|
||||||
|
isPeerConnected: connectState.isPeerConnected,
|
||||||
|
isWebSocketConnected: connectState.isWebSocketConnected,
|
||||||
|
currentConnectType: connectState.currentConnectType,
|
||||||
|
isReadyToSend
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isReadyToSend) {
|
||||||
|
const errorMsg = `连接未就绪 - 状态: ${connectState.state}, 数据通道: ${connectState.isDataChannelConnected}, P2P: ${connectState.isPeerConnected}, WebSocket: ${connectState.isWebSocketConnected}`;
|
||||||
|
console.error(errorMsg);
|
||||||
|
updateState({ error: errorMsg });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,16 +514,23 @@ export function useFileTransferBusiness(connection: IWebConnection) {
|
|||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
|
|
||||||
while (!success && retryCount <= MAX_RETRIES) {
|
while (!success && retryCount <= MAX_RETRIES) {
|
||||||
// 检查数据通道状态,这是文件传输的实际通道
|
// 改进传输过程中的连接状态检查
|
||||||
const channelState = connection.getConnectState();
|
const channelState = connection.getConnectState();
|
||||||
if (channelState.state === 'closed') {
|
const isChannelUsable =
|
||||||
console.warn(`数据通道已关闭,停止文件传输`);
|
channelState.state === 'open' ||
|
||||||
throw new Error('数据通道已关闭');
|
channelState.isDataChannelConnected ||
|
||||||
}
|
channelState.isPeerConnected ||
|
||||||
|
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket');
|
||||||
|
|
||||||
// 如果连接暂时断开但数据通道可用,仍然可以尝试发送
|
if (!isChannelUsable) {
|
||||||
if (!connection.getConnectState().isConnected && channelState.state === 'connecting') {
|
console.warn(`数据传输通道不可用,停止文件传输:`, {
|
||||||
console.warn(`WebRTC 连接暂时断开,但数据通道正在连接,继续尝试发送文件块 ${chunkIndex}`);
|
state: channelState.state,
|
||||||
|
isDataChannelConnected: channelState.isDataChannelConnected,
|
||||||
|
isPeerConnected: channelState.isPeerConnected,
|
||||||
|
isWebSocketConnected: channelState.isWebSocketConnected,
|
||||||
|
currentConnectType: channelState.currentConnectType
|
||||||
|
});
|
||||||
|
throw new Error('数据传输通道不可用');
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = chunkIndex * chunkSize;
|
const start = chunkIndex * chunkSize;
|
||||||
@@ -596,26 +629,26 @@ export function useFileTransferBusiness(connection: IWebConnection) {
|
|||||||
|
|
||||||
// 发送文件列表
|
// 发送文件列表
|
||||||
const sendFileList = useCallback((fileList: FileInfo[]) => {
|
const sendFileList = useCallback((fileList: FileInfo[]) => {
|
||||||
// 检查连接状态 - 优先检查数据通道状态,因为 P2P 连接可能已经建立但状态未及时更新
|
// 改进连接状态检查逻辑
|
||||||
const channelState = connection.getConnectState();
|
const channelState = connection.getConnectState();
|
||||||
const peerConnected = channelState.isPeerConnected;
|
const isReadyToSend =
|
||||||
const dataChannelConnected = channelState.isDataChannelConnected;
|
channelState.state === 'open' ||
|
||||||
const channelReadyState = channelState.state;
|
channelState.isDataChannelConnected ||
|
||||||
|
channelState.isPeerConnected ||
|
||||||
|
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') ||
|
||||||
|
channelState.isConnected;
|
||||||
|
|
||||||
console.log('发送文件列表检查:', {
|
console.log('发送文件列表检查:', {
|
||||||
channelState,
|
state: channelState.state,
|
||||||
peerConnected,
|
isDataChannelConnected: channelState.isDataChannelConnected,
|
||||||
dataChannelConnected,
|
isPeerConnected: channelState.isPeerConnected,
|
||||||
channelReadyState,
|
isWebSocketConnected: channelState.isWebSocketConnected,
|
||||||
|
currentConnectType: channelState.currentConnectType,
|
||||||
|
isConnected: channelState.isConnected,
|
||||||
|
isReadyToSend,
|
||||||
fileListLength: fileList.length
|
fileListLength: fileList.length
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用更宽松的条件检查连接状态
|
|
||||||
const isReadyToSend = channelReadyState === 'open' ||
|
|
||||||
dataChannelConnected ||
|
|
||||||
peerConnected ||
|
|
||||||
channelState.isConnected;
|
|
||||||
|
|
||||||
if (isReadyToSend) {
|
if (isReadyToSend) {
|
||||||
console.log('发送文件列表:', fileList.map(f => f.name));
|
console.log('发送文件列表:', fileList.map(f => f.name));
|
||||||
|
|
||||||
@@ -629,42 +662,36 @@ export function useFileTransferBusiness(connection: IWebConnection) {
|
|||||||
// 不立即重试,让上层逻辑处理重试
|
// 不立即重试,让上层逻辑处理重试
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('连接未就绪,等待连接后再发送文件列表:', {
|
console.log('连接未就绪,等待连接后再发送文件列表');
|
||||||
channelReadyState,
|
|
||||||
dataChannelConnected,
|
|
||||||
peerConnected,
|
|
||||||
isConnected: channelState.isConnected
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, [connection]);
|
}, [connection]);
|
||||||
|
|
||||||
// 请求文件
|
// 请求文件
|
||||||
const requestFile = useCallback((fileId: string, fileName: string) => {
|
const requestFile = useCallback((fileId: string, fileName: string) => {
|
||||||
const channelState = connection.getConnectState();
|
const channelState = connection.getConnectState();
|
||||||
const isChannelOpen = channelState.state === 'open';
|
|
||||||
const isDataChannelConnected = channelState.isDataChannelConnected;
|
// 统一的连接状态检查逻辑
|
||||||
const isPeerConnected = channelState.isPeerConnected;
|
const isReadyToRequest =
|
||||||
const isConnected = channelState.isConnected;
|
channelState.state === 'open' ||
|
||||||
|
channelState.isDataChannelConnected ||
|
||||||
|
channelState.isPeerConnected ||
|
||||||
|
(channelState.isWebSocketConnected && channelState.currentConnectType === 'websocket') ||
|
||||||
|
channelState.isConnected;
|
||||||
|
|
||||||
console.log('请求文件前检查连接状态:', {
|
console.log('请求文件前检查连接状态:', {
|
||||||
fileName,
|
fileName,
|
||||||
fileId,
|
fileId,
|
||||||
isChannelOpen,
|
state: channelState.state,
|
||||||
isDataChannelConnected,
|
isDataChannelConnected: channelState.isDataChannelConnected,
|
||||||
isPeerConnected,
|
isPeerConnected: channelState.isPeerConnected,
|
||||||
isConnected
|
isWebSocketConnected: channelState.isWebSocketConnected,
|
||||||
|
currentConnectType: channelState.currentConnectType,
|
||||||
|
isConnected: channelState.isConnected,
|
||||||
|
isReadyToRequest
|
||||||
});
|
});
|
||||||
|
|
||||||
// 使用更宽松的条件检查连接状态
|
|
||||||
const isReadyToRequest = isChannelOpen || isDataChannelConnected || isPeerConnected || isConnected;
|
|
||||||
|
|
||||||
if (!isReadyToRequest) {
|
if (!isReadyToRequest) {
|
||||||
console.error('数据通道未准备就绪,无法请求文件:', {
|
console.error('数据通道未准备就绪,无法请求文件');
|
||||||
isChannelOpen,
|
|
||||||
isDataChannelConnected,
|
|
||||||
isPeerConnected,
|
|
||||||
isConnected
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ const getCurrentBaseUrl = () => {
|
|||||||
|
|
||||||
// 动态获取 WebSocket URL - 总是在客户端运行时计算
|
// 动态获取 WebSocket URL - 总是在客户端运行时计算
|
||||||
const getCurrentWsUrl = () => {
|
const getCurrentWsUrl = () => {
|
||||||
return "ws://192.168.1.120:8080"
|
// return "ws://192.168.1.120:8080"
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
// 检查是否是 Next.js 开发服务器(端口 3000 或 3001)
|
// 检查是否是 Next.js 开发服务器(端口 3000 或 3001)
|
||||||
const isNextDevServer = window.location.hostname === 'localhost' &&
|
const isNextDevServer = window.location.hostname === 'localhost' &&
|
||||||
|
|||||||
Reference in New Issue
Block a user