torrent cards rewritten

This commit is contained in:
Daniel Shleifman
2021-06-02 19:19:41 +03:00
parent 8696f6cd0b
commit f0a2ba8390
13 changed files with 346 additions and 361 deletions

View File

@@ -1,144 +0,0 @@
import { useEffect, useState } from 'react'
import clsx from 'clsx'
import { useTheme } from '@material-ui/core/styles'
import Drawer from '@material-ui/core/Drawer'
import AppBar from '@material-ui/core/AppBar'
import Toolbar from '@material-ui/core/Toolbar'
import List from '@material-ui/core/List'
import Typography from '@material-ui/core/Typography'
import Divider from '@material-ui/core/Divider'
import IconButton from '@material-ui/core/IconButton'
import MenuIcon from '@material-ui/icons/Menu'
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'
import ChevronRightIcon from '@material-ui/icons/ChevronRight'
import ListItem from '@material-ui/core/ListItem'
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import CreditCardIcon from '@material-ui/icons/CreditCard'
import ListIcon from '@material-ui/icons/List'
import PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew'
import { playlistAllHost, shutdownHost, getTorrServerHost } from 'utils/Hosts'
import TorrentList from 'components/TorrentList'
import AddDialogButton from 'components/Add'
import RemoveAll from 'components/RemoveAll'
import SettingsDialog from 'components/Settings'
import AboutDialog from 'components/About'
import DonateSnackbar from 'components/Donate'
import DonateDialog from 'components/Donate/DonateDialog'
import UploadDialog from 'components/Upload'
import useStyles from './useStyles'
export default function MiniDrawer() {
const classes = useStyles()
const theme = useTheme()
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
const [tsVersion, setTSVersion] = useState('')
const handleDrawerOpen = () => setIsDrawerOpen(true)
const handleDrawerClose = () => setIsDrawerOpen(false)
useEffect(() => {
fetch(`${getTorrServerHost()}/echo`)
.then(resp => resp.text())
.then(txt => {
if (!txt.startsWith('<!DOCTYPE html>')) setTSVersion(txt)
})
}, [isDrawerOpen])
return (
<div className={classes.root}>
<AppBar
position='fixed'
className={clsx(classes.appBar, {
[classes.appBarShift]: isDrawerOpen,
})}
>
<Toolbar>
<IconButton
color='inherit'
aria-label='open drawer'
onClick={handleDrawerOpen}
edge='start'
className={clsx(classes.menuButton, {
[classes.hide]: isDrawerOpen,
})}
>
<MenuIcon />
</IconButton>
<Typography variant='h6' noWrap>
TorrServer {tsVersion}
</Typography>
</Toolbar>
</AppBar>
<Drawer
variant='permanent'
className={clsx(classes.drawer, {
[classes.drawerOpen]: isDrawerOpen,
[classes.drawerClose]: !isDrawerOpen,
})}
classes={{
paper: clsx({
[classes.drawerOpen]: isDrawerOpen,
[classes.drawerClose]: !isDrawerOpen,
}),
}}
>
<div className={classes.toolbar}>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
</div>
<Divider />
<List>
<AddDialogButton />
<UploadDialog />
<RemoveAll />
<ListItem button component='a' key='Playlist all torrents' target='_blank' href={playlistAllHost()}>
<ListItemIcon>
<ListIcon />
</ListItemIcon>
<ListItemText primary='Playlist all torrents' />
</ListItem>
</List>
<Divider />
<List>
<SettingsDialog />
<AboutDialog />
<ListItem button key='Close server' onClick={() => fetch(shutdownHost())}>
<ListItemIcon>
<PowerSettingsNewIcon />
</ListItemIcon>
<ListItemText primary='Close server' />
</ListItem>
</List>
<Divider />
<List>
<ListItem button key='Donation' onClick={() => setIsDonationDialogOpen(true)}>
<ListItemIcon>
<CreditCardIcon />
</ListItemIcon>
<ListItemText primary='Donate' />
</ListItem>
</List>
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
<TorrentList />
</main>
{isDonationDialogOpen && <DonateDialog onClose={() => setIsDonationDialogOpen(false)} />}
{!JSON.parse(localStorage.getItem('snackbarIsClosed')) && <DonateSnackbar />}
</div>
)
}

View File

@@ -1,65 +0,0 @@
import { makeStyles } from '@material-ui/core/styles'
const drawerWidth = 240
export default makeStyles(theme => ({
root: {
display: 'flex',
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
appBarShift: {
marginLeft: drawerWidth,
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
menuButton: {
marginRight: 36,
},
hide: {
display: 'none',
},
drawer: {
width: drawerWidth,
flexShrink: 1,
whiteSpace: 'nowrap',
},
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
},
drawerClose: {
transition: theme.transitions.create('width', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: 'hidden',
width: theme.spacing(7) + 1,
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9) + 1,
},
},
toolbar: {
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-end',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
},
}))

