Merge branch 'upload-file-dialog'

This commit is contained in:
Daniel Shleifman
2021-06-09 21:08:21 +03:00
15 changed files with 862 additions and 96 deletions

View File

@@ -1 +1,2 @@
REACT_APP_SERVER_HOST=
REACT_APP_SERVER_HOST=
REACT_APP_TMDB_API_KEY=

View File

@@ -13,11 +13,13 @@
"konva": "^8.0.1",
"lodash": "^4.17.21",
"material-ui-image": "^3.3.2",
"parse-torrent": "^9.1.3",
"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-dropzone": "^11.3.2",
"react-i18next": "^11.10.0",
"react-konva": "^17.0.2-4",
"react-measure": "^2.5.2",

View File

@@ -7,7 +7,6 @@ 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, Language as LanguageIcon } from '@material-ui/icons'
import List from '@material-ui/core/List'
import CloseServer from 'components/CloseServer'
@@ -24,7 +23,6 @@ export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
<AppSidebarStyle isDrawerOpen={isDrawerOpen}>
<List>
<AddDialogButton />
<UploadDialog />
<RemoveAll />
<ListItem button component='a' target='_blank' href={playlistAllHost()}>
<ListItemIcon>

View File

@@ -1,55 +1,308 @@
import { useState } from 'react'
import { useEffect, useMemo, useState } from 'react'
import Button from '@material-ui/core/Button'
import TextField from '@material-ui/core/TextField'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
import DialogTitle from '@material-ui/core/DialogTitle'
import { torrentsHost } from 'utils/Hosts'
import { torrentsHost, torrentUploadHost } from 'utils/Hosts'
import axios from 'axios'
import { useTranslation } from 'react-i18next'
import { NoImageIcon, AddItemIcon, TorrentIcon } from 'icons'
import debounce from 'lodash/debounce'
import { v4 as uuidv4 } from 'uuid'
import useChangeLanguage from 'utils/useChangeLanguage'
import { Cancel as CancelIcon } from '@material-ui/icons'
import { useDropzone } from 'react-dropzone'
import { useMediaQuery } from '@material-ui/core'
import parseTorrent from 'parse-torrent'
import ptt from 'parse-torrent-title'
import {
ButtonWrapper,
CancelIconWrapper,
ClearPosterButton,
PosterLanguageSwitch,
Content,
Header,
IconWrapper,
RightSide,
Poster,
PosterSuggestions,
PosterSuggestionsItem,
PosterWrapper,
LeftSide,
LeftSideBottomSectionFileSelected,
LeftSideBottomSectionNoFile,
LeftSideTopSection,
TorrentIconWrapper,
RightSideContainer,
} from './style'
import { checkImageURL, getMoviePosters, chechTorrentSource } from './helpers'
export default function AddDialog({ handleClose }) {
const { t } = useTranslation()
const [link, setLink] = useState('')
const [torrentSource, setTorrentSource] = useState('')
const [isTorrentSourceActive, setIsTorrentSourceActive] = useState(false)
const [title, setTitle] = useState('')
const [poster, setPoster] = useState('')
const [posterUrl, setPosterUrl] = useState('')
const [isPosterUrlCorrect, setIsPosterUrlCorrect] = useState(false)
const [isTorrentSourceCorrect, setIsTorrentSourceCorrect] = useState(false)
const [posterList, setPosterList] = useState()
const [isUserInteractedWithPoster, setIsUserInteractedWithPoster] = useState(false)
const [isUserInteractedWithTitle, setIsUserInteractedWithTitle] = useState(false)
const [currentLang] = useChangeLanguage()
const [selectedFile, setSelectedFile] = useState()
const [posterSearchLanguage, setPosterSearchLanguage] = useState(currentLang === 'ru' ? 'ru' : 'en')
const inputMagnet = ({ target: { value } }) => setLink(value)
const inputTitle = ({ target: { value } }) => setTitle(value)
const inputPoster = ({ target: { value } }) => setPoster(value)
const fullScreen = useMediaQuery('@media (max-width:930px)')
const posterSearch = useMemo(
() =>
(movieName, language, settings = {}) => {
const { shouldRefreshMainPoster = false } = settings
getMoviePosters(movieName, language).then(urlList => {
if (urlList) {
setPosterList(urlList)
if (!shouldRefreshMainPoster && isUserInteractedWithPoster) return
const [firstPoster] = urlList
checkImageURL(firstPoster).then(correctImage => {
if (correctImage) {
setIsPosterUrlCorrect(true)
setPosterUrl(firstPoster)
} else removePoster()
})
} else {
setPosterList()
if (isUserInteractedWithPoster) return
removePoster()
}
})
},
[isUserInteractedWithPoster],
)
const delayedPosterSearch = useMemo(() => debounce(posterSearch, 700), [posterSearch])
useEffect(() => {
if (isUserInteractedWithTitle) return
parseTorrent.remote(selectedFile || torrentSource, (err, parsedTorrent) => {
if (err) throw err
if (!parsedTorrent.name) return
const torrentName = ptt.parse(parsedTorrent.name).title
const fileInsideTorrentName = parsedTorrent.files ? ptt.parse(parsedTorrent.files[0].name).title : null
let value = torrentName
if (fileInsideTorrentName) {
value = torrentName.length < fileInsideTorrentName.length ? torrentName : fileInsideTorrentName
}
setTitle(value)
delayedPosterSearch(value, posterSearchLanguage)
})
}, [selectedFile, delayedPosterSearch, torrentSource, posterSearchLanguage, isUserInteractedWithTitle])
useEffect(() => {
setIsTorrentSourceCorrect(chechTorrentSource(torrentSource))
}, [torrentSource])
const handleCapture = files => {
const [file] = files
if (!file) return
setIsUserInteractedWithPoster(false)
setSelectedFile(file)
setTorrentSource(file.name)
}
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop: handleCapture, accept: '.torrent' })
const removePoster = () => {
setIsPosterUrlCorrect(false)
setPosterUrl('')
}
const handleTorrentSourceChange = ({ target: { value } }) => setTorrentSource(value)
const handleTitleChange = ({ target: { value } }) => {
setTitle(value)
delayedPosterSearch(value, posterSearchLanguage)
torrentSource && setIsUserInteractedWithTitle(true)
}
const handlePosterUrlChange = ({ target: { value } }) => {
setPosterUrl(value)
checkImageURL(value).then(setIsPosterUrlCorrect)
setIsUserInteractedWithPoster(!!value)
setPosterList()
}
const handleSave = () => {
axios.post(torrentsHost(), { action: 'add', link, title, poster, save_to_db: true }).finally(() => handleClose())
if (selectedFile) {
// file save
const data = new FormData()
data.append('save', 'true')
data.append('file', selectedFile)
title && data.append('title', title)
posterUrl && data.append('poster', posterUrl)
axios.post(torrentUploadHost(), data).finally(handleClose)
} else {
// link save
axios
.post(torrentsHost(), { action: 'add', link: torrentSource, title, poster: posterUrl, save_to_db: true })
.finally(handleClose)
}
}
const clearSelectedFile = () => {
setSelectedFile()
setTorrentSource('')
setIsUserInteractedWithTitle(false)
}
const userChangesPosterUrl = url => {
setPosterUrl(url)
checkImageURL(url).then(setIsPosterUrlCorrect)
setIsUserInteractedWithPoster(true)
}
return (
<Dialog open onClose={handleClose} aria-labelledby='form-dialog-title' fullWidth>
<DialogTitle id='form-dialog-title'>{t('AddMagnetOrLink')}</DialogTitle>
<Dialog
open
onClose={handleClose}
aria-labelledby='form-dialog-title'
fullScreen={fullScreen}
fullWidth
maxWidth='md'
>
<Header>{t('AddNewTorrent')}</Header>
<DialogContent>
<TextField onChange={inputTitle} margin='dense' id='title' label={t('Title')} type='text' fullWidth />
<TextField onChange={inputPoster} margin='dense' id='poster' label={t('Poster')} type='url' fullWidth />
<TextField
onChange={inputMagnet}
autoFocus
margin='dense'
id='magnet'
label={t('MagnetOrTorrentFileLink')}
type='text'
fullWidth
/>
</DialogContent>
<Content>
<LeftSide>
<LeftSideTopSection active={isTorrentSourceActive}>
<TextField
onChange={handleTorrentSourceChange}
value={torrentSource}
margin='dense'
label={t('TorrentSourceLink')}
helperText={t('TorrentSourceOptions')}
type='text'
fullWidth
onFocus={() => setIsTorrentSourceActive(true)}
onBlur={() => setIsTorrentSourceActive(false)}
inputProps={{ autoComplete: 'off' }}
disabled={!!selectedFile}
/>
</LeftSideTopSection>
<DialogActions>
{selectedFile ? (
<LeftSideBottomSectionFileSelected>
<TorrentIconWrapper>
<TorrentIcon />
<CancelIconWrapper onClick={clearSelectedFile}>
<CancelIcon />
</CancelIconWrapper>
</TorrentIconWrapper>
</LeftSideBottomSectionFileSelected>
) : (
<LeftSideBottomSectionNoFile isDragActive={isDragActive} {...getRootProps()}>
<input {...getInputProps()} />
<div>{t('AppendFile.Or')}</div>
<IconWrapper>
<AddItemIcon color='primary' />
<div>{t('AppendFile.ClickOrDrag')}</div>
</IconWrapper>
</LeftSideBottomSectionNoFile>
)}
</LeftSide>
<RightSide>
<RightSideContainer isHidden={!isTorrentSourceCorrect}>
<TextField
onChange={handleTitleChange}
value={title}
margin='dense'
label={t('Title')}
type='text'
fullWidth
/>
<TextField
onChange={handlePosterUrlChange}
value={posterUrl}
margin='dense'
label={t('AddPosterLinkInput')}
type='url'
fullWidth
/>
<PosterWrapper>
<Poster poster={+isPosterUrlCorrect}>
{isPosterUrlCorrect ? <img src={posterUrl} alt='poster' /> : <NoImageIcon />}
</Poster>
<PosterSuggestions>
{posterList
?.filter(url => url !== posterUrl)
.slice(0, 12)
.map(url => (
<PosterSuggestionsItem onClick={() => userChangesPosterUrl(url)} key={uuidv4()}>
<img src={url} alt='poster' />
</PosterSuggestionsItem>
))}
</PosterSuggestions>
{currentLang !== 'en' && (
<PosterLanguageSwitch
onClick={() => {
const newLanguage = posterSearchLanguage === 'en' ? 'ru' : 'en'
setPosterSearchLanguage(newLanguage)
posterSearch(title, newLanguage, { shouldRefreshMainPoster: true })
}}
showbutton={+isPosterUrlCorrect}
color='primary'
variant='contained'
size='small'
>
{posterSearchLanguage === 'en' ? 'EN' : 'RU'}
</PosterLanguageSwitch>
)}
<ClearPosterButton
showbutton={+isPosterUrlCorrect}
onClick={() => {
removePoster()
setIsUserInteractedWithPoster(true)
}}
color='primary'
variant='contained'
size='small'
>
{t('Clear')}
</ClearPosterButton>
</PosterWrapper>
</RightSideContainer>
<RightSideContainer
isError={torrentSource && !isTorrentSourceCorrect}
notificationMessage={
!torrentSource ? t('AddTorrentSourceNotification') : !isTorrentSourceCorrect && t('WrongTorrentSource')
}
isHidden={isTorrentSourceCorrect}
/>
</RightSide>
</Content>
<ButtonWrapper>
<Button onClick={handleClose} color='primary' variant='outlined'>
{t('Cancel')}
</Button>
<Button variant='contained' disabled={!link} onClick={handleSave} color='primary'>
<Button variant='contained' disabled={!torrentSource} onClick={handleSave} color='primary'>
{t('Add')}
</Button>
</DialogActions>
</ButtonWrapper>
</Dialog>
)
}

