import React from "react"; import axios from "axios"; import { ChatMessage } from "../database.d"; import ChatReplay from "./ChatReplay"; import { IconChevronDown, IconFilter } from "../icons"; import { useDebounce } from "../hooks/useDebounce"; import { parseChatReplay } from "./parser"; export type ChatReplayPanelProps = { src: string; currentTimeSeconds: number; onChatToggle?: (isVisible: boolean) => any; }; const ChatReplayPanel = (props: ChatReplayPanelProps) => { const [replayData, setReplayData] = React.useState(null); const [filteredReplayData, setFilteredReplayData] = React.useState< ChatMessage[] >(null); const [downloadProgress, setDownloadProgress] = React.useState(-1); const [isFilterVisible, setIsFilterVisible] = React.useState(false); const [chatFilter, setChatFilter] = React.useState(""); const [isChatVisible, setIsChatVisible] = React.useState(false); const [isErrored, setIsErrored] = React.useState(false); const refChatScrollDiv = React.useRef(null); const activeChatFilter = useDebounce(chatFilter, 250); const downloadChatData = async () => { setDownloadProgress(0); setReplayData(null); setIsErrored(false); try { const data = await axios.get(props.src, { onDownloadProgress: ({ loaded }) => setDownloadProgress(loaded), transformResponse: (res) => res, }); setReplayData(parseChatReplay(data.data)); setIsChatVisible(true); } catch (ex) { console.log("[chat] error parsing chat:", ex); setIsErrored(true); } }; React.useEffect(() => { if (!replayData) return; if (!activeChatFilter) return setFilteredReplayData(replayData); setFilteredReplayData( replayData.filter( (message) => !!message.message && message.message.toLowerCase().includes(activeChatFilter.toLowerCase()) ) ); }, [activeChatFilter, replayData]); /** * Automatically download chat replay */ React.useEffect(() => { downloadChatData(); }, [props.src]); React.useEffect(() => { if (refChatScrollDiv.current) refChatScrollDiv.current.scrollTo({ top: refChatScrollDiv.current.scrollHeight, behavior: "smooth", }); }, [props.currentTimeSeconds]); React.useEffect(() => { props.onChatToggle?.(isChatVisible); }, [isChatVisible]); if (replayData === null) return (
{ if (isErrored || downloadProgress < 0) downloadChatData(); }} > {isErrored ? (

Error loading chat, click to retry

) : downloadProgress < 0 ? ( <>

Chat replay available!

Click to Enable

) : downloadProgress === 0 ? (

Loading chat replay...

) : (

Loaded {(downloadProgress / 1024 / 1024).toFixed(2)}MB

)}
); return (
Chat replay
{isFilterVisible && (
setChatFilter(e.target.value)} />
)}
{isChatVisible && (
)}
); }; export default ChatReplayPanel;