View File

@@ -1,5 +1,5 @@
import { NoImageIcon } from 'icons'
import { humanizeSize } from 'utils/Utils'
import { humanizeSize, shortenText } from 'utils/Utils'
import { useEffect, useState } from 'react'
import { Button, ButtonGroup } from '@material-ui/core'
import ptt from 'parse-torrent-title'
@@ -30,8 +30,6 @@ import { DownlodSpeedWidget, UploadSpeedWidget, PeersWidget, SizeWidget } from '
import TorrentFunctions from './TorrentFunctions'
import { isFilePlayable } from './helpers'
const shortenText = (text, count) => text.slice(0, count) + (text.length > count ? '...' : '')
const Loader = () => (
<div style={{ minHeight: '80vh', display: 'grid', placeItems: 'center' }}>
<CircularProgress />

View File

@@ -1,9 +1,7 @@
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 { UnfoldMore as UnfoldMoreIcon, Close as CloseIcon, Delete as DeleteIcon } from '@material-ui/icons'
import { getPeerString, humanizeSize, shortenText } from 'utils/Utils'
import { torrentsHost } from 'utils/Hosts'
import { NoImageIcon } from 'icons'
import DialogTorrentDetailsContent from 'components/DialogTorrentDetailsContent'
@@ -12,16 +10,7 @@ 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'
import { StyledButton, TorrentCard, TorrentCardButtons, TorrentCardDescription, TorrentCardPoster } from './style'
const Transition = forwardRef((props, ref) => <Slide direction='up' ref={ref} {...props} />)
@@ -51,7 +40,7 @@ export default function Torrent({ torrent }) {
<TorrentCardButtons>
<StyledButton onClick={openDetailedInfo}>
<HeightIcon />
<UnfoldMoreIcon />
<span>Details</span>
</StyledButton>
@@ -67,31 +56,29 @@ export default function Torrent({ torrent }) {
</TorrentCardButtons>
<TorrentCardDescription>
<span>
<TorrentCardDescriptionLabel>Name</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent isTitle>{title || name}</TorrentCardDescriptionContent>
</span>
<div className='description-title-wrapper'>
<div className='description-section-name'>Name</div>
<div className='description-torrent-title'>{shortenText(title || name, 100)}</div>
</div>
<TorrentCardDetails>
<span>
<TorrentCardDescriptionLabel>Size</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
{torrentSize > 0 && humanizeSize(torrentSize)}
</TorrentCardDescriptionContent>
</span>
<div className='description-statistics-wrapper'>
<div className='description-statistics-element-wrapper'>
<div className='description-section-name'>Size</div>
<div className='description-statistics-element-value'>{torrentSize > 0 && humanizeSize(torrentSize)}</div>
</div>
<span>
<TorrentCardDescriptionLabel>Speed</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>
<div className='description-statistics-element-wrapper'>
<div className='description-section-name'>Speed</div>
<div className='description-statistics-element-value'>
{downloadSpeed > 0 ? humanizeSize(downloadSpeed) : '---'}
</TorrentCardDescriptionContent>
</span>
</div>
</div>
<span>
<TorrentCardDescriptionLabel>Peers</TorrentCardDescriptionLabel>
<TorrentCardDescriptionContent>{getPeerString(torrent) || '---'}</TorrentCardDescriptionContent>
</span>
</TorrentCardDetails>
<div className='description-statistics-element-wrapper'>
<div className='description-section-name'>Peers</div>
<div className='description-statistics-element-value'>{getPeerString(torrent) || '---'}</div>
</div>
</div>
</TorrentCardDescription>
</TorrentCard>

View File

@@ -4,22 +4,26 @@ 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';
grid-template-columns: 120px 260px 1fr;
grid-template-rows: 180px;
grid-template-areas: 'poster description buttons';
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%);
@media (max-width: 600px), (max-height: 500px) {
@media (max-width: 1260px), (max-height: 500px) {
grid-template-areas:
'poster description'
'buttons buttons';
grid-template-columns: 25% 1fr;
grid-template-rows: 100px min-content;
grid-template-columns: 70px 1fr;
grid-template-rows: 110px max-content;
}
@media (max-width: 770px) {
grid-template-columns: 60px 1fr;
grid-template-rows: 90px max-content;
}
`
@@ -33,7 +37,9 @@ export const TorrentCardPoster = styled.div`
isPoster
? css`
img {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 5px;
}
`
@@ -41,26 +47,27 @@ export const TorrentCardPoster = styled.div`
display: grid;
place-items: center;
background: #74c39c;
border: 1px solid;
border: 1px solid #337a57;
svg {
transform: translateY(-3px);
}
`};
@media (max-width: 600px), (max-height: 500px) {
@media (max-width: 1260px), (max-height: 500px) {
svg {
width: 50%;
}
}
`
export const TorrentCardButtons = styled.div`
grid-area: buttons;
display: grid;
gap: 5px;
@media (max-width: 600px), (max-height: 500px) {
grid-template-columns: repeat(4, 1fr);
@media (max-width: 1260px), (max-height: 500px) {
grid-template-columns: repeat(3, 1fr);
}
`
export const TorrentCardDescription = styled.div`
@@ -68,43 +75,101 @@ export const TorrentCardDescription = styled.div`
background: #74c39c;
border-radius: 5px;
padding: 5px;
word-break: break-word;
display: grid;
grid-template-rows: 55% 1fr;
gap: 10px;
@media (max-width: 600px), (max-height: 500px) {
@media (max-width: 770px) {
grid-template-rows: 60% 1fr;
gap: 3px;
}
@media (max-width: 770px) {
grid-template-rows: 56% 1fr;
}
.description-title-wrapper {
display: flex;
flex-direction: column;
justify-content: space-between;
}
`
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;
word-break: break-all;
@media (max-width: 600px), (max-height: 500px) {
font-size: 11px;
margin-bottom: 3px;
margin-left: 0;
${({ isTitle }) =>
isTitle &&
css`
overflow: auto;
height: 45px;
`}
}
@media (max-width: 410px) {
.description-section-name {
text-transform: uppercase;
font-size: 10px;
font-weight: 500;
letter-spacing: 0.4px;
color: #216e47;
@media (max-width: 770px) {
font-size: 0.4rem;
}
}
.description-torrent-title {
overflow: auto;
word-break: break-all;
@media (max-width: 770px) {
font-size: 0.6rem;
}
@media (max-width: 600px), (max-height: 500px) {
font-size: 11px;
margin-bottom: 3px;
margin-left: 0;
}
@media (max-width: 410px) {
font-size: 10px;
}
}
.description-statistics-wrapper {
display: grid;
grid-template-columns: 80px 80px 1fr;
align-self: end;
@media (max-width: 1260px), (max-height: 500px) {
grid-template-columns: 70px 70px 1fr;
}
@media (max-width: 770px) {
grid-template-columns: 65px 65px 1fr;
}
@media (max-width: 600px), (max-height: 500px) {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
}
.description-statistics-element-wrapper {
}
.description-statistics-element-value {
margin-left: 5px;
margin-bottom: 10px;
word-break: break-all;
@media (max-width: 1260px), (max-height: 500px) {
font-size: 0.7rem;
margin-bottom: 0;
margin-left: 0;
}
@media (max-width: 770px) {
font-size: 0.6rem;
}
@media (max-width: 600px), (max-height: 500px) {
font-size: 11px;
margin-bottom: 3px;
margin-left: 0;
}
@media (max-width: 410px) {
font-size: 10px;
}
}
`
@@ -121,41 +186,39 @@ export const StyledButton = styled.button`
font-size: 1rem;
font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif;
letter-spacing: 0.009em;
padding: 10px 20px;
:hover {
background: #2a7e54;
}
> :first-child {
margin-right: 10px;
}
@media (max-width: 600px), (max-height: 500px) {
padding: 5px 0;
@media (max-width: 1260px), (max-height: 500px) {
padding: 5px 10px;
font-size: 0.8rem;
justify-content: center;
span {
display: none;
}
svg {
width: 20px;
}
> :first-child {
margin-right: 0;
}
}
@media (max-width: 500px) {
font-size: 0.7rem;
svg {
width: 15px;
}
}
:hover {
background: #2a7e54;
}
`
@media (max-width: 420px) {
padding: 7px 10px;
justify-content: center;
export const TorrentCardDetails = styled.div`
@media (max-width: 600px), (max-height: 500px) {
display: grid;
grid-template-columns: repeat(3, 1fr);
svg {
display: none;
}
}
`

View File

@@ -5,24 +5,10 @@ import { torrentsHost } from 'utils/Hosts'
import TorrentCard from 'components/TorrentCard'
import axios from 'axios'
import CircularProgress from '@material-ui/core/CircularProgress'
const TorrentListWrapper = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, 350px);
gap: 30px;
@media (max-width: 600px), (max-height: 500px) {
gap: 10px;
grid-template-columns: repeat(auto-fit, 310px);
}
@media (max-width: 410px) {
grid-template-columns: minmax(min-content, 290px);
}
`
import { TorrentListWrapper } from 'App/style'
const CenteredGrid = styled.div`
height: 75vh;
height: 100%;
display: grid;
place-items: center;
`
@@ -63,7 +49,9 @@ export default function TorrentList() {
<Typography>Offline</Typography>
</CenteredGrid>
) : !torrents.length ? (
<Typography>No torrents added</Typography>
<CenteredGrid>
<Typography>No torrents added</Typography>
</CenteredGrid>
) : (
<TorrentListWrapper>
{torrents.map(torrent => (