mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-21 06:26:10 +05:00
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:
189
web/src/components/Torrent/index.js
Normal file
189
web/src/components/Torrent/index.js
Normal 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)
|
||||
}
|
||||
}
|
||||
98
web/src/components/Torrent/style.js
Normal file
98
web/src/components/Torrent/style.js
Normal 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;
|
||||
}
|
||||
`
|
||||
Reference in New Issue
Block a user