diff --git a/frontend/js/components/buttons/showMore.js b/frontend/js/components/buttons/showMore.js
index 333dce6..9108b41 100644
--- a/frontend/js/components/buttons/showMore.js
+++ b/frontend/js/components/buttons/showMore.js
@@ -27,7 +27,7 @@ export const ShowMore = ({ children, id, inLibrary }) => {
ShowMore.propTypes = {
id: PropTypes.string,
inLibrary: PropTypes.bool.isRequired,
- children: PropTypes.oneOf(PropTypes.object, PropTypes.array)
+ children: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
};
ShowMore.defaultProps = {
id: "",
diff --git a/frontend/js/components/forms/modal.js b/frontend/js/components/forms/modal.js
index 4ee6cc4..508800d 100644
--- a/frontend/js/components/forms/modal.js
+++ b/frontend/js/components/forms/modal.js
@@ -48,5 +48,5 @@ FormModal.propTypes = {
icon: PropTypes.string,
title: PropTypes.string,
handleSubmit: PropTypes.func,
- children: PropTypes.oneOf(PropTypes.object, PropTypes.array)
+ children: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
};
diff --git a/frontend/js/components/list/posters.js b/frontend/js/components/list/posters.js
index 2e78a06..87339da 100644
--- a/frontend/js/components/list/posters.js
+++ b/frontend/js/components/list/posters.js
@@ -85,82 +85,96 @@ ListPosters.propTypes = {
export default ListPosters;
-const Posters = props => {
+const Posters = ({
+ elmts,
+ onKeyEnter,
+ selectedImdbId,
+ selectPoster,
+ onDoubleClick
+}) => {
const addMoreCount = 20;
const [size, setSize] = useState(0);
const [postersPerRow, setPostersPerRow] = useState(0);
const [posterHeight, setPosterHeight] = useState(0);
- const loadMore = () => {
- if (size === props.elmts.size) {
+ const loadMore = useCallback(() => {
+ if (size === elmts.size) {
return;
}
const newSize =
- size + addMoreCount >= props.elmts.size
- ? props.elmts.size
- : size + addMoreCount;
+ size + addMoreCount >= elmts.size ? elmts.size : size + addMoreCount;
setSize(newSize);
- };
+ }, [size, elmts.size]);
useEffect(() => {
loadMore();
- }, [props.elmts.size]);
+ }, [elmts.size, loadMore]);
- const move = event => {
- // Only run the function if nothing else if actively focused
- if (document.activeElement.tagName.toLowerCase() !== "body") {
- return;
- }
-
- let diff = 0;
- let moveFocus = 0;
- switch (event.key) {
- case "Enter":
- props.onKeyEnter(props.selectedImdbId);
+ const move = useCallback(
+ event => {
+ // Only run the function if nothing else if actively focused
+ if (document.activeElement.tagName.toLowerCase() !== "body") {
return;
- case "l":
- diff = 1;
- break;
- case "h":
- diff = -1;
- break;
- case "k":
- diff = -1 * postersPerRow;
- moveFocus = -1 * posterHeight;
- break;
- case "j":
- diff = postersPerRow;
- moveFocus = posterHeight;
- break;
- default:
- return;
- }
+ }
- // Get the index of the currently selected item
- const idx = props.elmts.keySeq().findIndex(k => k === props.selectedImdbId);
+ let diff = 0;
+ let moveFocus = 0;
+ switch (event.key) {
+ case "Enter":
+ onKeyEnter(selectedImdbId);
+ return;
+ case "l":
+ diff = 1;
+ break;
+ case "h":
+ diff = -1;
+ break;
+ case "k":
+ diff = -1 * postersPerRow;
+ moveFocus = -1 * posterHeight;
+ break;
+ case "j":
+ diff = postersPerRow;
+ moveFocus = posterHeight;
+ break;
+ default:
+ return;
+ }
- var newIdx = idx + diff;
+ // Get the index of the currently selected item
+ const idx = elmts.keySeq().findIndex(k => k === selectedImdbId);
- // Handle edge cases
- if (newIdx > props.elmts.size - 1) {
- newIdx = props.elmts.size - 1;
- } else if (newIdx < 0) {
- newIdx = 0;
- }
+ var newIdx = idx + diff;
- // Get the imdbID of the newly selected item
- var selectedImdb = Object.keys(props.elmts.toJS())[newIdx];
+ // Handle edge cases
+ if (newIdx > elmts.size - 1) {
+ newIdx = elmts.size - 1;
+ } else if (newIdx < 0) {
+ newIdx = 0;
+ }
- // Select the movie
- props.selectPoster(selectedImdb);
- if (moveFocus !== 0) {
- window.scrollBy(0, moveFocus);
- }
- };
+ // Get the imdbID of the newly selected item
+ var selectedImdb = Object.keys(elmts.toJS())[newIdx];
- const posterCount = useCallback(node => {
+ // Select the movie
+ selectPoster(selectedImdb);
+ if (moveFocus !== 0) {
+ window.scrollBy(0, moveFocus);
+ }
+ },
+ [
+ elmts,
+ onKeyEnter,
+ posterHeight,
+ postersPerRow,
+ selectPoster,
+ selectedImdbId
+ ]
+ );
+
+ const posterCount = node => {
if (node === null) {
return;
}
@@ -180,7 +194,7 @@ const Posters = props => {
childWidth >= parentWidth ? 1 : Math.floor(parentWidth / childWidth);
setPostersPerRow(numberPerRow);
setPosterHeight(posterHeight);
- });
+ };
useEffect(() => {
document.onkeypress = move;
@@ -189,7 +203,7 @@ const Posters = props => {
};
}, [move]);
- if (props.elmts.size === 0) {
+ if (elmts.size === 0) {
return (
No result
@@ -203,23 +217,23 @@ const Posters = props => {
className="poster-list d-flex flex-column flex-sm-row flex-sm-wrap justify-content-around"
dataLength={size}
next={loadMore}
- hasMore={size !== props.elmts.size}
+ hasMore={size !== elmts.size}
loader={
}
>
- {props.elmts
+ {elmts
.slice(0, size)
.toIndexedSeq()
.map(function(el, index) {
const imdbId = el.get("imdb_id");
- const selected = imdbId === props.selectedImdbId ? true : false;
+ const selected = imdbId === selectedImdbId ? true : false;
return (
props.selectPoster(imdbId)}
- onDoubleClick={() => props.onDoubleClick(imdbId)}
+ onClick={() => selectPoster(imdbId)}
+ onDoubleClick={() => onDoubleClick(imdbId)}
/>
);
}, this)}
diff --git a/frontend/js/components/movies/route.js b/frontend/js/components/movies/route.js
index 7a10448..a4057d1 100644
--- a/frontend/js/components/movies/route.js
+++ b/frontend/js/components/movies/route.js
@@ -55,7 +55,7 @@ const MoviesRoute = ({
);
};
MoviesRoute.propTypes = {
- component: PropTypes.func,
+ component: PropTypes.object,
match: PropTypes.object,
isExplorerFetched: PropTypes.bool.isRequired,
fetchMovies: PropTypes.func.isRequired,
diff --git a/frontend/js/components/torrents/search.js b/frontend/js/components/torrents/search.js
index 1bc1649..044d1a5 100644
--- a/frontend/js/components/torrents/search.js
+++ b/frontend/js/components/torrents/search.js
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { useState, useEffect, useCallback } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { addTorrent, searchTorrents } from "../../actions/torrents";
@@ -15,12 +15,21 @@ const mapStateToProps = state => ({
});
const mapDispatchToProps = { addTorrent, searchTorrents };
-const TorrentSearch = props => {
- const [search, setSearch] = useState(props.match.params.search || "");
- const [type, setType] = useState(props.match.params.type || "");
+const TorrentSearch = ({
+ searching,
+ searchTorrents,
+ results,
+ addTorrent,
+ history,
+ match
+}) => {
+ const [search, setSearch] = useState(match.params.search || "");
+ const [type, setType] = useState(match.params.type || "");
const [url, setUrl] = useState("");
- const getUrl = () => `/torrents/search/${type}/${encodeURI(search)}`;
+ const getUrl = useCallback(() => {
+ return `/torrents/search/${type}/${encodeURI(search)}`;
+ }, [type, search]);
useEffect(() => {
if (search === "") {
@@ -31,9 +40,9 @@ const TorrentSearch = props => {
}
const url = getUrl();
- props.searchTorrents(url);
- props.history.push(url);
- }, [url]);
+ searchTorrents(url);
+ history.push(url);
+ }, [url, getUrl, searchTorrents, history, search, type]);
return (
@@ -68,9 +77,9 @@ const TorrentSearch = props => {
diff --git a/frontend/js/components/websocket.js b/frontend/js/components/websocket.js
index a54fbf9..04f6400 100644
--- a/frontend/js/components/websocket.js
+++ b/frontend/js/components/websocket.js
@@ -1,4 +1,5 @@
-import { useEffect, useState } from "react";
+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";
@@ -13,47 +14,28 @@ const mapDispatchToProps = {
newEpisodeEvent
};
-const WsHandler = props => {
+const WsHandler = ({
+ isLogged,
+ setFetchedTorrents,
+ newMovieEvent,
+ newEpisodeEvent
+}) => {
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 = () => {
+ const stop = useCallback(() => {
if (!ws) {
return;
}
ws.close();
setWs(null);
- };
+ }, [ws]);
- const connect = () => {
+ const connect = useCallback(() => {
if (ws) {
return;
}
- if (!props.isLogged) {
+ if (!isLogged) {
stop();
}
@@ -91,13 +73,13 @@ const WsHandler = props => {
switch (data.type) {
case "torrents":
- props.setFetchedTorrents(data.message);
+ setFetchedTorrents(data.message);
break;
case "newVideo":
if (data.message.type === "movie") {
- props.newMovieEvent(data.message.data);
+ newMovieEvent(data.message.data);
} else if (data.message.type === "episode") {
- props.newEpisodeEvent(data.message.data);
+ newEpisodeEvent(data.message.data);
}
break;
}
@@ -108,9 +90,39 @@ const WsHandler = props => {
};
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);