This commit is contained in:
Daniel Shleifman
2021-06-09 12:48:43 +03:00
parent d6b10d79d8
commit c144ef960d
6 changed files with 306 additions and 272 deletions

View File

@@ -5,7 +5,6 @@ import Dialog from '@material-ui/core/Dialog'
import { torrentsHost, torrentUploadHost } from 'utils/Hosts'
import axios from 'axios'
import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'
import { NoImageIcon, AddItemIcon, TorrentIcon } from 'icons'
import debounce from 'lodash/debounce'
import { v4 as uuidv4 } from 'uuid'
@@ -14,260 +13,25 @@ import { Cancel as CancelIcon } from '@material-ui/icons'
import { useDropzone } from 'react-dropzone'
import { useMediaQuery } from '@material-ui/core'
const Header = styled.div`
background: #00a572;
color: rgba(0, 0, 0, 0.87);
font-size: 20px;
color: #fff;
font-weight: 500;
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
padding: 15px 24px;
position: relative;
`
const Content = styled.div`
background: linear-gradient(145deg, #e4f6ed, #b5dec9);
flex: 1;
display: grid;
grid-template-columns: repeat(2, 1fr);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
overflow: auto;
@media (max-width: 930px) {
grid-template-columns: 1fr;
}
`
const LeftSide = styled.div`
padding: 0 20px 20px 20px;
border-right: 1px solid rgba(0, 0, 0, 0.12);
`
const RightSide = styled.div`
display: flex;
flex-direction: column;
`
const RightSideBottomSectionBasicStyles = css`
transition: transform 0.3s;
padding: 20px;
height: 100%;
display: grid;
`
const RightSideBottomSectionNoFile = styled.div`
${RightSideBottomSectionBasicStyles}
border: 4px dashed transparent;
${({ isDragActive }) => isDragActive && `border: 4px dashed green`};
justify-items: center;
grid-template-rows: 100px 1fr;
cursor: pointer;
:hover {
background-color: rgba(0, 0, 0, 0.04);
svg {
transform: translateY(-4%);
}
}
@media (max-width: 930px) {
height: 400px;
place-items: center;
grid-template-rows: 40% 1fr;
}
`
const RightSideBottomSectionFileSelected = styled.div`
${RightSideBottomSectionBasicStyles}
place-items: center;
@media (max-width: 930px) {
height: 400px;
}
`
const TorrentIconWrapper = styled.div`
position: relative;
`
const CancelIconWrapper = styled.div`
position: absolute;
top: -9px;
left: 10px;
cursor: pointer;
> svg {
transition: all 0.3s;
fill: rgba(0, 0, 0, 0.7);
:hover {
fill: rgba(0, 0, 0, 0.6);
}
}
`
const IconWrapper = styled.div`
display: grid;
justify-items: center;
align-content: start;
gap: 10px;
align-self: start;
svg {
transition: all 0.3s;
}
`
const RightSideTopSection = styled.div`
background: #e3f2eb;
padding: 0 20px 20px 20px;
transition: all 0.3s;
${({ active }) => active && 'box-shadow: 0 8px 10px -9px rgba(0, 0, 0, 0.5)'};
`
const PosterWrapper = styled.div`
margin-top: 20px;
display: grid;
grid-template-columns: max-content 1fr;
grid-template-rows: 300px max-content;
column-gap: 5px;
position: relative;
margin-bottom: 20px;
grid-template-areas:
'poster suggestions'
'clear empty';
@media (max-width: 540px) {
grid-template-columns: 1fr;
gap: 5px 0;
justify-items: center;
grid-template-areas:
'poster'
'clear'
'suggestions';
}
`
const PosterSuggestions = styled.div`
display: grid;
grid-area: suggestions;
grid-template-columns: repeat(3, max-content);
grid-template-rows: repeat(4, max-content);
gap: 5px;
@media (max-width: 540px) {
grid-template-columns: repeat(5, max-content);
}
@media (max-width: 375px) {
grid-template-columns: repeat(4, max-content);
}
`
const PosterSuggestionsItem = styled.div`
cursor: pointer;
width: 71px;
height: 71px;
@media (max-width: 430px) {
width: 60px;
height: 60px;
}
@media (max-width: 375px) {
width: 71px;
height: 71px;
}
@media (max-width: 355px) {
width: 60px;
height: 60px;
}
img {
transition: all 0.3s;
border-radius: 5px;
width: 100%;
height: 100%;
object-fit: cover;
:hover {
filter: brightness(130%);
}
}
`
export const Poster = styled.div`
${({ poster }) => css`
border-radius: 5px;
overflow: hidden;
width: 200px;
grid-area: poster;
${poster
? css`
img {
width: 200px;
object-fit: cover;
border-radius: 5px;
height: 100%;
}
`
: css`
display: grid;
place-items: center;
background: #74c39c;
svg {
transform: scale(1.5) translateY(-3px);
}
`}
`}
`
const ClearPosterButton = styled(Button)`
grid-area: clear;
justify-self: center;
transform: translateY(-50%);
position: absolute;
${({ showbutton }) => !showbutton && 'display: none'};
@media (max-width: 540px) {
transform: translateY(-140%);
}
`
const ButtonWrapper = styled.div`
padding: 20px;
display: flex;
justify-content: flex-end;
> :not(:last-child) {
margin-right: 10px;
}
`
const getMoviePosters = (movieName, language = 'en') => {
const request = `${`http://api.themoviedb.org/3/search/multi?api_key=${process.env.REACT_APP_TMDB_API_KEY}`}&language=${language}&include_image_language=${language},null&query=${movieName}`
return axios
.get(request)
.then(({ data: { results } }) =>
results.filter(el => el.poster_path).map(el => `https://image.tmdb.org/t/p/w300${el.poster_path}`),
)
.catch(() => null)
}
const checkImageURL = async url => {
if (!url || !url.match(/.(jpg|jpeg|png|gif)$/i)) return false
try {
await fetch(url)
return true
} catch (e) {
return false
}
}
import {
ButtonWrapper,
CancelIconWrapper,
ClearPosterButton,
Content,
Header,
IconWrapper,
LeftSide,
Poster,
PosterSuggestions,
PosterSuggestionsItem,
PosterWrapper,
RightSide,
RightSideBottomSectionFileSelected,
RightSideBottomSectionNoFile,
RightSideTopSection,
TorrentIconWrapper,
} from './style'
import { checkImageURL, getMoviePosters } from './helpers'
export default function AddDialog({ handleClose }) {
const { t } = useTranslation()
@@ -338,16 +102,18 @@ export default function AddDialog({ handleClose }) {
const handleSave = () => {
if (selectedFile) {
// file save
const data = new FormData()
data.append('save', 'true')
data.append('file', selectedFile)
title && data.append('title', title)
posterUrl && data.append('poster', posterUrl)
axios.post(torrentUploadHost(), data).finally(() => handleClose())
axios.post(torrentUploadHost(), data).finally(handleClose)
} else {
// link save
axios
.post(torrentsHost(), { action: 'add', link: torrentSource, title, poster: posterUrl, save_to_db: true })
.finally(() => handleClose())
.finally(handleClose)
}
}
@@ -396,6 +162,7 @@ export default function AddDialog({ handleClose }) {
<Poster poster={+isPosterUrlCorrect}>
{isPosterUrlCorrect ? <img src={posterUrl} alt='poster' /> : <NoImageIcon />}
</Poster>
<PosterSuggestions>
{posterList
?.filter(url => url !== posterUrl)

View File

@@ -0,0 +1,23 @@
import axios from 'axios'
export const getMoviePosters = (movieName, language = 'en') => {
const request = `${`http://api.themoviedb.org/3/search/multi?api_key=${process.env.REACT_APP_TMDB_API_KEY}`}&language=${language}&include_image_language=${language},null&query=${movieName}`
return axios
.get(request)
.then(({ data: { results } }) =>
results.filter(el => el.poster_path).map(el => `https://image.tmdb.org/t/p/w300${el.poster_path}`),
)
.catch(() => null)
}
export const checkImageURL = async url => {
if (!url || !url.match(/.(jpg|jpeg|png|gif)$/i)) return false
try {
await fetch(url)
return true
} catch (e) {
return false
}
}

View File

@@ -0,0 +1,236 @@
import { Button } from '@material-ui/core'
import styled, { css } from 'styled-components'
export const Header = styled.div`
background: #00a572;
color: rgba(0, 0, 0, 0.87);
font-size: 20px;
color: #fff;
font-weight: 500;
box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
padding: 15px 24px;
position: relative;
`
export const Content = styled.div`
background: linear-gradient(145deg, #e4f6ed, #b5dec9);
flex: 1;
display: grid;
grid-template-columns: repeat(2, 1fr);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
overflow: auto;
@media (max-width: 930px) {
grid-template-columns: 1fr;
}
`
export const LeftSide = styled.div`
padding: 0 20px 20px 20px;
border-right: 1px solid rgba(0, 0, 0, 0.12);
`
export const RightSide = styled.div`
display: flex;
flex-direction: column;
`
export const RightSideBottomSectionBasicStyles = css`
transition: transform 0.3s;
padding: 20px;
height: 100%;
display: grid;
`
export const RightSideBottomSectionNoFile = styled.div`
${RightSideBottomSectionBasicStyles}
border: 4px dashed transparent;
text-align: center;
${({ isDragActive }) => isDragActive && `border: 4px dashed green`};
justify-items: center;
grid-template-rows: 100px 1fr;
cursor: pointer;
:hover {
background-color: rgba(0, 0, 0, 0.04);
svg {
transform: translateY(-4%);
}
}
@media (max-width: 930px) {
height: 400px;
place-items: center;
grid-template-rows: 40% 1fr;
}
`
export const RightSideBottomSectionFileSelected = styled.div`
${RightSideBottomSectionBasicStyles}
place-items: center;
@media (max-width: 930px) {
height: 400px;
}
`
export const TorrentIconWrapper = styled.div`
position: relative;
`
export const CancelIconWrapper = styled.div`
position: absolute;
top: -9px;
left: 10px;
cursor: pointer;
> svg {
transition: all 0.3s;
fill: rgba(0, 0, 0, 0.7);
:hover {
fill: rgba(0, 0, 0, 0.6);
}
}
`
export const IconWrapper = styled.div`
display: grid;
justify-items: center;
align-content: start;
gap: 10px;
align-self: start;
svg {
transition: all 0.3s;
}
`
export const RightSideTopSection = styled.div`
background: #e3f2eb;
padding: 0 20px 20px 20px;
transition: all 0.3s;
${({ active }) => active && 'box-shadow: 0 8px 10px -9px rgba(0, 0, 0, 0.5)'};
`
export const PosterWrapper = styled.div`
margin-top: 20px;
display: grid;
grid-template-columns: max-content 1fr;
grid-template-rows: 300px max-content;
column-gap: 5px;
position: relative;
margin-bottom: 20px;
grid-template-areas:
'poster suggestions'
'clear empty';
@media (max-width: 540px) {
grid-template-columns: 1fr;
gap: 5px 0;
justify-items: center;
grid-template-areas:
'poster'
'clear'
'suggestions';
}
`
export const PosterSuggestions = styled.div`
display: grid;
grid-area: suggestions;
grid-template-columns: repeat(3, max-content);
grid-template-rows: repeat(4, max-content);
gap: 5px;
@media (max-width: 540px) {
grid-template-columns: repeat(5, max-content);
}
@media (max-width: 375px) {
grid-template-columns: repeat(4, max-content);
}
`
export const PosterSuggestionsItem = styled.div`
cursor: pointer;
width: 71px;
height: 71px;
@media (max-width: 430px) {
width: 60px;
height: 60px;
}
@media (max-width: 375px) {
width: 71px;
height: 71px;
}
@media (max-width: 355px) {
width: 60px;
height: 60px;
}
img {
transition: all 0.3s;
border-radius: 5px;
width: 100%;
height: 100%;
object-fit: cover;
:hover {
filter: brightness(130%);
}
}
`
export const Poster = styled.div`
${({ poster }) => css`
border-radius: 5px;
overflow: hidden;
width: 200px;
grid-area: poster;
${poster
? css`
img {
width: 200px;
object-fit: cover;
border-radius: 5px;
height: 100%;
}
`
: css`
display: grid;
place-items: center;
background: #74c39c;
svg {
transform: scale(1.5) translateY(-3px);
}
`}
`}
`
export const ClearPosterButton = styled(Button)`
grid-area: clear;
justify-self: center;
transform: translateY(-50%);
position: absolute;
${({ showbutton }) => !showbutton && 'display: none'};
@media (max-width: 540px) {
transform: translateY(-140%);
}
`
export const ButtonWrapper = styled.div`
padding: 20px;
display: flex;
justify-content: flex-end;
> :not(:last-child) {
margin-right: 10px;
}
`

View File

@@ -11,14 +11,14 @@ import {
DownlodSpeedWidget,
} from '../widgets'
export default function Test({
export default function DetailedView({
downloadSpeed,
uploadSpeed,
torrent,
torrentSize,
PiecesCount,
PiecesLength,
statString,
stat,
cache,
}) {
return (
@@ -32,7 +32,7 @@ export default function Test({
<SizeWidget data={torrentSize} />
<PiecesCountWidget data={PiecesCount} />
<PiecesLengthWidget data={PiecesLength} />
<StatusWidget data={statString} />
<StatusWidget stat={stat} />
</WidgetWrapper>
</DetailedViewWidgetSection>

View File

@@ -54,7 +54,6 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
stat,
download_speed: downloadSpeed,
upload_speed: uploadSpeed,
stat_string: statString,
torrent_size: torrentSize,
file_stats: torrentFileList,
} = torrent
@@ -133,7 +132,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
torrentSize={torrentSize}
PiecesCount={PiecesCount}
PiecesLength={PiecesLength}
statString={statString}
stat={stat}
cache={cache}
/>
) : (
@@ -156,7 +155,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
<UploadSpeedWidget data={uploadSpeed} />
<PeersWidget data={torrent} />
<SizeWidget data={torrentSize} />
<StatusWidget data={statString} />
<StatusWidget stat={stat} />
</WidgetWrapper>
<Divider />

View File

@@ -9,6 +9,7 @@ import {
} from '@material-ui/icons'
import { getPeerString, humanizeSize } from 'utils/Utils'
import { useTranslation } from 'react-i18next'
import { GETTING_INFO, IN_DB, CLOSED, PRELOAD, WORKING } from 'torrentStates'
import StatisticsField from './StatisticsField'
@@ -69,17 +70,25 @@ export const PiecesLengthWidget = ({ data }) => {
)
}
export const StatusWidget = ({ data }) => {
export const StatusWidget = ({ stat }) => {
const { t } = useTranslation()
let i18nd = data
if (data.toLowerCase() === 'torrent added') i18nd = t('TorrentAdded')
else if (data.toLowerCase() === 'torrent getting info') i18nd = t('TorrentGettingInfo')
else if (data.toLowerCase() === 'torrent preload') i18nd = t('TorrentPreload')
else if (data.toLowerCase() === 'torrent working') i18nd = t('TorrentWorking')
else if (data.toLowerCase() === 'torrent closed') i18nd = t('TorrentClosed')
else if (data.toLowerCase() === 'torrent in db') i18nd = t('TorrentInDb')
const values = {
[GETTING_INFO]: t('TorrentGettingInfo'),
[PRELOAD]: t('TorrentPreload'),
[WORKING]: t('TorrentWorking'),
[CLOSED]: t('TorrentClosed'),
[IN_DB]: t('TorrentInDb'),
}
return (
<StatisticsField title={t('TorrentStatus')} value={i18nd} iconBg='#aea25b' valueBg='#b4aa6e' icon={BuildIcon} />
<StatisticsField
title={t('TorrentStatus')}
value={values[stat]}
iconBg='#aea25b'
valueBg='#b4aa6e'
icon={BuildIcon}
/>
)
}