"use client"; import { useState, useEffect, useCallback, useRef, useContext } from "react"; import useWebSocket, { ReadyState } from "react-use-websocket"; import MessageDispatcher from "./message"; import { Token } from "@/lib/types"; import dayjs from "dayjs"; import { DanmuContext } from "./provider"; const MOMO_IM_URL = "wss://live-ws.immomo.com/ws/im"; const useGenMessage = () => { const [msgId, setMsgId] = useState(3); return { genMessage(text: string) { const msg = { msg_id: msgId, client_time: Date.now(), type: "Bili", data: { text }, }; setMsgId(msgId + 1); return msg; }, }; }; export default function Danmu({ token }: { token: Token }) { const [messageHistory, setMessageHistory] = useState[]>([]); const ref = useRef(null); const { liveId, dispatch } = useContext(DanmuContext); const { genMessage } = useGenMessage(); const { sendMessage, lastMessage, readyState } = useWebSocket(MOMO_IM_URL, { heartbeat: { message: () => { const pingMessage = { msg_id: 2, client_time: Date.now(), type: "Ping", data: {}, }; return JSON.stringify(pingMessage); }, interval: 5000, }, }); const momoId = token.uid; const roomId = liveId; const momoToken = token.token; useEffect(() => { if (ReadyState.OPEN === readyState) { const clientTime = Date.now(); const data = { msg_id: 1, client_time: clientTime, type: "Sauth", data: { momoid: momoId, roomid: roomId, role: 6, isVisitor: false, token: momoToken, }, }; if (roomId) { sendMessage(JSON.stringify(data)); console.log("重新连接..."); setMessageHistory([]); dispatch({ type: "listener", payload: { listener: (msg: string) => { const data = genMessage(msg); sendMessage(JSON.stringify(data)); }, }, }); } } }, [readyState, roomId, momoId, momoToken]); useEffect(() => { if (lastMessage !== null) { if (lastMessage.data) { const current = dayjs().format("HH:mm:ss"); const message = JSON.parse(lastMessage.data); if (message.type === "pong") { return; } if (message.type === "group") { message.groups.forEach((group: any) => { group.current = current; setMessageHistory((prev) => prev.concat(group)); setTimeout(() => { if (ref.current) { ref.current.scrollTop = ref.current.scrollHeight; } }, 0); }); } else { message.current = current; setMessageHistory((prev) => prev.concat(message)); setTimeout(() => { if (ref.current) { ref.current.scrollTop = ref.current.scrollHeight; } }, 0); } } } }, [lastMessage]); return (
{messageHistory.map((message, idx) => ( ))}
); }