Compare commits
No commits in common. "a14776611849d2e2f1ef0142e5e08df436470432" and "69115c731854c886579a1c7303e241062e54c19b" have entirely different histories.
a147766118
...
69115c7318
@ -5,10 +5,10 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<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="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="Description" content="Canapé">
|
<meta name="Description" content="Canapé">
|
||||||
<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") %>" sizes="32x32">
|
||||||
<link rel="icon" type="image/png" href="<%= require("./img/favicon-32x32.png").default %>" sizes="32x32">
|
<link rel="icon" type="image/png" href="<%= require("./img/favicon-16x16.png") %>" sizes="16x16">
|
||||||
<meta name="msapplication-navbutton-color" content="#4E5D6C">
|
<meta name="msapplication-navbutton-color" content="#4E5D6C">
|
||||||
<link rel="mask-icon" href="<%= require("./img/safari-pinned-tab.svg").default %>" color="#5bbad5">
|
<link rel="mask-icon" href="<%= require("./img/safari-pinned-tab.svg") %>" color="#5bbad5">
|
||||||
<title>Canapé</title>
|
<title>Canapé</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -27,7 +27,7 @@ export const ShowMore = ({ children, id, inLibrary }) => {
|
|||||||
ShowMore.propTypes = {
|
ShowMore.propTypes = {
|
||||||
id: PropTypes.string,
|
id: PropTypes.string,
|
||||||
inLibrary: PropTypes.bool.isRequired,
|
inLibrary: PropTypes.bool.isRequired,
|
||||||
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
|
children: PropTypes.oneOf(PropTypes.object, PropTypes.array)
|
||||||
};
|
};
|
||||||
ShowMore.defaultProps = {
|
ShowMore.defaultProps = {
|
||||||
id: "",
|
id: "",
|
||||||
|
@ -48,5 +48,5 @@ FormModal.propTypes = {
|
|||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
handleSubmit: PropTypes.func,
|
handleSubmit: PropTypes.func,
|
||||||
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array])
|
children: PropTypes.oneOf(PropTypes.object, PropTypes.array)
|
||||||
};
|
};
|
||||||
|
@ -85,96 +85,82 @@ ListPosters.propTypes = {
|
|||||||
|
|
||||||
export default ListPosters;
|
export default ListPosters;
|
||||||
|
|
||||||
const Posters = ({
|
const Posters = props => {
|
||||||
elmts,
|
|
||||||
onKeyEnter,
|
|
||||||
selectedImdbId,
|
|
||||||
selectPoster,
|
|
||||||
onDoubleClick
|
|
||||||
}) => {
|
|
||||||
const addMoreCount = 20;
|
const addMoreCount = 20;
|
||||||
const [size, setSize] = useState(0);
|
const [size, setSize] = useState(0);
|
||||||
const [postersPerRow, setPostersPerRow] = useState(0);
|
const [postersPerRow, setPostersPerRow] = useState(0);
|
||||||
const [posterHeight, setPosterHeight] = useState(0);
|
const [posterHeight, setPosterHeight] = useState(0);
|
||||||
|
|
||||||
const loadMore = useCallback(() => {
|
const loadMore = () => {
|
||||||
if (size === elmts.size) {
|
if (size === props.elmts.size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSize =
|
const newSize =
|
||||||
size + addMoreCount >= elmts.size ? elmts.size : size + addMoreCount;
|
size + addMoreCount >= props.elmts.size
|
||||||
|
? props.elmts.size
|
||||||
|
: size + addMoreCount;
|
||||||
|
|
||||||
setSize(newSize);
|
setSize(newSize);
|
||||||
}, [size, elmts.size]);
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadMore();
|
loadMore();
|
||||||
}, [elmts.size, loadMore]);
|
}, [props.elmts.size]);
|
||||||
|
|
||||||
const move = useCallback(
|
const move = event => {
|
||||||
event => {
|
// Only run the function if nothing else if actively focused
|
||||||
// Only run the function if nothing else if actively focused
|
if (document.activeElement.tagName.toLowerCase() !== "body") {
|
||||||
if (document.activeElement.tagName.toLowerCase() !== "body") {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let diff = 0;
|
||||||
|
let moveFocus = 0;
|
||||||
|
switch (event.key) {
|
||||||
|
case "Enter":
|
||||||
|
props.onKeyEnter(props.selectedImdbId);
|
||||||
return;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
let diff = 0;
|
// Get the index of the currently selected item
|
||||||
let moveFocus = 0;
|
const idx = props.elmts.keySeq().findIndex(k => k === props.selectedImdbId);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the index of the currently selected item
|
var newIdx = idx + diff;
|
||||||
const idx = elmts.keySeq().findIndex(k => k === selectedImdbId);
|
|
||||||
|
|
||||||
var newIdx = idx + diff;
|
// Handle edge cases
|
||||||
|
if (newIdx > props.elmts.size - 1) {
|
||||||
|
newIdx = props.elmts.size - 1;
|
||||||
|
} else if (newIdx < 0) {
|
||||||
|
newIdx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle edge cases
|
// Get the imdbID of the newly selected item
|
||||||
if (newIdx > elmts.size - 1) {
|
var selectedImdb = Object.keys(props.elmts.toJS())[newIdx];
|
||||||
newIdx = elmts.size - 1;
|
|
||||||
} else if (newIdx < 0) {
|
|
||||||
newIdx = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the imdbID of the newly selected item
|
// Select the movie
|
||||||
var selectedImdb = Object.keys(elmts.toJS())[newIdx];
|
props.selectPoster(selectedImdb);
|
||||||
|
if (moveFocus !== 0) {
|
||||||
|
window.scrollBy(0, moveFocus);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Select the movie
|
const posterCount = useCallback(node => {
|
||||||
selectPoster(selectedImdb);
|
|
||||||
if (moveFocus !== 0) {
|
|
||||||
window.scrollBy(0, moveFocus);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[
|
|
||||||
elmts,
|
|
||||||
onKeyEnter,
|
|
||||||
posterHeight,
|
|
||||||
postersPerRow,
|
|
||||||
selectPoster,
|
|
||||||
selectedImdbId
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const posterCount = node => {
|
|
||||||
if (node === null) {
|
if (node === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -194,7 +180,7 @@ const Posters = ({
|
|||||||
childWidth >= parentWidth ? 1 : Math.floor(parentWidth / childWidth);
|
childWidth >= parentWidth ? 1 : Math.floor(parentWidth / childWidth);
|
||||||
setPostersPerRow(numberPerRow);
|
setPostersPerRow(numberPerRow);
|
||||||
setPosterHeight(posterHeight);
|
setPosterHeight(posterHeight);
|
||||||
};
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.onkeypress = move;
|
document.onkeypress = move;
|
||||||
@ -203,7 +189,7 @@ const Posters = ({
|
|||||||
};
|
};
|
||||||
}, [move]);
|
}, [move]);
|
||||||
|
|
||||||
if (elmts.size === 0) {
|
if (props.elmts.size === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="jumbotron">
|
<div className="jumbotron">
|
||||||
<h2>No result</h2>
|
<h2>No result</h2>
|
||||||
@ -217,23 +203,23 @@ const Posters = ({
|
|||||||
className="poster-list d-flex flex-column flex-sm-row flex-sm-wrap justify-content-around"
|
className="poster-list d-flex flex-column flex-sm-row flex-sm-wrap justify-content-around"
|
||||||
dataLength={size}
|
dataLength={size}
|
||||||
next={loadMore}
|
next={loadMore}
|
||||||
hasMore={size !== elmts.size}
|
hasMore={size !== props.elmts.size}
|
||||||
loader={<Loader />}
|
loader={<Loader />}
|
||||||
>
|
>
|
||||||
{elmts
|
{props.elmts
|
||||||
.slice(0, size)
|
.slice(0, size)
|
||||||
.toIndexedSeq()
|
.toIndexedSeq()
|
||||||
.map(function(el, index) {
|
.map(function(el, index) {
|
||||||
const imdbId = el.get("imdb_id");
|
const imdbId = el.get("imdb_id");
|
||||||
const selected = imdbId === selectedImdbId ? true : false;
|
const selected = imdbId === props.selectedImdbId ? true : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Poster
|
<Poster
|
||||||
url={el.get("poster_url")}
|
url={el.get("poster_url")}
|
||||||
key={index}
|
key={index}
|
||||||
selected={selected}
|
selected={selected}
|
||||||
onClick={() => selectPoster(imdbId)}
|
onClick={() => props.selectPoster(imdbId)}
|
||||||
onDoubleClick={() => onDoubleClick(imdbId)}
|
onDoubleClick={() => props.onDoubleClick(imdbId)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, this)}
|
}, this)}
|
||||||
|
@ -55,7 +55,7 @@ const MoviesRoute = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
MoviesRoute.propTypes = {
|
MoviesRoute.propTypes = {
|
||||||
component: PropTypes.object,
|
component: PropTypes.func,
|
||||||
match: PropTypes.object,
|
match: PropTypes.object,
|
||||||
isExplorerFetched: PropTypes.bool.isRequired,
|
isExplorerFetched: PropTypes.bool.isRequired,
|
||||||
fetchMovies: PropTypes.func.isRequired,
|
fetchMovies: PropTypes.func.isRequired,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { addTorrent, searchTorrents } from "../../actions/torrents";
|
import { addTorrent, searchTorrents } from "../../actions/torrents";
|
||||||
@ -15,21 +15,12 @@ const mapStateToProps = state => ({
|
|||||||
});
|
});
|
||||||
const mapDispatchToProps = { addTorrent, searchTorrents };
|
const mapDispatchToProps = { addTorrent, searchTorrents };
|
||||||
|
|
||||||
const TorrentSearch = ({
|
const TorrentSearch = props => {
|
||||||
searching,
|
const [search, setSearch] = useState(props.match.params.search || "");
|
||||||
searchTorrents,
|
const [type, setType] = useState(props.match.params.type || "");
|
||||||
results,
|
|
||||||
addTorrent,
|
|
||||||
history,
|
|
||||||
match
|
|
||||||
}) => {
|
|
||||||
const [search, setSearch] = useState(match.params.search || "");
|
|
||||||
const [type, setType] = useState(match.params.type || "");
|
|
||||||
const [url, setUrl] = useState("");
|
const [url, setUrl] = useState("");
|
||||||
|
|
||||||
const getUrl = useCallback(() => {
|
const getUrl = () => `/torrents/search/${type}/${encodeURI(search)}`;
|
||||||
return `/torrents/search/${type}/${encodeURI(search)}`;
|
|
||||||
}, [type, search]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (search === "") {
|
if (search === "") {
|
||||||
@ -40,9 +31,9 @@ const TorrentSearch = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const url = getUrl();
|
const url = getUrl();
|
||||||
searchTorrents(url);
|
props.searchTorrents(url);
|
||||||
history.push(url);
|
props.history.push(url);
|
||||||
}, [url, getUrl, searchTorrents, history, search, type]);
|
}, [url]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
@ -77,9 +68,9 @@ const TorrentSearch = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<TorrentList
|
<TorrentList
|
||||||
searching={searching}
|
searching={props.searching}
|
||||||
results={results}
|
results={props.results}
|
||||||
addTorrent={addTorrent}
|
addTorrent={props.addTorrent}
|
||||||
searchFromURL={search}
|
searchFromURL={search}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useEffect, useState, useCallback } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import PropTypes from "prop-types";
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { setFetchedTorrents } from "../actions/torrents";
|
import { setFetchedTorrents } from "../actions/torrents";
|
||||||
import { newMovieEvent } from "../actions/movies";
|
import { newMovieEvent } from "../actions/movies";
|
||||||
@ -14,28 +13,47 @@ const mapDispatchToProps = {
|
|||||||
newEpisodeEvent
|
newEpisodeEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
const WsHandler = ({
|
const WsHandler = props => {
|
||||||
isLogged,
|
|
||||||
setFetchedTorrents,
|
|
||||||
newMovieEvent,
|
|
||||||
newEpisodeEvent
|
|
||||||
}) => {
|
|
||||||
const [ws, setWs] = useState(null);
|
const [ws, setWs] = useState(null);
|
||||||
|
|
||||||
const stop = useCallback(() => {
|
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) {
|
if (!ws) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ws.close();
|
ws.close();
|
||||||
setWs(null);
|
setWs(null);
|
||||||
}, [ws]);
|
};
|
||||||
|
|
||||||
const connect = useCallback(() => {
|
const connect = () => {
|
||||||
if (ws) {
|
if (ws) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isLogged) {
|
if (!props.isLogged) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,13 +91,13 @@ const WsHandler = ({
|
|||||||
|
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "torrents":
|
case "torrents":
|
||||||
setFetchedTorrents(data.message);
|
props.setFetchedTorrents(data.message);
|
||||||
break;
|
break;
|
||||||
case "newVideo":
|
case "newVideo":
|
||||||
if (data.message.type === "movie") {
|
if (data.message.type === "movie") {
|
||||||
newMovieEvent(data.message.data);
|
props.newMovieEvent(data.message.data);
|
||||||
} else if (data.message.type === "episode") {
|
} else if (data.message.type === "episode") {
|
||||||
newEpisodeEvent(data.message.data);
|
props.newEpisodeEvent(data.message.data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -90,39 +108,9 @@ const WsHandler = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
setWs(socket);
|
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;
|
return null;
|
||||||
};
|
};
|
||||||
WsHandler.propTypes = {
|
|
||||||
isLogged: PropTypes.bool.isRequired,
|
|
||||||
setFetchedTorrents: PropTypes.func,
|
|
||||||
newMovieEvent: PropTypes.func,
|
|
||||||
newEpisodeEvent: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(WsHandler);
|
export default connect(mapStateToProps, mapDispatchToProps)(WsHandler);
|
||||||
|
@ -104,8 +104,11 @@ const config = {
|
|||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".js"]
|
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;
|
module.exports = config;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user