2024-04-07 01:53:46 +08:00
|
|
|
"use client";
|
2024-04-07 04:49:59 +08:00
|
|
|
import { useState, useEffect, useCallback, useRef, useContext } from "react";
|
2024-04-07 01:53:46 +08:00
|
|
|
import useWebSocket, { ReadyState } from "react-use-websocket";
|
|
|
|
import MessageDispatcher from "./message";
|
|
|
|
import { Token } from "@/lib/types";
|
2024-04-07 03:23:34 +08:00
|
|
|
import dayjs from "dayjs";
|
2024-04-07 04:49:59 +08:00
|
|
|
import { DanmuContext } from "./provider";
|
2024-04-07 01:53:46 +08:00
|
|
|
|
|
|
|
const MOMO_IM_URL = "wss://live-ws.immomo.com/ws/im";
|
|
|
|
|
2024-04-07 05:06:03 +08:00
|
|
|
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;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2024-04-07 03:23:34 +08:00
|
|
|
export default function Danmu({ token }: { token: Token }) {
|
2024-04-07 01:53:46 +08:00
|
|
|
const [messageHistory, setMessageHistory] = useState<MessageEvent<any>[]>([]);
|
2024-04-07 02:02:08 +08:00
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
2024-04-07 05:06:03 +08:00
|
|
|
const { liveId, dispatch } = useContext(DanmuContext);
|
|
|
|
const { genMessage } = useGenMessage();
|
2024-04-07 01:53:46 +08:00
|
|
|
|
|
|
|
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;
|
2024-04-07 04:49:59 +08:00
|
|
|
const roomId = liveId;
|
2024-04-07 01:53:46 +08:00
|
|
|
const momoToken = token.token;
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (ReadyState.OPEN === readyState) {
|
2024-04-07 04:49:59 +08:00
|
|
|
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));
|
2024-04-07 05:06:03 +08:00
|
|
|
console.log("重新连接...");
|
2024-04-07 04:49:59 +08:00
|
|
|
setMessageHistory([]);
|
2024-04-07 05:06:03 +08:00
|
|
|
dispatch({
|
|
|
|
type: "listener",
|
|
|
|
payload: {
|
|
|
|
listener: (msg: string) => {
|
|
|
|
const data = genMessage(msg);
|
|
|
|
sendMessage(JSON.stringify(data));
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
2024-04-07 04:49:59 +08:00
|
|
|
}
|
2024-04-07 01:53:46 +08:00
|
|
|
}
|
2024-04-07 04:49:59 +08:00
|
|
|
}, [readyState, roomId, momoId, momoToken]);
|
2024-04-07 01:53:46 +08:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (lastMessage !== null) {
|
|
|
|
if (lastMessage.data) {
|
2024-04-07 03:23:34 +08:00
|
|
|
const current = dayjs().format("HH:mm:ss");
|
2024-04-07 01:53:46 +08:00
|
|
|
const message = JSON.parse(lastMessage.data);
|
|
|
|
if (message.type === "pong") {
|
|
|
|
return;
|
|
|
|
}
|
2024-04-07 03:23:34 +08:00
|
|
|
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));
|
2024-04-07 02:02:08 +08:00
|
|
|
setTimeout(() => {
|
2024-04-07 03:23:34 +08:00
|
|
|
if (ref.current) {
|
|
|
|
ref.current.scrollTop = ref.current.scrollHeight;
|
|
|
|
}
|
2024-04-07 02:02:08 +08:00
|
|
|
}, 0);
|
|
|
|
}
|
2024-04-07 01:53:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [lastMessage]);
|
|
|
|
|
|
|
|
return (
|
2024-04-07 03:32:54 +08:00
|
|
|
<div className="h-[60vh] md:h-[40vh] overflow-auto" ref={ref}>
|
2024-04-07 01:53:46 +08:00
|
|
|
{messageHistory.map((message, idx) => (
|
|
|
|
<MessageDispatcher key={idx} message={message} />
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
);
|
2024-04-07 03:23:34 +08:00
|
|
|
}
|