View File

@@ -0,0 +1,29 @@
import axios from 'axios'
export const getMoviePosters = (movieName, language = 'en') => {
const request = `${`http://api.themoviedb.org/3/search/multi?api_key=${process.env.REACT_APP_TMDB_API_KEY}`}&language=${language}&include_image_language=${language},null&query=${movieName}`
return axios
.get(request)
.then(({ data: { results } }) =>
results.filter(el => el.poster_path).map(el => `https://image.tmdb.org/t/p/w300${el.poster_path}`),
)
.catch(() => null)
}
export const checkImageURL = async url => {
if (!url || !url.match(/.(jpg|jpeg|png|gif)$/i)) return false
try {
await fetch(url)
return true
} catch (e) {
return false
}
}
const magnetRegex = /^magnet:\?xt=urn:[a-z0-9].*/i
const hashRegex = /^\b[0-9a-f]{32}\b$|^\b[0-9a-f]{40}\b$|^\b[0-9a-f]{64}\b$/i
const torrentRegex = /^.*\.(torrent)$/i
export const chechTorrentSource = source =>
source.match(hashRegex) !== null || source.match(magnetRegex) !== null || source.match(torrentRegex) !== null

View File

@@ -0,0 +1,296 @@
import { Button } from '@material-ui/core'
import styled, { css } from 'styled-components'
export const Header = styled.div`
background: #00a572;
color: rgba(0, 0, 0, 0.87);
font-size: 20px;
color: #fff;
font-weight: 500;
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: 15px 24px;
position: relative;
`
export const Content = styled.div`
background: linear-gradient(145deg, #e4f6ed, #b5dec9);
flex: 1;
display: grid;
grid-template-columns: repeat(2, 1fr);
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
overflow: auto;
@media (max-width: 930px) {
grid-template-columns: 1fr;
}
`
export const RightSide = styled.div`
padding: 0 20px 20px 20px;
`
export const RightSideContainer = styled.div`
${({ isHidden, notificationMessage, isError }) => css`
height: 455px;
${notificationMessage &&
css`
position: relative;
white-space: nowrap;
:before {
font-size: 20px;
font-weight: 300;
content: '${notificationMessage}';
display: grid;
place-items: center;
background: ${isError ? '#cda184' : '#84cda7'};
padding: 10px 15px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 5px;
}
`};
${isHidden &&
css`
display: none;
`};
`}
`
export const LeftSide = styled.div`
display: flex;
flex-direction: column;
border-right: 1px solid rgba(0, 0, 0, 0.12);
`
export const LeftSideBottomSectionBasicStyles = css`
transition: transform 0.3s;
padding: 20px;
height: 100%;
display: grid;
`
export const LeftSideBottomSectionNoFile = styled.div`
${LeftSideBottomSectionBasicStyles}
border: 4px dashed rgba(0,0,0,0.1);
text-align: center;
${({ isDragActive }) => isDragActive && `border: 4px dashed green`};
justify-items: center;
grid-template-rows: 100px 1fr;
cursor: pointer;
:hover {
background-color: rgba(0, 0, 0, 0.04);
svg {
transform: translateY(-4%);
}
}
@media (max-width: 930px) {
border: 4px dashed transparent;
height: 400px;
place-items: center;
grid-template-rows: 40% 1fr;
}
`
export const LeftSideBottomSectionFileSelected = styled.div`
${LeftSideBottomSectionBasicStyles}
place-items: center;
@media (max-width: 930px) {
height: 400px;
}
`
export const TorrentIconWrapper = styled.div`
position: relative;
`
export const CancelIconWrapper = styled.div`
position: absolute;
top: -9px;
left: 10px;
cursor: pointer;
> svg {
transition: all 0.3s;
fill: rgba(0, 0, 0, 0.7);
:hover {
fill: rgba(0, 0, 0, 0.6);
}
}
`
export const IconWrapper = styled.div`
display: grid;
justify-items: center;
align-content: start;
gap: 10px;
align-self: start;
svg {
transition: all 0.3s;
}
`
export const LeftSideTopSection = styled.div`
background: #e3f2eb;
padding: 0 20px 20px 20px;
transition: all 0.3s;
${({ active }) => active && 'box-shadow: 0 8px 10px -9px rgba(0, 0, 0, 0.5)'};
`
export const PosterWrapper = styled.div`
margin-top: 20px;
display: grid;
grid-template-columns: max-content 1fr;
grid-template-rows: 300px max-content;
column-gap: 5px;
position: relative;
margin-bottom: 20px;
grid-template-areas:
'poster suggestions'
'clear empty';
@media (max-width: 540px) {
grid-template-columns: 1fr;
gap: 5px 0;
justify-items: center;
grid-template-areas:
'poster'
'clear'
'suggestions';
}
`
export const PosterSuggestions = styled.div`
display: grid;
grid-area: suggestions;
grid-auto-flow: column;
grid-template-columns: repeat(3, max-content);
grid-template-rows: repeat(4, max-content);
gap: 5px;
@media (max-width: 540px) {
grid-auto-flow: row;
grid-template-columns: repeat(5, max-content);
}
@media (max-width: 375px) {
grid-template-columns: repeat(4, max-content);
}
`
export const PosterSuggestionsItem = styled.div`
cursor: pointer;
width: 71px;
height: 71px;
@media (max-width: 430px) {
width: 60px;
height: 60px;
}
@media (max-width: 375px) {
width: 71px;
height: 71px;
}
@media (max-width: 355px) {
width: 60px;
height: 60px;
}
img {
transition: all 0.3s;
border-radius: 5px;
width: 100%;
height: 100%;
object-fit: cover;
:hover {
filter: brightness(130%);
}
}
`
export const Poster = styled.div`
${({ poster }) => css`
border-radius: 5px;
overflow: hidden;
width: 200px;
grid-area: poster;
${poster
? css`
img {
width: 200px;
object-fit: cover;
border-radius: 5px;
height: 100%;
}
`
: css`
display: grid;
place-items: center;
background: #74c39c;
svg {
transform: scale(1.5) translateY(-3px);
}
`}
`}
`
export const ClearPosterButton = styled(Button)`
grid-area: clear;
justify-self: center;
transform: translateY(-50%);
position: absolute;
${({ showbutton }) => !showbutton && 'display: none'};
@media (max-width: 540px) {
transform: translateY(-140%);
}
`
export const PosterLanguageSwitch = styled.div`
grid-area: poster;
z-index: 5;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 30px;
height: 30px;
background: #74c39c;
border-radius: 50%;
display: grid;
place-items: center;
color: #e1f4eb;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
${({ showbutton }) => !showbutton && 'display: none'};
:hover {
filter: brightness(1.1);
}
`
export const ButtonWrapper = styled.div`
padding: 20px;
display: flex;
justify-content: flex-end;
> :not(:last-child) {
margin-right: 10px;
}
`

