Compare commits

...

3 Commits

Author SHA1 Message Date
a147766118 Fix icons path in index.html
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2020-02-28 14:42:50 +01:00
86acc89215 Fix the react warnings 2020-02-28 13:52:54 +01:00
224eec48c0 Update the source map configuration 2020-02-28 13:52:33 +01:00
8 changed files with 149 additions and 117 deletions

View File

@ -5,10 +5,10 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="Description" content="Canapé">
<link rel="icon" type="image/png" href="<%= require("./img/favicon-32x32.png") %>" sizes="32x32">
<link rel="icon" type="image/png" href="<%= require("./img/favicon-16x16.png") %>" sizes="16x16">
<link rel="icon" type="image/png" href="<%= require("./img/favicon-16x16.png").default %>" sizes="16x16">
<link rel="icon" type="image/png" href="<%= require("./img/favicon-32x32.png").default %>" sizes="32x32">
<meta name="msapplication-navbutton-color" content="#4E5D6C">
<link rel="mask-icon" href="<%= require("./img/safari-pinned-tab.svg") %>" color="#5bbad5">
<link rel="mask-icon" href="<%= require("./img/safari-pinned-tab.svg").default %>" color="#5bbad5">
<title>Canapé</title>
</head>
<body>

View File

@ -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: "",

View File

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

View File

@ -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 (
<div className="jumbotron">
<h2>No result</h2>
@ -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={<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 (
<Poster
url={el.get("poster_url")}
key={index}
selected={selected}
onClick={() => props.selectPoster(imdbId)}
onDoubleClick={() => props.onDoubleClick(imdbId)}
onClick={() => selectPoster(imdbId)}
onDoubleClick={() => onDoubleClick(imdbId)}
/>
);
}, this)}

View File

@ -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,

View File

@ -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 (
<div className="row">
@ -68,9 +77,9 @@ const TorrentSearch = props => {
</div>
<div className="col-12">
<TorrentList
searching={props.searching}
results={props.results}
addTorrent={props.addTorrent}
searching={searching}
results={results}
addTorrent={addTorrent}
searchFromURL={search}
/>
</div>

View File

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

View File

@ -104,11 +104,8 @@ const config = {
],
resolve: {
extensions: [".js"]
}
},
devtool: mode === "production" ? "source-map" : "inline-source-map"
};
if (process.env.NODE_ENV !== "production") {
config.devtool = "#cheap-module-source-map";
}
module.exports = config;