From aaad333ef607dbddb2739e22156e60c556f98925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Delattre?= Date: Thu, 23 May 2019 22:49:30 +0200 Subject: [PATCH] Add a websocket handler in the frontend --- frontend/js/actions/torrents.js | 11 ++++ frontend/js/app.js | 2 + frontend/js/components/torrents/list.js | 39 +++--------- frontend/js/components/websocket.js | 82 +++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 29 deletions(-) create mode 100644 frontend/js/components/websocket.js diff --git a/frontend/js/actions/torrents.js b/frontend/js/actions/torrents.js index 8af86d0..69e6b2c 100644 --- a/frontend/js/actions/torrents.js +++ b/frontend/js/actions/torrents.js @@ -37,3 +37,14 @@ export function searchTorrents(url) { configureAxios().get(url) ) } + +export function setFetchedTorrents(torrents) { + return { + type: "TORRENTS_FETCH_FULFILLED", + payload: { + response: { + data : torrents, + }, + }, + } +} diff --git a/frontend/js/app.js b/frontend/js/app.js index 4b43409..ba2ac00 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -32,6 +32,7 @@ import Alert from "./components/alerts/alert" import MovieList from "./components/movies/list" import MoviesRoute from "./components/movies/route" import NavBar from "./components/navbar" +import WsHandler from "./components/websocket" import ShowDetails from "./components/shows/details" import ShowList from "./components/shows/list" import ShowsRoute from "./components/shows/route" @@ -46,6 +47,7 @@ import UserTokens from "./components/users/tokens" const App = () => (
+
diff --git a/frontend/js/components/torrents/list.js b/frontend/js/components/torrents/list.js index a20d5b3..d30d538 100644 --- a/frontend/js/components/torrents/list.js +++ b/frontend/js/components/torrents/list.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react" +import React, { useState } from "react" import PropTypes from "prop-types" import { Map, List } from "immutable" import { connect } from "react-redux" @@ -11,34 +11,15 @@ const mapDispatchToProps = { fetchTorrents, addTorrent, removeTorrent, }; -const TorrentList = (props) => { - const [fetched, setIsFetched] = useState(false); - - useEffect(() => { - const intervalID = setInterval(() => { - props.fetchTorrents(); - }, 10000); - - return () => { - clearInterval(intervalID); - }; - }); - - if (!fetched) { - props.fetchTorrents(); - setIsFetched(true); - } - - return ( -
- - -
- ); -} +const TorrentList = (props) => ( +
+ + +
+); TorrentList.propTypes = { fetchTorrents: PropTypes.func.isRequired, addTorrent: PropTypes.func.isRequired, diff --git a/frontend/js/components/websocket.js b/frontend/js/components/websocket.js new file mode 100644 index 0000000..3f70ee0 --- /dev/null +++ b/frontend/js/components/websocket.js @@ -0,0 +1,82 @@ +import { useEffect, useState } from "react" +import { connect } from "react-redux" +import { setFetchedTorrents } from "../actions/torrents" + +const mapStateToProps = (state) => ({ + isLogged: state.userStore.get("isLogged"), +}); +const mapDispatchToProps = { setFetchedTorrents }; + +const WsHandler = (props) => { + const [ws, setWs] = useState(null); + + 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]); + + const stop = () => { + if (!ws) { + return + } + ws.close() + setWs(null); + } + + const connect = () => { + if (ws) { return; } + + if (!props.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.onmessage = (event) => { + if (!event.data) { return } + + const data = JSON.parse(event.data); + if (!data.type){ return } + + switch (data.type) { + case "torrents": + props.setFetchedTorrents(data.message); + break; + } + } + + socket.onerror = () => { stop(); } + + setWs(socket) + } + + return null; +} + +export default connect(mapStateToProps, mapDispatchToProps)(WsHandler);