import { useEffect, useState, useCallback } from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; import { setFetchedTorrents } from "../actions/torrents"; import { newMovieEvent } from "../actions/movies"; import { newEpisodeEvent } from "../actions/shows"; const mapStateToProps = state => ({ isLogged: state.userStore.get("isLogged") }); const mapDispatchToProps = { setFetchedTorrents, newMovieEvent, newEpisodeEvent }; const WsHandler = ({ isLogged, setFetchedTorrents, newMovieEvent, newEpisodeEvent }) => { const [ws, setWs] = useState(null); const stop = useCallback(() => { if (!ws) { return; } ws.close(); setWs(null); }, [ws]); const connect = useCallback(() => { if (ws) { return; } if (!isLogged) { stop(); } const type = location.protocol === "https:" ? "wss" : "ws"; const socket = new WebSocket(type + ":" + location.host + "/events"); socket.onopen = () => { socket.send( JSON.stringify({ type: "subscribe", message: "torrents" }) ); socket.send( JSON.stringify({ type: "subscribe", message: "newVideo" }) ); }; socket.onmessage = event => { if (!event.data) { return; } const data = JSON.parse(event.data); if (!data.type) { return; } if (data.status !== "ok") { // TODO: handle this somehow return; } switch (data.type) { case "torrents": setFetchedTorrents(data.message); break; case "newVideo": if (data.message.type === "movie") { newMovieEvent(data.message.data); } else if (data.message.type === "episode") { newEpisodeEvent(data.message.data); } break; } }; socket.onerror = () => { stop(); }; setWs(socket); }, [ws, isLogged, newMovieEvent, setFetchedTorrents, newEpisodeEvent, stop]); useEffect(() => { const intervalID = setInterval(() => { if (!ws) { connect(); return; } if (ws.readyState === WebSocket.CLOSED) { stop(); } }, 10000); if (!ws) { connect(); } return () => { if (ws) { stop(); } clearInterval(intervalID); }; }, [ws, connect, stop]); return null; }; WsHandler.propTypes = { isLogged: PropTypes.bool.isRequired, setFetchedTorrents: PropTypes.func, newMovieEvent: PropTypes.func, newEpisodeEvent: PropTypes.func }; export default connect(mapStateToProps, mapDispatchToProps)(WsHandler);