View File

@@ -11,14 +11,14 @@ import {
DownlodSpeedWidget,
} from '../widgets'
export default function Test({
export default function DetailedView({
downloadSpeed,
uploadSpeed,
torrent,
torrentSize,
PiecesCount,
PiecesLength,
statString,
stat,
cache,
}) {
return (
@@ -32,7 +32,7 @@ export default function Test({
<SizeWidget data={torrentSize} />
<PiecesCountWidget data={PiecesCount} />
<PiecesLengthWidget data={PiecesLength} />
<StatusWidget data={statString} />
<StatusWidget stat={stat} />
</WidgetWrapper>
</DetailedViewWidgetSection>

View File

@@ -54,7 +54,6 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
stat,
download_speed: downloadSpeed,
upload_speed: uploadSpeed,
stat_string: statString,
torrent_size: torrentSize,
file_stats: torrentFileList,
} = torrent
@@ -133,7 +132,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
torrentSize={torrentSize}
PiecesCount={PiecesCount}
PiecesLength={PiecesLength}
statString={statString}
stat={stat}
cache={cache}
/>
) : (
@@ -156,7 +155,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
<UploadSpeedWidget data={uploadSpeed} />
<PeersWidget data={torrent} />
<SizeWidget data={torrentSize} />
<StatusWidget data={statString} />
<StatusWidget stat={stat} />
</WidgetWrapper>
<Divider />

View File

@@ -9,6 +9,7 @@ import {
} from '@material-ui/icons'
import { getPeerString, humanizeSize } from 'utils/Utils'
import { useTranslation } from 'react-i18next'
import { GETTING_INFO, IN_DB, CLOSED, PRELOAD, WORKING } from 'torrentStates'
import StatisticsField from './StatisticsField'
@@ -69,22 +70,26 @@ export const PiecesLengthWidget = ({ data }) => {
)
}
export const StatusWidget = ({ data }) => {
export const StatusWidget = ({ stat }) => {
const { t } = useTranslation()
let i18nd = data
if (data.toLowerCase() === 'torrent added')
i18nd = t('TorrentAdded')
else if (data.toLowerCase() === 'torrent getting info')
i18nd = t('TorrentGettingInfo')
else if (data.toLowerCase() === 'torrent preload')
i18nd = t('TorrentPreload')
else if (data.toLowerCase() === 'torrent working')
i18nd = t('TorrentWorking')
else if (data.toLowerCase() === 'torrent closed')
i18nd = t('TorrentClosed')
else if (data.toLowerCase() === 'torrent in db')
i18nd = t('TorrentInDb')
return <StatisticsField title={t('TorrentStatus')} value={i18nd} iconBg='#aea25b' valueBg='#b4aa6e' icon={BuildIcon} />
const values = {
[GETTING_INFO]: t('TorrentGettingInfo'),
[PRELOAD]: t('TorrentPreload'),
[WORKING]: t('TorrentWorking'),
[CLOSED]: t('TorrentClosed'),
[IN_DB]: t('TorrentInDb'),
}
return (
<StatisticsField
title={t('TorrentStatus')}
value={values[stat]}
iconBg='#aea25b'
valueBg='#b4aa6e'
icon={BuildIcon}
/>
)
}
export const SizeWidget = ({ data }) => {

View File

@@ -1,33 +0,0 @@
import ListItemIcon from '@material-ui/core/ListItemIcon'
import ListItemText from '@material-ui/core/ListItemText'
import ListItem from '@material-ui/core/ListItem'
import PublishIcon from '@material-ui/icons/Publish'
import { torrentUploadHost } from 'utils/Hosts'
import axios from 'axios'
import { useTranslation } from 'react-i18next'
export default function UploadDialog() {
const { t } = useTranslation()
const handleCapture = ({ target: { files } }) => {
const [file] = files
const data = new FormData()
data.append('save', 'true')
data.append('file', file)
axios.post(torrentUploadHost(), data)
}
return (
<div>
<label htmlFor='raised-button-file'>
<input onChange={handleCapture} accept='*/*' type='file' style={{ display: 'none' }} id='raised-button-file' />
<ListItem button variant='raised' type='submit' component='span' key={t('UploadFile')}>
<ListItemIcon>
<PublishIcon />
</ListItemIcon>
<ListItemText primary={t('UploadFile')} />
</ListItem>
</label>
</div>
)
}

View File

@@ -1,4 +1,3 @@
// eslint-disable-next-line import/prefer-default-export
export const NoImageIcon = () => (
<svg
height='80px'
@@ -20,3 +19,96 @@ export const NoImageIcon = () => (
</g>
</svg>
)
export const AddItemIcon = () => (
<svg
height='100px'
width='100px'
fill='#248a57'
viewBox='0 0 452 452'
version='1.1'
xmlns='http://www.w3.org/2000/svg'
>
<g id='#000000ff'>
<path
opacity='1.00'
d=' M 210.49 18.69 C 244.92 16.12 280.02 22.13 311.46 36.47 C 344.90 51.54 374.16 75.69 395.41 105.58 C 415.62 133.87 428.55 167.34 432.48 201.89 C 438.07 248.86 427.02 297.61 401.45 337.43 C 382.92 366.59 357.02 391.04 326.80 407.80 C 300.81 422.31 271.64 431.08 241.96 433.26 C 207.37 435.97 172.14 429.83 140.54 415.51 C 109.95 401.69 82.82 380.33 62.16 353.86 C 39.25 324.67 24.38 289.21 19.78 252.38 C 14.94 214.51 20.65 175.31 36.47 140.54 C 54.11 101.38 84.24 67.99 121.37 46.39 C 148.44 30.52 179.19 20.98 210.49 18.69 M 213.46 36.60 C 178.91 38.80 145.03 50.71 116.76 70.72 C 84.67 93.21 59.84 125.88 46.91 162.88 C 34.87 196.99 32.96 234.54 41.25 269.73 C 48.89 302.45 65.53 332.98 88.79 357.21 C 113.91 383.56 146.78 402.45 182.25 410.72 C 216.67 418.86 253.37 417.21 286.87 405.85 C 329.85 391.49 367.13 361.01 389.89 321.85 C 406.02 294.41 414.96 262.84 415.73 231.03 C 416.71 196.59 408.11 161.91 390.97 132.00 C 372.31 99.13 343.57 72.09 309.61 55.49 C 279.95 40.89 246.43 34.40 213.46 36.60 Z'
/>
<path
opacity='1.00'
d=' M 217.02 117.63 C 223.01 117.45 228.99 117.45 234.98 117.63 C 235.16 150.72 234.93 183.81 235.09 216.89 C 268.18 217.03 301.28 216.82 334.38 216.99 C 334.57 222.99 334.57 229.00 334.38 235.01 C 301.28 235.18 268.18 234.97 235.09 235.11 C 234.93 268.19 235.16 301.28 234.98 334.37 C 228.99 334.55 223.00 334.55 217.02 334.37 C 216.84 301.28 217.07 268.19 216.92 235.11 C 183.82 234.97 150.72 235.17 117.62 235.01 C 117.43 229.00 117.43 222.99 117.62 216.99 C 150.72 216.82 183.82 217.03 216.91 216.89 C 217.07 183.81 216.84 150.72 217.02 117.63 Z'
/>
</g>
</svg>
)
export const TorrentIcon = () => (
<svg width='150px' height='150px' viewBox='0 0 512 512' version='1.1' xmlns='http://www.w3.org/2000/svg'>
<g id='#248a57ff'>
<path
fill='#248a57'
opacity='1.00'
d=' M 102.41 0.00 L 319.87 0.00 C 320.21 29.68 319.87 59.37 320.04 89.05 C 320.29 97.32 323.88 105.47 329.94 111.12 C 336.01 117.07 344.56 120.18 353.01 120.01 C 382.02 119.87 411.04 120.22 440.05 119.83 C 439.94 236.88 440.04 353.93 440.00 470.98 C 440.01 478.16 440.50 485.68 437.47 492.41 C 432.79 503.85 421.05 511.80 408.71 512.00 L 103.28 512.00 C 90.95 511.79 79.20 503.84 74.53 492.42 C 72.06 486.96 71.87 480.87 71.99 474.97 C 72.01 327.63 71.99 180.30 72.00 32.96 C 71.95 27.61 73.03 22.22 75.52 17.46 C 80.55 7.39 91.19 0.57 102.41 0.00 M 360.00 382.07 C 358.69 383.73 359.01 385.99 358.90 387.97 C 358.95 396.36 358.91 404.75 358.93 413.14 C 352.50 403.51 346.13 393.83 339.77 384.16 C 338.65 382.47 337.13 380.65 334.92 380.63 C 331.97 380.41 329.13 382.87 329.22 385.89 C 328.94 396.58 329.24 407.28 329.08 417.98 C 329.14 420.43 328.85 422.98 329.54 425.38 C 330.75 429.14 337.11 428.63 337.54 424.63 C 338.19 415.09 337.55 405.51 337.83 395.95 C 343.71 404.78 349.41 413.73 355.26 422.58 C 356.92 424.93 358.74 427.96 362.00 428.00 C 365.02 428.51 367.54 425.83 367.40 422.90 C 367.55 411.27 367.39 399.62 367.48 387.99 C 367.40 386.11 367.63 384.06 366.61 382.38 C 365.24 380.16 361.58 380.00 360.00 382.07 M 100.79 382.81 C 98.94 384.82 100.19 388.63 103.01 388.89 C 106.91 389.29 110.85 388.97 114.77 389.07 C 114.77 399.73 114.78 410.39 114.75 421.05 C 114.76 423.37 114.89 426.34 117.28 427.52 C 119.95 429.02 123.67 427.14 123.86 424.04 C 124.22 412.40 123.84 400.72 124.04 389.07 C 128.25 388.87 132.57 389.54 136.71 388.62 C 140.15 387.40 139.25 381.72 135.61 381.56 C 126.10 381.14 116.55 381.57 107.03 381.37 C 104.95 381.53 102.34 381.06 100.79 382.81 M 156.46 381.58 C 150.26 383.15 145.11 388.05 143.12 394.11 C 140.49 401.86 140.79 410.83 144.81 418.06 C 151.07 429.05 167.20 430.79 177.27 424.26 C 183.48 420.06 186.24 412.28 186.28 405.03 C 186.43 398.11 184.59 390.56 179.19 385.85 C 173.03 380.52 164.12 379.62 156.46 381.58 M 197.74 381.67 C 195.24 381.99 194.12 384.61 194.23 386.87 C 194.06 397.92 194.27 408.97 194.15 420.02 C 194.24 422.43 193.92 425.36 195.97 427.11 C 198.62 429.25 203.28 427.47 203.31 423.89 C 203.66 418.45 203.32 412.99 203.49 407.54 C 206.76 407.72 210.68 407.24 213.15 409.89 C 217.60 414.61 220.01 420.80 223.85 425.97 C 225.63 428.66 230.20 428.72 231.83 425.86 C 232.87 424.27 231.80 422.43 231.24 420.89 C 228.63 415.38 225.17 409.99 220.02 406.56 C 223.42 405.53 227.11 404.31 229.29 401.31 C 233.14 395.94 231.83 387.34 226.14 383.76 C 221.99 381.01 216.77 381.52 212.04 381.39 C 207.28 381.52 202.48 381.08 197.74 381.67 M 240.23 386.91 C 240.19 398.28 240.20 409.66 240.22 421.03 C 240.25 423.12 240.14 425.65 241.97 427.09 C 244.58 429.23 249.25 427.52 249.33 423.98 C 249.76 418.50 249.34 413.00 249.49 407.51 C 252.77 407.64 256.62 407.29 259.13 409.85 C 263.88 414.69 266.10 421.38 270.41 426.55 C 272.74 429.20 278.48 428.00 278.28 424.04 C 276.28 417.09 271.87 410.81 266.09 406.46 C 269.75 405.55 273.64 404.05 275.74 400.71 C 278.91 395.49 277.81 387.82 272.73 384.18 C 268.85 381.14 263.64 381.44 259.00 381.41 C 254.02 381.52 249.02 381.13 244.05 381.58 C 241.41 381.77 240.05 384.51 240.23 386.91 M 286.38 386.01 C 286.17 397.35 286.39 408.70 286.27 420.04 C 286.31 422.30 286.17 425.31 288.52 426.53 C 291.20 427.60 294.20 427.07 297.03 427.21 C 304.36 427.04 311.73 427.52 319.04 426.95 C 322.44 426.37 322.43 420.75 319.05 420.15 C 311.25 419.44 303.38 420.13 295.56 419.82 C 295.59 415.47 295.58 411.12 295.58 406.78 C 302.60 406.71 309.65 407.09 316.66 406.54 C 320.07 405.84 319.57 399.91 315.98 399.96 C 309.20 399.54 302.39 399.95 295.59 399.80 C 295.57 396.05 295.57 392.30 295.58 388.55 C 303.03 388.43 310.50 388.74 317.94 388.37 C 321.67 388.25 321.80 381.95 318.11 381.66 C 309.41 381.03 300.65 381.57 291.93 381.42 C 289.16 381.15 286.27 383.00 286.38 386.01 M 375.06 381.95 C 372.19 383.34 372.77 388.27 375.95 388.84 C 379.96 389.33 384.02 388.96 388.05 389.08 C 387.92 400.08 388.05 411.07 387.99 422.07 C 387.75 424.61 389.07 427.71 391.95 427.92 C 394.85 428.51 397.33 425.86 397.14 423.05 C 397.37 411.73 397.16 400.40 397.23 389.08 C 401.42 388.89 405.69 389.52 409.82 388.64 C 413.41 387.46 412.48 381.48 408.64 381.52 C 400.79 381.23 392.93 381.50 385.08 381.39 C 381.74 381.50 378.31 381.05 375.06 381.95 Z'
/>
<path
fill='#248a57'
opacity='1.00'
d=' M 160.39 388.45 C 164.79 387.33 170.01 388.38 173.03 391.97 C 176.12 395.52 177.00 400.46 176.87 405.04 C 176.76 409.47 175.56 414.16 172.29 417.34 C 167.50 421.98 158.82 421.68 154.58 416.43 C 150.59 411.44 150.26 404.45 151.51 398.43 C 152.46 393.85 155.68 389.57 160.39 388.45 Z'
/>
<path
fill='#248a57'
opacity='1.00'
d=' M 203.47 388.42 C 208.28 388.55 213.18 387.93 217.93 388.93 C 222.82 390.10 223.71 398.14 218.81 399.89 C 213.88 401.57 208.52 400.89 203.40 400.90 C 203.44 396.73 203.45 392.57 203.47 388.42 Z'
/>
<path
fill='#248a57'
opacity='1.00'
d=' M 249.45 388.38 C 254.29 388.56 259.22 387.96 264.00 388.94 C 268.52 390.07 269.67 397.04 265.66 399.44 C 260.63 401.83 254.85 400.80 249.47 400.94 C 249.51 396.75 249.48 392.57 249.45 388.38 Z'
/>
</g>
<g id='#74c39cff'>
<path
fill='#74c39c'
opacity='1.00'
d=' M 319.87 0.00 L 320.20 0.00 C 360.20 39.89 400.19 79.79 440.05 119.83 C 411.04 120.22 382.02 119.87 353.01 120.01 C 344.56 120.18 336.01 117.07 329.94 111.12 C 323.88 105.47 320.29 97.32 320.04 89.05 C 319.87 59.37 320.21 29.68 319.87 0.00 Z'
/>
</g>
<g id='#fdfdfdff'>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 360.00 382.07 C 361.58 380.00 365.24 380.16 366.61 382.38 C 367.63 384.06 367.40 386.11 367.48 387.99 C 367.39 399.62 367.55 411.27 367.40 422.90 C 367.54 425.83 365.02 428.51 362.00 428.00 C 358.74 427.96 356.92 424.93 355.26 422.58 C 349.41 413.73 343.71 404.78 337.83 395.95 C 337.55 405.51 338.19 415.09 337.54 424.63 C 337.11 428.63 330.75 429.14 329.54 425.38 C 328.85 422.98 329.14 420.43 329.08 417.98 C 329.24 407.28 328.94 396.58 329.22 385.89 C 329.13 382.87 331.97 380.41 334.92 380.63 C 337.13 380.65 338.65 382.47 339.77 384.16 C 346.13 393.83 352.50 403.51 358.93 413.14 C 358.91 404.75 358.95 396.36 358.90 387.97 C 359.01 385.99 358.69 383.73 360.00 382.07 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 100.79 382.81 C 102.34 381.06 104.95 381.53 107.03 381.37 C 116.55 381.57 126.10 381.14 135.61 381.56 C 139.25 381.72 140.15 387.40 136.71 388.62 C 132.57 389.54 128.25 388.87 124.04 389.07 C 123.84 400.72 124.22 412.40 123.86 424.04 C 123.67 427.14 119.95 429.02 117.28 427.52 C 114.89 426.34 114.76 423.37 114.75 421.05 C 114.78 410.39 114.77 399.73 114.77 389.07 C 110.85 388.97 106.91 389.29 103.01 388.89 C 100.19 388.63 98.94 384.82 100.79 382.81 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 156.46 381.58 C 164.12 379.62 173.03 380.52 179.19 385.85 C 184.59 390.56 186.43 398.11 186.28 405.03 C 186.24 412.28 183.48 420.06 177.27 424.26 C 167.20 430.79 151.07 429.05 144.81 418.06 C 140.79 410.83 140.49 401.86 143.12 394.11 C 145.11 388.05 150.26 383.15 156.46 381.58 M 160.39 388.45 C 155.68 389.57 152.46 393.85 151.51 398.43 C 150.26 404.45 150.59 411.44 154.58 416.43 C 158.82 421.68 167.50 421.98 172.29 417.34 C 175.56 414.16 176.76 409.47 176.87 405.04 C 177.00 400.46 176.12 395.52 173.03 391.97 C 170.01 388.38 164.79 387.33 160.39 388.45 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 197.74 381.67 C 202.48 381.08 207.28 381.52 212.04 381.39 C 216.77 381.52 221.99 381.01 226.14 383.76 C 231.83 387.34 233.14 395.94 229.29 401.31 C 227.11 404.31 223.42 405.53 220.02 406.56 C 225.17 409.99 228.63 415.38 231.24 420.89 C 231.80 422.43 232.87 424.27 231.83 425.86 C 230.20 428.72 225.63 428.66 223.85 425.97 C 220.01 420.80 217.60 414.61 213.15 409.89 C 210.68 407.24 206.76 407.72 203.49 407.54 C 203.32 412.99 203.66 418.45 203.31 423.89 C 203.28 427.47 198.62 429.25 195.97 427.11 C 193.92 425.36 194.24 422.43 194.15 420.02 C 194.27 408.97 194.06 397.92 194.23 386.87 C 194.12 384.61 195.24 381.99 197.74 381.67 M 203.47 388.42 C 203.45 392.57 203.44 396.73 203.40 400.90 C 208.52 400.89 213.88 401.57 218.81 399.89 C 223.71 398.14 222.82 390.10 217.93 388.93 C 213.18 387.93 208.28 388.55 203.47 388.42 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 240.23 386.91 C 240.05 384.51 241.41 381.77 244.05 381.58 C 249.02 381.13 254.02 381.52 259.00 381.41 C 263.64 381.44 268.85 381.14 272.73 384.18 C 277.81 387.82 278.91 395.49 275.74 400.71 C 273.64 404.05 269.75 405.55 266.09 406.46 C 271.87 410.81 276.28 417.09 278.28 424.04 C 278.48 428.00 272.74 429.20 270.41 426.55 C 266.10 421.38 263.88 414.69 259.13 409.85 C 256.62 407.29 252.77 407.64 249.49 407.51 C 249.34 413.00 249.76 418.50 249.33 423.98 C 249.25 427.52 244.58 429.23 241.97 427.09 C 240.14 425.65 240.25 423.12 240.22 421.03 C 240.20 409.66 240.19 398.28 240.23 386.91 M 249.45 388.38 C 249.48 392.57 249.51 396.75 249.47 400.94 C 254.85 400.80 260.63 401.83 265.66 399.44 C 269.67 397.04 268.52 390.07 264.00 388.94 C 259.22 387.96 254.29 388.56 249.45 388.38 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 286.38 386.01 C 286.27 383.00 289.16 381.15 291.93 381.42 C 300.65 381.57 309.41 381.03 318.11 381.66 C 321.80 381.95 321.67 388.25 317.94 388.37 C 310.50 388.74 303.03 388.43 295.58 388.55 C 295.57 392.30 295.57 396.05 295.59 399.80 C 302.39 399.95 309.20 399.54 315.98 399.96 C 319.57 399.91 320.07 405.84 316.66 406.54 C 309.65 407.09 302.60 406.71 295.58 406.78 C 295.58 411.12 295.59 415.47 295.56 419.82 C 303.38 420.13 311.25 419.44 319.05 420.15 C 322.43 420.75 322.44 426.37 319.04 426.95 C 311.73 427.52 304.36 427.04 297.03 427.21 C 294.20 427.07 291.20 427.60 288.52 426.53 C 286.17 425.31 286.31 422.30 286.27 420.04 C 286.39 408.70 286.17 397.35 286.38 386.01 Z'
/>
<path
fill='#fdfdfd'
opacity='1.00'
d=' M 375.06 381.95 C 378.31 381.05 381.74 381.50 385.08 381.39 C 392.93 381.50 400.79 381.23 408.64 381.52 C 412.48 381.48 413.41 387.46 409.82 388.64 C 405.69 389.52 401.42 388.89 397.23 389.08 C 397.16 400.40 397.37 411.73 397.14 423.05 C 397.33 425.86 394.85 428.51 391.95 427.92 C 389.07 427.71 387.75 424.61 387.99 422.07 C 388.05 411.07 387.92 400.08 388.05 389.08 C 384.02 388.96 379.96 389.33 375.95 388.84 C 372.77 388.27 372.19 383.34 375.06 381.95 Z'
/>
</g>
</svg>
)

View File

@@ -3,7 +3,7 @@
"Actions": "Actions",
"Add": "Add",
"AddFromLink": "Add from Link",
"AddMagnetOrLink": "Add magnet or link to torrent file",
"AddNewTorrent": "Add new torrent",
"AddRetrackers": "Add retrackers",
"Buffer": "Preload Buffer / Cache",
"BufferNote": "Enable “Preload Buffer” in settings to see cache loading progress",
@@ -39,7 +39,7 @@
"Host": "Host",
"Info": "Info",
"LatestFilePlayed": "Latest file played:",
"MagnetOrTorrentFileLink": "Magnet or torrent file link",
"TorrentSourceLink": "Torrent source link",
"Name": "Name",
"NoTorrentsAdded": "No torrents added",
"Offline": "Offline",
@@ -51,7 +51,7 @@
"PiecesCount": "Pieces count",
"PiecesLength": "Pieces length",
"PlaylistAll": "Playlist All",
"Poster": "Poster",
"AddPosterLinkInput": "Poster link",
"Preload": "Preload",
"PreloadBuffer": "Preload Buffer",
"ReaderReadAHead": "Reader Read Ahead (5-100%)",
@@ -62,7 +62,7 @@
"RemoveViews": "Remove View States",
"ReplaceRetrackers": "Replace retrackers",
"Resolution": "Resolution",
"RetrackersMode": "Retrackers Mode",
"RetrackersMode": "Retrackers Mode",
"Save": "Save",
"Season": "Season",
"SelectSeason": "Select Season",
@@ -96,5 +96,13 @@
"UseDisk": "Use Disk for Cache",
"UseDiskDesc": "Better use external media on flash-based devices",
"UTP": "μTP (Micro Transport Protocol)",
"Viewed": "Viewed"
"Viewed": "Viewed",
"AppendFile": {
"Or": "OR",
"ClickOrDrag": "CLICK / DRAG & DROP (.torrent)"
},
"TorrentSourceOptions": "magnet / hash / .torrent file link",
"Clear": "Clear",
"AddTorrentSourceNotification": "First add your torrent source",
"WrongTorrentSource": "Wrong torrent source"
}

View File

@@ -3,7 +3,7 @@
"Actions": "Действия",
"Add": "Добавить",
"AddFromLink": "Добавить",
"AddMagnetOrLink": "Добавьте magnet или ссылку на торрент",
"AddNewTorrent": "Добавить новый торрент",
"AddRetrackers": "Добавлять",
"Buffer": "Предзагрузка / Кеш",
"BufferNote": "Включите «Наполнять кеш перед началом воспроизведения» в настройках для показа заполнения кеша",
@@ -39,7 +39,7 @@
"Host": "Хост",
"Info": "Инфо",
"LatestFilePlayed": "Последний воспроизведенный файл:",
"MagnetOrTorrentFileLink": "Ссылка на файл торрента или magnet-ссылка",
"TorrentSourceLink": "Ссылка на источник торрента",
"Name": "Название",
"NoTorrentsAdded": "Нет торрентов",
"Offline": "Сервер не доступен",
@@ -51,7 +51,7 @@
"PiecesCount": "Кол-во блоков",
"PiecesLength": "Размер блока",
"PlaylistAll": "Плейлист всех",
"Poster": остер",
"AddPosterLinkInput": "Ссылка на постер",
"Preload": "Предзагр.",
"PreloadBuffer": "Наполнять кеш перед началом воспроизведения",
"ReaderReadAHead": "Кеш предзагрузки (5-100%, рек. 95%)",
@@ -96,5 +96,13 @@
"UseDisk": "Использовать диск для кеша",
"UseDiskDesc": "Рекомендуется использовать внешние носители на устройствах с flash-памятью",
"UTP": "μTP (Micro Transport Protocol)",
"Viewed": "Просм."
"Viewed": "Просм.",
"AppendFile": {
"Or": "ИЛИ",
"ClickOrDrag": "НАЖМИТЕ / ПЕРЕТАЩИТЕ ФАЙЛ (.torrent)"
},
"TorrentSourceOptions": "magnet ссылка / хеш / ссылка на .torrent файл",
"Clear": "Очистить",
"AddTorrentSourceNotification": "Сначала добавьте торрент источник",
"WrongTorrentSource": "Неправильный torrent источник"
}

View File

@@ -2730,6 +2730,11 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
attr-accept@^2.2.1:
version "2.2.2"
resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b"
integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==
autoprefixer@^9.6.1:
version "9.8.6"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f"
@@ -3218,6 +3223,18 @@ batch@0.6.1:
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
bencode@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/bencode/-/bencode-2.0.1.tgz#667a6a31c5e038d558608333da6b7c94e836c85b"
integrity sha512-2uhEl8FdjSBUyb69qDTgOEeeqDTa+n3yMQzLW0cOzNf1Ow5bwcg3idf+qsWisIKRH8Bk8oC7UXL8irRcPA8ZEQ==
dependencies:
safe-buffer "^5.1.1"
bep53-range@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/bep53-range/-/bep53-range-1.1.0.tgz#a009311710c955d27eb3a30cf329e8c139693d27"
integrity sha512-yGQTG4NtwTciX0Bkgk1FqQL4p+NiCQKpTSFho2lrxvUkXIlzyJDwraj8aYxAxRZMnnOhRr7QlIBoMRPEnIR34Q==
bfj@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2"
@@ -3255,6 +3272,11 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
blob-to-buffer@^1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz#a17fd6c1c564011408f8971e451544245daaa84a"
integrity sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==
bluebird@^3.5.5:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -4523,6 +4545,13 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
@@ -5591,6 +5620,13 @@ file-loader@6.1.1:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
file-selector@^0.2.2:
version "0.2.4"
resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.2.4.tgz#7b98286f9dbb9925f420130ea5ed0a69238d4d80"
integrity sha512-ZDsQNbrv6qRi1YTDOEWzf5J2KjZ9KMI1Q2SGeTkCJmNNW25Jg4TW4UMcmoqcg4WrAyKRcpBXdbWRxkfrOzVRbA==
dependencies:
tslib "^2.0.3"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@@ -5956,6 +5992,11 @@ get-package-type@^0.1.0:
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
get-stdin@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
get-stream@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
@@ -8131,6 +8172,14 @@ magic-string@^0.25.0, magic-string@^0.25.7:
dependencies:
sourcemap-codec "^1.4.4"
magnet-uri@^6.0.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/magnet-uri/-/magnet-uri-6.2.0.tgz#10f7be050bf23452df210838239b118463c3eeff"
integrity sha512-O9AgdDwT771fnUj0giPYu/rACpz8173y8UXCSOdLITjOVfBenZ9H9q3FqQmveK+ORUMuD+BkKNSZP8C3+IMAKQ==
dependencies:
bep53-range "^1.1.0"
thirty-two "^1.0.2"
make-dir@^2.0.0, make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@@ -8326,6 +8375,11 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
mini-css-extract-plugin@0.11.3:
version "0.11.3"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6"
@@ -9088,6 +9142,19 @@ parse-torrent-title@^1.3.0:
resolved "https://registry.yarnpkg.com/parse-torrent-title/-/parse-torrent-title-1.3.0.tgz#3dedea10277b17998b124a4fd67d9e190b0306b8"
integrity sha512-R5wya73/Ef0qUhb9177Ko8nRQyN1ziWD5DPnlrDrrgcchUnmIrG//cPENunvFYRZCLDZosXTKTo7TpQ2Pgbryg==
parse-torrent@^9.1.3:
version "9.1.3"
resolved "https://registry.yarnpkg.com/parse-torrent/-/parse-torrent-9.1.3.tgz#9b4bc8dca243b356bf449938d6d38a259a2a707c"
integrity sha512-/Yr951CvJM8S6TjMaqrsmMxeQEAjDeCX+MZ3hGXXc7DG2wqzp/rzOsHtDzIVqN6NsFRCqy6wYLF/W7Sgvq7bXw==
dependencies:
bencode "^2.0.1"
blob-to-buffer "^1.2.9"
get-stdin "^8.0.0"
magnet-uri "^6.0.0"
queue-microtask "^1.2.2"
simple-get "^4.0.0"
simple-sha1 "^3.0.1"
parse5@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
@@ -10322,6 +10389,15 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-dropzone@^11.3.2:
version "11.3.2"
resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-11.3.2.tgz#2efb6af800a4779a9daa1e7ba1f8d51d0ab862d7"
integrity sha512-Z0l/YHcrNK1r85o6RT77Z5XgTARmlZZGfEKBl3tqTXL9fZNQDuIdRx/J0QjvR60X+yYu26dnHeaG2pWU+1HHvw==
dependencies:
attr-accept "^2.2.1"
file-selector "^0.2.2"
prop-types "^15.7.2"
react-error-overlay@^6.0.9:
version "6.0.9"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
@@ -10962,6 +11038,11 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
rusha@^0.8.13:
version "0.8.14"
resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68"
integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@@ -11255,6 +11336,28 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
simple-concat@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
simple-get@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675"
integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==
dependencies:
decompress-response "^6.0.0"
once "^1.3.1"
simple-concat "^1.0.0"
simple-sha1@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/simple-sha1/-/simple-sha1-3.1.0.tgz#40cac8436dfaf9924332fc46a5c7bca45f656131"
integrity sha512-ArTptMRC1v08H8ihPD6l0wesKvMfF9e8XL5rIHPanI7kGOsSsbY514MwVu6X1PITHCTB2F08zB7cyEbfc4wQjg==
dependencies:
queue-microtask "^1.2.2"
rusha "^0.8.13"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
@@ -11977,6 +12080,11 @@ textextensions@^3.2.0:
resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-3.3.0.tgz#03530d5287b86773c08b77458589148870cc71d3"
integrity sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==
thirty-two@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a"
integrity sha1-TKL//AKlEpDSdEueP1V2k8prYno=
throat@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"