Files
file-transfer-go/chuan-next/src/hooks/webrtc/useTextTransferBusiness.ts

167 lines
4.6 KiB
TypeScript

import { useState, useCallback, useRef, useEffect } from 'react';
import type { WebRTCConnection } from './useSharedWebRTCManager';
// 文本传输状态
interface TextTransferState {
isConnecting: boolean;
isConnected: boolean;
isWebSocketConnected: boolean;
connectionError: string | null;
currentText: string; // 当前文本内容
isTyping: boolean; // 对方是否在输入
}
// 回调类型
type TextSyncCallback = (text: string) => void;
type TypingStatusCallback = (isTyping: boolean) => void;
const CHANNEL_NAME = 'text-transfer';
/**
* 文本传输业务层
* 必须传入共享的 WebRTC 连接
*/
export function useTextTransferBusiness(connection: WebRTCConnection) {
const [state, setState] = useState<TextTransferState>({
isConnecting: false,
isConnected: false,
isWebSocketConnected: false,
connectionError: null,
currentText: '',
isTyping: false
});
// 回调引用
const textSyncCallbackRef = useRef<TextSyncCallback | null>(null);
const typingCallbackRef = useRef<TypingStatusCallback | null>(null);
// 更新状态的辅助函数
const updateState = useCallback((updates: Partial<TextTransferState>) => {
setState(prev => ({ ...prev, ...updates }));
}, []);
// 消息处理器
const handleMessage = useCallback((message: any) => {
if (!message.type.startsWith('text-')) return;
console.log('文本传输收到消息:', message.type, message);
switch (message.type) {
case 'text-sync':
// 实时文本同步 - 接收方看到发送方的实时编辑
if (message.payload && typeof message.payload.text === 'string') {
updateState({ currentText: message.payload.text });
// 触发文本同步回调
if (textSyncCallbackRef.current) {
textSyncCallbackRef.current(message.payload.text);
}
}
break;
case 'text-typing':
// 打字状态
if (typeof message.payload?.typing === 'boolean') {
updateState({ isTyping: message.payload.typing });
// 触发打字状态回调
if (typingCallbackRef.current) {
typingCallbackRef.current(message.payload.typing);
}
}
break;
default:
console.warn('未知的文本消息类型:', message.type);
}
}, [updateState]);
// 注册消息处理器
useEffect(() => {
const unregister = connection.registerMessageHandler(CHANNEL_NAME, handleMessage);
return unregister;
}, [handleMessage]);
// 监听连接状态变化 (直接使用 connection 的状态)
useEffect(() => {
// 这里我们直接依赖 connection 的状态变化
// 由于我们使用共享连接,状态会自动同步
}, []);
// 连接
const connect = useCallback((roomCode: string, role: 'sender' | 'receiver') => {
return connection.connect(roomCode, role);
}, [connection]);
// 断开连接
const disconnect = useCallback(() => {
return connection.disconnect();
}, [connection]);
// 发送实时文本同步 (替代原来的 sendMessage)
const sendTextSync = useCallback((text: string) => {
if (!connection) return;
const message = {
type: 'text-sync',
payload: { text }
};
connection.sendMessage(message, CHANNEL_NAME);
console.log('发送实时文本同步:', text.length, '字符');
}, [connection]);
// 发送打字状态
const sendTypingStatus = useCallback((isTyping: boolean) => {
if (!connection) return;
const message = {
type: 'text-typing',
payload: { typing: isTyping }
};
connection.sendMessage(message, CHANNEL_NAME);
console.log('发送打字状态:', isTyping);
}, [connection]);
// 设置文本同步回调
const onTextSync = useCallback((callback: TextSyncCallback) => {
textSyncCallbackRef.current = callback;
// 返回清理函数
return () => {
textSyncCallbackRef.current = null;
};
}, []);
// 设置打字状态回调
const onTypingStatus = useCallback((callback: TypingStatusCallback) => {
typingCallbackRef.current = callback;
// 返回清理函数
return () => {
typingCallbackRef.current = null;
};
}, []);
return {
// 状态 - 直接从 connection 获取
isConnecting: connection.isConnecting,
isConnected: connection.isConnected,
isWebSocketConnected: connection.isWebSocketConnected,
connectionError: connection.error,
currentText: state.currentText,
isTyping: state.isTyping,
// 操作方法
connect,
disconnect,
sendTextSync,
sendTypingStatus,
// 回调设置
onTextSync,
onTypingStatus
};
}