Compare commits
3 Commits
69115c7318
...
a147766118
Author | SHA1 | Date | |
---|---|---|---|
a147766118 | |||
86acc89215 | |||
224eec48c0 |
@ -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>
|
||||
|
@ -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: "",
|
||||
|
@ -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])
|
||||
};
|
||||
|
@ -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)}
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user