mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
torrent cards rewritten
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
"parse-torrent-title": "^1.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-copy-to-clipboard": "^5.0.3",
|
||||
"react-div-100vh": "^0.6.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-konva": "^17.0.2-4",
|
||||
"react-measure": "^2.5.2",
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core'
|
||||
|
||||
import Appbar from './components/Appbar/index'
|
||||
|
||||
const baseTheme = createMuiTheme({
|
||||
overrides: {
|
||||
MuiCssBaseline: {
|
||||
'@global': {
|
||||
html: {
|
||||
WebkitFontSmoothing: 'auto',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
palette: {
|
||||
primary: {
|
||||
main: '#3fb57a',
|
||||
},
|
||||
secondary: {
|
||||
main: '#FFA724',
|
||||
},
|
||||
tonalOffset: 0.2,
|
||||
},
|
||||
})
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<MuiThemeProvider theme={baseTheme}>
|
||||
<CssBaseline />
|
||||
<Appbar />
|
||||
</MuiThemeProvider>
|
||||
)
|
||||
}
|
||||
60
web/src/App/Sidebar.jsx
Normal file
60
web/src/App/Sidebar.jsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { playlistAllHost, shutdownHost } from 'utils/Hosts'
|
||||
import Divider from '@material-ui/core/Divider'
|
||||
import ListItem from '@material-ui/core/ListItem'
|
||||
import ListItemIcon from '@material-ui/core/ListItemIcon'
|
||||
import ListItemText from '@material-ui/core/ListItemText'
|
||||
import AddDialogButton from 'components/Add'
|
||||
import RemoveAll from 'components/RemoveAll'
|
||||
import SettingsDialog from 'components/Settings'
|
||||
import AboutDialog from 'components/About'
|
||||
import UploadDialog from 'components/Upload'
|
||||
import {
|
||||
CreditCard as CreditCardIcon,
|
||||
List as ListIcon,
|
||||
PowerSettingsNew as PowerSettingsNewIcon,
|
||||
} from '@material-ui/icons'
|
||||
import List from '@material-ui/core/List'
|
||||
|
||||
import { AppSidebarStyle } from './style'
|
||||
|
||||
export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
|
||||
return (
|
||||
<AppSidebarStyle isDrawerOpen={isDrawerOpen}>
|
||||
<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>
|
||||
</AppSidebarStyle>
|
||||
)
|
||||
}
|
||||
66
web/src/App/index.jsx
Normal file
66
web/src/App/index.jsx
Normal file
@@ -0,0 +1,66 @@
|
||||
import CssBaseline from '@material-ui/core/CssBaseline'
|
||||
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import IconButton from '@material-ui/core/IconButton'
|
||||
import { Menu as MenuIcon, Close as CloseIcon } from '@material-ui/icons'
|
||||
import { getTorrServerHost } from 'utils/Hosts'
|
||||
import TorrentList from 'components/TorrentList'
|
||||
import DonateSnackbar from 'components/Donate'
|
||||
import DonateDialog from 'components/Donate/DonateDialog'
|
||||
import Div100vh from 'react-div-100vh'
|
||||
|
||||
import { AppWrapper, AppHeader } from './style'
|
||||
import Sidebar from './Sidebar'
|
||||
|
||||
const baseTheme = createMuiTheme({
|
||||
overrides: { MuiCssBaseline: { '@global': { html: { WebkitFontSmoothing: 'auto' } } } },
|
||||
palette: { primary: { main: '#3fb57a' }, secondary: { main: '#FFA724' }, tonalOffset: 0.2 },
|
||||
})
|
||||
|
||||
export default function App() {
|
||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false)
|
||||
const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
|
||||
const [tsVersion, setTSVersion] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`${getTorrServerHost()}/echo`)
|
||||
.then(resp => resp.text())
|
||||
.then(txt => {
|
||||
if (!txt.startsWith('<!DOCTYPE html>')) setTSVersion(txt)
|
||||
})
|
||||
}, [isDrawerOpen])
|
||||
|
||||
return (
|
||||
<MuiThemeProvider theme={baseTheme}>
|
||||
<CssBaseline />
|
||||
|
||||
{/* Div100vh - iOS WebKit fix */}
|
||||
<Div100vh>
|
||||
<AppWrapper>
|
||||
<AppHeader>
|
||||
<IconButton
|
||||
style={{ marginRight: '20px' }}
|
||||
color='inherit'
|
||||
onClick={() => setIsDrawerOpen(!isDrawerOpen)}
|
||||
edge='start'
|
||||
>
|
||||
{isDrawerOpen ? <CloseIcon /> : <MenuIcon />}
|
||||
</IconButton>
|
||||
|
||||
<Typography variant='h6' noWrap>
|
||||
TorrServer {tsVersion}
|
||||
</Typography>
|
||||
</AppHeader>
|
||||
|
||||
<Sidebar isDrawerOpen={isDrawerOpen} setIsDonationDialogOpen={setIsDonationDialogOpen} />
|
||||
|
||||
<TorrentList />
|
||||
|
||||
{isDonationDialogOpen && <DonateDialog onClose={() => setIsDonationDialogOpen(false)} />}
|
||||
{!JSON.parse(localStorage.getItem('snackbarIsClosed')) && <DonateSnackbar />}
|
||||
</AppWrapper>
|
||||
</Div100vh>
|
||||
</MuiThemeProvider>
|
||||
)
|
||||
}
|
||||
57
web/src/App/style.js
Normal file
57
web/src/App/style.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import styled, { css } from 'styled-components'
|
||||
|
||||
export const AppWrapper = styled.div`
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: 60px 1fr;
|
||||
grid-template-rows: 60px 1fr;
|
||||
grid-template-areas:
|
||||
'head head'
|
||||
'side content';
|
||||
`
|
||||
export const AppHeader = styled.div`
|
||||
background: #3fb57a;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
grid-area: head;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
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: 0 24px;
|
||||
z-index: 3;
|
||||
`
|
||||
export const AppSidebarStyle = styled.div`
|
||||
${({ isDrawerOpen }) => css`
|
||||
grid-area: side;
|
||||
width: ${isDrawerOpen ? '400%' : '100%'};
|
||||
z-index: 2;
|
||||
overflow-x: hidden;
|
||||
transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms;
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.12);
|
||||
background: #fff;
|
||||
white-space: nowrap;
|
||||
`}
|
||||
`
|
||||
export const TorrentListWrapper = styled.div`
|
||||
grid-area: content;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
|
||||
display: grid;
|
||||
place-content: start;
|
||||
grid-template-columns: repeat(auto-fit, minmax(max-content, 570px));
|
||||
gap: 20px;
|
||||
|
||||
@media (max-width: 1260px), (max-height: 500px) {
|
||||
padding: 10px;
|
||||
gap: 15px;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
@media (max-width: 1100px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
`
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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),
|
||||
},
|
||||
}))
|
||||
@@ -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 />
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -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 => (
|
||||
|
||||
@@ -8,3 +8,6 @@ export function getPeerString(torrent) {
|
||||
if (!torrent || !torrent.connected_seeders) return ''
|
||||
return `[${torrent.connected_seeders}] ${torrent.active_peers} / ${torrent.total_peers}`
|
||||
}
|
||||
|
||||
export const shortenText = (text, sympolAmount) =>
|
||||
text.slice(0, sympolAmount) + (text.length > sympolAmount ? '...' : '')
|
||||
|
||||
@@ -10282,6 +10282,11 @@ react-dev-utils@^11.0.3:
|
||||
strip-ansi "6.0.0"
|
||||
text-table "0.2.0"
|
||||
|
||||
react-div-100vh@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/react-div-100vh/-/react-div-100vh-0.6.0.tgz#577972d8ac17693edcd44061c1a4b5a7578e49ec"
|
||||
integrity sha512-ErV0VTNXUd8jZqofC0ExZr5u+XDD2kN2te4SbwtqsyTm0UOjVYu53kP+FalGQrTe+DoMG8VYR2dITcAFu7c/5w==
|
||||
|
||||
react-dom@^17.0.2:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
|
||||
Reference in New Issue
Block a user