Add a websocket handler in the frontend

This commit is contained in:
Grégoire Delattre 2019-05-23 22:49:30 +02:00
parent 18127fa3a0
commit aaad333ef6
4 changed files with 105 additions and 29 deletions

View File

@ -37,3 +37,14 @@ export function searchTorrents(url) {
configureAxios().get(url) configureAxios().get(url)
) )
} }
export function setFetchedTorrents(torrents) {
return {
type: "TORRENTS_FETCH_FULFILLED",
payload: {
response: {
data : torrents,
},
},
}
}

View File

@ -32,6 +32,7 @@ import Alert from "./components/alerts/alert"
import MovieList from "./components/movies/list" import MovieList from "./components/movies/list"
import MoviesRoute from "./components/movies/route" import MoviesRoute from "./components/movies/route"
import NavBar from "./components/navbar" import NavBar from "./components/navbar"
import WsHandler from "./components/websocket"
import ShowDetails from "./components/shows/details" import ShowDetails from "./components/shows/details"
import ShowList from "./components/shows/list" import ShowList from "./components/shows/list"
import ShowsRoute from "./components/shows/route" import ShowsRoute from "./components/shows/route"
@ -46,6 +47,7 @@ import UserTokens from "./components/users/tokens"
const App = () => ( const App = () => (
<div> <div>
<WsHandler />
<NavBar /> <NavBar />
<Alert /> <Alert />
<div className="container-fluid"> <div className="container-fluid">

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react" import React, { useState } from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import { Map, List } from "immutable" import { Map, List } from "immutable"
import { connect } from "react-redux" import { connect } from "react-redux"
@ -11,25 +11,7 @@ const mapDispatchToProps = {
fetchTorrents, addTorrent, removeTorrent, fetchTorrents, addTorrent, removeTorrent,
}; };
const TorrentList = (props) => { 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 (
<div> <div>
<AddTorrent addTorrent={props.addTorrent} /> <AddTorrent addTorrent={props.addTorrent} />
<Torrents <Torrents
@ -38,7 +20,6 @@ const TorrentList = (props) => {
/> />
</div> </div>
); );
}
TorrentList.propTypes = { TorrentList.propTypes = {
fetchTorrents: PropTypes.func.isRequired, fetchTorrents: PropTypes.func.isRequired,
addTorrent: PropTypes.func.isRequired, addTorrent: PropTypes.func.isRequired,

View File

@ -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);