temporary disabled donation button behind the header. All torrents are rendered with card style. Created GRID wrapper for holding all torrent cards. Empty posters will be rendered as NoImageIcon svg

This commit is contained in:
Daniel Shleifman
2021-05-24 17:04:20 +03:00
parent fcf4faff4a
commit af1534787e
11 changed files with 484 additions and 166 deletions

View File

@@ -0,0 +1,189 @@
import { useEffect, useRef, useState } from 'react'
import Button from '@material-ui/core/Button'
import 'fontsource-roboto'
import HeightIcon from '@material-ui/icons/Height';
import CloseIcon from '@material-ui/icons/Close';
import DeleteIcon from '@material-ui/icons/Delete'
import DialogActions from '@material-ui/core/DialogActions'
import Dialog from '@material-ui/core/Dialog'
import { getPeerString, humanizeSize } from '../../utils/Utils'
import DialogTorrentInfo from '../DialogTorrentInfo'
import { torrentsHost } from '../../utils/Hosts'
import DialogCacheInfo from '../DialogCacheInfo'
import DataUsageIcon from '@material-ui/icons/DataUsage'
import { NoImageIcon } from '../../icons';
import { StyledButton, TorrentCard, TorrentCardButtons, TorrentCardDescription, TorrentCardDescriptionContent, TorrentCardDescriptionLabel, TorrentCardPoster } from './style';
export default function Torrent(props) {
const [open, setOpen] = useState(false)
const [showCache, setShowCache] = useState(false)
const [torrent, setTorrent] = useState(props.torrent)
const timerID = useRef(-1)
useEffect(() => {
setTorrent(props.torrent)
}, [props.torrent])
useEffect(() => {
if (open)
timerID.current = setInterval(() => {
getTorrent(torrent.hash, (torr, error) => {
if (error) console.error(error)
else if (torr) setTorrent(torr)
})
}, 1000)
else clearInterval(timerID.current)
return () => {
clearInterval(timerID.current)
}
}, [torrent.hash, open])
const { title, name, poster, torrent_size, download_speed } = torrent
return (
<>
<TorrentCard>
<TorrentCardPoster isPoster={poster}>
{poster
? <img src={poster} alt="poster" />
: <NoImageIcon />}
</TorrentCardPoster>
<TorrentCardButtons>
<StyledButton
onClick={() => {
setShowCache(true)
setOpen(true)
}}
>
<DataUsageIcon />
Cache
</StyledButton>
<StyledButton
onClick={() => dropTorrent(torrent)}
>
<CloseIcon />
Drop
</StyledButton>
<StyledButton
onClick={() => deleteTorrent(torrent)}
>
<DeleteIcon />
Delete
</StyledButton>
<StyledButton
onClick={() => {
setShowCache(false)
setOpen(true)
}}
>
<HeightIcon />
Details
</StyledButton>
</TorrentCardButtons>
<TorrentCardDescription>
<TorrentCardDescriptionLabel>Name</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{title || name}</TorrentCardDescriptionContent>
<TorrentCardDescriptionLabel>Size</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{torrent_size > 0 && humanizeSize(torrent_size)}</TorrentCardDescriptionContent>
<TorrentCardDescriptionLabel>Download speed</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{download_speed > 0 ? humanizeSize(download_speed) : '---'}</TorrentCardDescriptionContent>
<TorrentCardDescriptionLabel>Peers</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{getPeerString(torrent) || '---'}</TorrentCardDescriptionContent>
</TorrentCardDescription>
</TorrentCard>
<Dialog
open={open}
onClose={() => setOpen(false)}
aria-labelledby="form-dialog-title"
fullWidth
maxWidth={'lg'}
>
{!showCache ? <DialogTorrentInfo torrent={(open, torrent)} /> : <DialogCacheInfo hash={(open, torrent.hash)} />}
<DialogActions>
<Button
variant="outlined"
color="primary"
onClick={() => setOpen(false)}
>
OK
</Button>
</DialogActions>
</Dialog>
</>
)
}
function getTorrent(hash, callback) {
try {
fetch(torrentsHost(), {
method: 'post',
body: JSON.stringify({ action: 'get', hash: hash }),
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then(
(json) => {
callback(json, null)
},
(error) => {
callback(null, error)
}
)
} catch (e) {
console.error(e)
}
}
function deleteTorrent(torrent) {
try {
fetch(torrentsHost(), {
method: 'post',
body: JSON.stringify({
action: 'rem',
hash: torrent.hash,
}),
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
})
} catch (e) {
console.error(e)
}
}
function dropTorrent(torrent) {
try {
fetch(torrentsHost(), {
method: 'post',
body: JSON.stringify({
action: 'drop',
hash: torrent.hash,
}),
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
})
} catch (e) {
console.error(e)
}
}

View File

@@ -0,0 +1,98 @@
import styled, { css } from 'styled-components';
export const TorrentCard = styled.div`
border: 1px solid;
border-radius: 5px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: 175px minmax(min-content, 1fr);
grid-template-areas:
"poster buttons"
"description description";
gap: 10px;
padding: 10px;
background: #3fb57a;
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%);
`
export const TorrentCardPoster = styled.div`
grid-area: poster;
border-radius: 5px;
overflow: hidden;
text-align: center;
${({ isPoster }) => isPoster ? css`
img {
height: 100%;
border-radius: 5px;
}
`: css`
display: grid;
place-items: center;
background: #74c39c;
border: 1px solid;
svg {
transform: translateY(-3px);
}
`};
`
export const TorrentCardButtons = styled.div`
grid-area: buttons;
display: grid;
gap: 5px;
`
export const TorrentCardDescription = styled.div`
grid-area: description;
background: #74c39c;
border-radius: 5px;
padding: 5px;
`
export const TorrentCardDescriptionLabel = styled.div`
text-transform: uppercase;
font-size: 10px;
font-weight: 500;
letter-spacing: 0.4px;
color: #216e47;
`
export const TorrentCardDescriptionContent = styled.div`
margin-left: 5px;
margin-bottom: 10px;
`
export const StyledButton = styled.button`
border-radius: 5px;
border: none;
cursor: pointer;
transition: 0.2s;
display: flex;
align-items: center;
text-transform: uppercase;
background: #216e47;
color: #fff;
font-size: 1rem;
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
letter-spacing: 0.009em;
> :first-child {
margin-right: 10px;
}
@media (max-width: 600px) {
font-size: 0.7rem;
> :first-child {
margin-right: 15px;
}
}
:hover {
background: #2a7e54;
}
`