This commit is contained in:
Daniel Shleifman
2021-05-31 15:21:56 +03:00
parent 695a7c53b6
commit aab85cc366
13 changed files with 191 additions and 260 deletions

View File

@@ -36,6 +36,7 @@
"react/prop-types": 0,
"react/react-in-jsx-scope": 0,
"react/jsx-uses-react": 0,
"import/no-unresolved": 0 // used to allow relative paths from "src" folder
"import/no-unresolved": 0, // used to allow relative paths from "src" folder
"react/jsx-props-no-spreading": 0
}
}

View File

@@ -63,7 +63,7 @@ export default function AddDialog({ handleClose }) {
Cancel
</Button>
<Button disabled={!magnet} onClick={handleCloseSave} color='primary' variant='outlined'>
<Button variant='contained' disabled={!magnet} onClick={handleCloseSave} color='primary'>
Add
</Button>
</DialogActions>

View File

@@ -34,7 +34,6 @@ export default function SingleBlock({
width={boxHeight}
fillAfterStrokeEnabled
preventDefault={false}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(isComplete
? { fill: processCompletedColor }
: inProgress && {

View File

@@ -34,7 +34,6 @@ export default function SingleBlock({
width={boxHeight}
fillAfterStrokeEnabled
preventDefault={false}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(isComplete
? { fill: processCompletedColor }
: inProgress && {

View File

@@ -28,9 +28,7 @@ export const useUpdateCache = hash => {
}, 100)
} else clearInterval(timerID.current)
return () => {
clearInterval(timerID.current)
}
return () => clearInterval(timerID.current)
}, [hash])
return cache

View File

@@ -2,14 +2,13 @@ import { NoImageIcon } from 'icons'
import { getPeerString, humanizeSize } from 'utils/Utils'
import { CopyToClipboard } from 'react-copy-to-clipboard'
import { useEffect, useState } from 'react'
import { Button, ButtonGroup, Typography } from '@material-ui/core'
import { Button } from '@material-ui/core'
import ptt from 'parse-torrent-title'
import {
ArrowDownward as ArrowDownwardIcon,
ArrowUpward as ArrowUpwardIcon,
SwapVerticalCircle as SwapVerticalCircleIcon,
ViewAgenda as ViewAgendaIcon,
Cached as CachedIcon,
} from '@material-ui/icons'
import axios from 'axios'
import { streamHost, torrentsHost, viewedHost } from 'utils/Hosts'
@@ -109,7 +108,6 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
<DialogHeader
onClose={closeDialog}
title={isDetailedCacheView ? 'Detailed Cache View' : 'Torrent Details'}
// eslint-disable-next-line react/jsx-props-no-spreading
{...(isDetailedCacheView && { onBack: () => setIsDetailedCacheView(false) })}
/>

View File

@@ -204,10 +204,6 @@ export const Table = styled.table`
tbody tr {
border-bottom: 1px solid #ddd;
/* :nth-of-type(even) {
background: #f3f3f3;
} */
:last-of-type {
border-bottom: 2px solid #009879;
}

View File

@@ -126,7 +126,7 @@ export default function DialogTorrentInfo({ torrent, open }) {
fetch(`${streamHost()}?link=${torrentLocalComponentValue.hash}&index=${file.id}&preload`)
}
>
<CachedIcon />
{/* <CachedIcon /> */}
<Typography>Preload</Typography>
</Button>
</ButtonGroup>

View File

@@ -1,7 +1,9 @@
import { Button, Dialog, DialogActions, DialogTitle } from '@material-ui/core'
import ListItem from '@material-ui/core/ListItem'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import DeleteIcon from '@material-ui/icons/Delete'
import { useState } from 'react'
import { torrentsHost } from 'utils/Hosts'
const fnRemoveAll = () => {
@@ -29,13 +31,40 @@ const fnRemoveAll = () => {
}
export default function RemoveAll() {
return (
<ListItem button key='Remove all' onClick={fnRemoveAll}>
<ListItemIcon>
<DeleteIcon />
</ListItemIcon>
const [open, setOpen] = useState(false)
const closeDialog = () => setOpen(false)
const openDialog = () => setOpen(true)
<ListItemText primary='Remove all' />
</ListItem>
return (
<>
<ListItem button key='Remove all' onClick={openDialog}>
<ListItemIcon>
<DeleteIcon />
</ListItemIcon>
<ListItemText primary='Remove all' />
</ListItem>
<Dialog open={open} onClose={closeDialog}>
<DialogTitle>Delete Torrent?</DialogTitle>
<DialogActions>
<Button variant='outlined' onClick={closeDialog} color='primary'>
Cancel
</Button>
<Button
variant='contained'
onClick={() => {
fnRemoveAll()
closeDialog()
}}
color='primary'
autoFocus
>
Ok
</Button>
</DialogActions>
</Dialog>
</>
)
}

View File

@@ -1,208 +0,0 @@
/* eslint-disable camelcase */
import 'fontsource-roboto'
import { forwardRef, useEffect, useRef, useState } from 'react'
import DialogActions from '@material-ui/core/DialogActions'
import DialogTorrentInfo from 'components/DialogTorrentInfo'
import DialogCacheInfo from 'components/DialogCacheInfo'
import HeightIcon from '@material-ui/icons/Height'
import CloseIcon from '@material-ui/icons/Close'
import DeleteIcon from '@material-ui/icons/Delete'
import DataUsageIcon from '@material-ui/icons/DataUsage'
import { getPeerString, humanizeSize } from 'utils/Utils'
import { torrentsHost } from 'utils/Hosts'
import { NoImageIcon } from 'icons'
import DialogTorrentDetailsContent from 'components/DialogTorrentDetailsContent'
import Dialog from '@material-ui/core/Dialog'
import Slide from '@material-ui/core/Slide'
import { Button } from '@material-ui/core'
import {
StyledButton,
TorrentCard,
TorrentCardButtons,
TorrentCardDescription,
TorrentCardDescriptionContent,
TorrentCardDescriptionLabel,
TorrentCardPoster,
TorrentCardDetails,
} from './style'
// eslint-disable-next-line react/jsx-props-no-spreading
const Transition = forwardRef((props, ref) => <Slide direction='up' ref={ref} {...props} />)
export default function Torrent({ torrent }) {
const [open, setOpen] = useState(false)
const [showCache, setShowCache] = useState(false)
const [torrentLocalComponentValue, setTorrentLocalComponentValue] = useState(torrent)
const timerID = useRef(-1)
useEffect(() => {
setTorrentLocalComponentValue(torrent)
}, [torrent])
useEffect(() => {
if (open)
timerID.current = setInterval(() => {
getTorrent(torrentLocalComponentValue.hash, (torr, error) => {
if (error) console.error(error)
else if (torr) setTorrentLocalComponentValue(torr)
})
}, 1000)
else clearInterval(timerID.current)
return () => {
clearInterval(timerID.current)
}
}, [torrentLocalComponentValue.hash, open])
const { title, name, poster, torrent_size, download_speed } = torrentLocalComponentValue
return (
<>
<TorrentCard>
<TorrentCardPoster isPoster={poster}>
{poster ? <img src={poster} alt='poster' /> : <NoImageIcon />}
</TorrentCardPoster>
<TorrentCardButtons>
<StyledButton
onClick={() => {
setShowCache(true)
setOpen(true)
}}
>
<DataUsageIcon />
<span>Cache</span>
</StyledButton>
<StyledButton onClick={() => dropTorrent(torrentLocalComponentValue)}>
<CloseIcon />
<span>Drop</span>
</StyledButton>
<StyledButton
onClick={() => {
setShowCache(false)
setOpen(true)
}}
>
<HeightIcon />
<span>Details</span>
</StyledButton>
<StyledButton onClick={() => deleteTorrent(torrentLocalComponentValue)}>
<DeleteIcon />
<span>Delete</span>
</StyledButton>
</TorrentCardButtons>
<TorrentCardDescription>
<span>
<TorrentCardDescriptionLabel>Name</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent isTitle>{title || name}</TorrentCardDescriptionContent>
</span>
<TorrentCardDetails>
<span>
<TorrentCardDescriptionLabel>Size</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{torrent_size > 0 && humanizeSize(torrent_size)}
</TorrentCardDescriptionContent>
</span>
<span>
<TorrentCardDescriptionLabel>Speed</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{download_speed > 0 ? humanizeSize(download_speed) : '---'}
</TorrentCardDescriptionContent>
</span>
<span>
<TorrentCardDescriptionLabel>Peers</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{getPeerString(torrentLocalComponentValue) || '---'}
</TorrentCardDescriptionContent>
</span>
</TorrentCardDetails>
</TorrentCardDescription>
</TorrentCard>
<Dialog open={open} fullScreen TransitionComponent={Transition}>
<DialogTorrentDetailsContent closeDialog={() => setOpen(false)} torrent={torrentLocalComponentValue} />
</Dialog>
{/* <Dialog open={open} fullScreen>
{showCache ? (
<DialogCacheInfo hash={torrentLocalComponentValue.hash} />
) : (
<DialogTorrentInfo torrent={torrentLocalComponentValue} />
)}
<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 }),
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,132 @@
/* eslint-disable camelcase */
import 'fontsource-roboto'
import { forwardRef, useState } from 'react'
import HeightIcon from '@material-ui/icons/Height'
import CloseIcon from '@material-ui/icons/Close'
import DeleteIcon from '@material-ui/icons/Delete'
import { getPeerString, humanizeSize } from 'utils/Utils'
import { torrentsHost } from 'utils/Hosts'
import { NoImageIcon } from 'icons'
import DialogTorrentDetailsContent from 'components/DialogTorrentDetailsContent'
import Dialog from '@material-ui/core/Dialog'
import Slide from '@material-ui/core/Slide'
import { Button, DialogActions, DialogTitle, useMediaQuery, useTheme } from '@material-ui/core'
import axios from 'axios'
import {
StyledButton,
TorrentCard,
TorrentCardButtons,
TorrentCardDescription,
TorrentCardDescriptionContent,
TorrentCardDescriptionLabel,
TorrentCardPoster,
TorrentCardDetails,
} from './style'
const Transition = forwardRef((props, ref) => <Slide direction='up' ref={ref} {...props} />)
export default function Torrent({ torrent }) {
const [isDetailedInfoOpened, setIsDetailedInfoOpened] = useState(false)
const [isDeleteTorrentOpened, setIsDeleteTorrentOpened] = useState(false)
const theme = useTheme()
const fullScreen = useMediaQuery(theme.breakpoints.down('md'))
const openDetailedInfo = () => setIsDetailedInfoOpened(true)
const closeDetailedInfo = () => setIsDetailedInfoOpened(false)
const openDeleteTorrentAlert = () => setIsDeleteTorrentOpened(true)
const closeDeleteTorrentAlert = () => setIsDeleteTorrentOpened(false)
const { title, name, poster, torrent_size, download_speed, hash } = torrent
const dropTorrent = () => axios.post(torrentsHost(), { action: 'drop', hash })
const deleteTorrent = () => axios.post(torrentsHost(), { action: 'rem', hash })
return (
<>
<TorrentCard>
<TorrentCardPoster isPoster={poster}>
{poster ? <img src={poster} alt='poster' /> : <NoImageIcon />}
</TorrentCardPoster>
<TorrentCardButtons>
<StyledButton onClick={openDetailedInfo}>
<HeightIcon />
<span>Details</span>
</StyledButton>
<StyledButton onClick={() => dropTorrent(torrent)}>
<CloseIcon />
<span>Drop</span>
</StyledButton>
<StyledButton onClick={openDeleteTorrentAlert}>
<DeleteIcon />
<span>Delete</span>
</StyledButton>
</TorrentCardButtons>
<TorrentCardDescription>
<span>
<TorrentCardDescriptionLabel>Name</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent isTitle>{title || name}</TorrentCardDescriptionContent>
</span>
<TorrentCardDetails>
<span>
<TorrentCardDescriptionLabel>Size</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{torrent_size > 0 && humanizeSize(torrent_size)}
</TorrentCardDescriptionContent>
</span>
<span>
<TorrentCardDescriptionLabel>Speed</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{download_speed > 0 ? humanizeSize(download_speed) : '---'}
</TorrentCardDescriptionContent>
</span>
<span>
<TorrentCardDescriptionLabel>Peers</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{getPeerString(torrent) || '---'}</TorrentCardDescriptionContent>
</span>
</TorrentCardDetails>
</TorrentCardDescription>
</TorrentCard>
<Dialog
open={isDetailedInfoOpened}
onClose={closeDetailedInfo}
fullScreen={fullScreen}
fullWidth
maxWidth='xl'
TransitionComponent={Transition}
>
<DialogTorrentDetailsContent closeDialog={closeDetailedInfo} torrent={torrent} />
</Dialog>
<Dialog open={isDeleteTorrentOpened} onClose={closeDeleteTorrentAlert}>
<DialogTitle>Delete Torrent?</DialogTitle>
<DialogActions>
<Button variant='outlined' onClick={closeDeleteTorrentAlert} color='primary'>
Cancel
</Button>
<Button
variant='contained'
onClick={() => {
deleteTorrent(torrent)
closeDeleteTorrentAlert()
}}
color='primary'
autoFocus
>
Ok
</Button>
</DialogActions>
</Dialog>
</>
)
}

View File

@@ -2,7 +2,8 @@ import styled from 'styled-components'
import { useEffect, useRef, useState } from 'react'
import { Typography } from '@material-ui/core'
import { torrentsHost } from 'utils/Hosts'
import Torrent from 'components/Torrent'
import TorrentCard from 'components/TorrentCard'
import axios from 'axios'
const TorrentListWrapper = styled.div`
display: grid;
@@ -19,43 +20,29 @@ const TorrentListWrapper = styled.div`
}
`
const getTorrentList = (callback, errorCallback) => {
fetch(torrentsHost(), {
method: 'post',
body: JSON.stringify({ action: 'list' }),
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
})
.then(res => res.json())
.then(callback)
.catch(() => errorCallback())
}
export default function TorrentList() {
const [torrents, setTorrents] = useState([])
const [offline, setOffline] = useState(true)
const timerID = useRef(-1)
const updateTorrentList = torrs => {
setTorrents(torrs)
setOffline(false)
}
const resetTorrentList = () => {
setTorrents([])
setOffline(true)
}
useEffect(() => {
timerID.current = setInterval(() => {
getTorrentList(updateTorrentList, resetTorrentList)
// getting torrent list
axios
.post(torrentsHost(), { action: 'list' })
.then(({ data }) => {
// updating torrent list
setTorrents(data)
setOffline(false)
})
.catch(() => {
// resetting torrent list
setTorrents([])
setOffline(true)
})
}, 1000)
return () => {
clearInterval(timerID.current)
}
return () => clearInterval(timerID.current)
}, [])
return (
@@ -65,7 +52,7 @@ export default function TorrentList() {
) : !torrents.length ? (
<Typography>No torrents added</Typography>
) : (
torrents && torrents.map(torrent => <Torrent key={torrent.hash} torrent={torrent} />)
torrents.map(torrent => <TorrentCard key={torrent.hash} torrent={torrent} />)
)}
</TorrentListWrapper>
)