mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
added support of original title in add dialog
This commit is contained in:
@@ -25,6 +25,7 @@ export default function AddDialog({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [torrentSource, setTorrentSource] = useState(originalHash || '')
|
const [torrentSource, setTorrentSource] = useState(originalHash || '')
|
||||||
const [title, setTitle] = useState(originalTitle || '')
|
const [title, setTitle] = useState(originalTitle || '')
|
||||||
|
const [parsedTitle, setParsedTitle] = useState('')
|
||||||
const [posterUrl, setPosterUrl] = useState(originalPoster || '')
|
const [posterUrl, setPosterUrl] = useState(originalPoster || '')
|
||||||
const [isPosterUrlCorrect, setIsPosterUrlCorrect] = useState(false)
|
const [isPosterUrlCorrect, setIsPosterUrlCorrect] = useState(false)
|
||||||
const [isTorrentSourceCorrect, setIsTorrentSourceCorrect] = useState(false)
|
const [isTorrentSourceCorrect, setIsTorrentSourceCorrect] = useState(false)
|
||||||
@@ -85,7 +86,7 @@ export default function AddDialog({
|
|||||||
|
|
||||||
const delayedPosterSearch = useMemo(() => debounce(posterSearch, 700), [posterSearch])
|
const delayedPosterSearch = useMemo(() => debounce(posterSearch, 700), [posterSearch])
|
||||||
|
|
||||||
const prevTitleState = usePreviousState(title)
|
const prevParsedTitleState = usePreviousState(parsedTitle)
|
||||||
const prevTorrentSourceState = usePreviousState(torrentSource)
|
const prevTorrentSourceState = usePreviousState(torrentSource)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -98,27 +99,28 @@ export default function AddDialog({
|
|||||||
setIsTorrentSourceCorrect(true)
|
setIsTorrentSourceCorrect(true)
|
||||||
|
|
||||||
if (torrentSourceChanged) {
|
if (torrentSourceChanged) {
|
||||||
parseTorrentTitle(selectedFile || torrentSource, newTitle => {
|
parseTorrentTitle(selectedFile || torrentSource, ({ parsedTitle, originalName }) => {
|
||||||
if (!newTitle) return
|
if (!parsedTitle) return
|
||||||
|
|
||||||
setSkipDebounce(true)
|
setSkipDebounce(true)
|
||||||
setTitle(newTitle)
|
setTitle(originalName)
|
||||||
|
setParsedTitle(parsedTitle)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [prevTorrentSourceState, selectedFile, torrentSource])
|
}, [prevTorrentSourceState, selectedFile, torrentSource])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if title exists and title was changed then search poster.
|
// if title exists and title was changed then search poster.
|
||||||
const titleChanged = title !== prevTitleState
|
const titleChanged = parsedTitle !== prevParsedTitleState
|
||||||
if (!titleChanged) return
|
if (!titleChanged) return
|
||||||
|
|
||||||
if (skipDebounce) {
|
if (skipDebounce) {
|
||||||
posterSearch(title, posterSearchLanguage)
|
posterSearch(parsedTitle, posterSearchLanguage)
|
||||||
setSkipDebounce(false)
|
setSkipDebounce(false)
|
||||||
} else {
|
} else {
|
||||||
title === '' ? removePoster() : delayedPosterSearch(title, posterSearchLanguage)
|
parsedTitle === '' ? removePoster() : delayedPosterSearch(parsedTitle, posterSearchLanguage)
|
||||||
}
|
}
|
||||||
}, [title, prevTitleState, delayedPosterSearch, posterSearch, posterSearchLanguage, skipDebounce])
|
}, [parsedTitle, prevParsedTitleState, delayedPosterSearch, posterSearch, posterSearchLanguage, skipDebounce])
|
||||||
|
|
||||||
const removePoster = () => {
|
const removePoster = () => {
|
||||||
setIsPosterUrlCorrect(false)
|
setIsPosterUrlCorrect(false)
|
||||||
@@ -128,6 +130,7 @@ export default function AddDialog({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedFile && !torrentSource) {
|
if (!selectedFile && !torrentSource) {
|
||||||
setTitle('')
|
setTitle('')
|
||||||
|
setParsedTitle('')
|
||||||
setPosterList()
|
setPosterList()
|
||||||
removePoster()
|
removePoster()
|
||||||
setIsUserInteractedWithPoster(false)
|
setIsUserInteractedWithPoster(false)
|
||||||
@@ -186,12 +189,14 @@ export default function AddDialog({
|
|||||||
|
|
||||||
<RightSideComponent
|
<RightSideComponent
|
||||||
setTitle={setTitle}
|
setTitle={setTitle}
|
||||||
|
setParsedTitle={setParsedTitle}
|
||||||
setPosterUrl={setPosterUrl}
|
setPosterUrl={setPosterUrl}
|
||||||
setIsPosterUrlCorrect={setIsPosterUrlCorrect}
|
setIsPosterUrlCorrect={setIsPosterUrlCorrect}
|
||||||
setIsUserInteractedWithPoster={setIsUserInteractedWithPoster}
|
setIsUserInteractedWithPoster={setIsUserInteractedWithPoster}
|
||||||
setPosterList={setPosterList}
|
setPosterList={setPosterList}
|
||||||
isTorrentSourceCorrect={isTorrentSourceCorrect}
|
isTorrentSourceCorrect={isTorrentSourceCorrect}
|
||||||
title={title}
|
title={title}
|
||||||
|
parsedTitle={parsedTitle}
|
||||||
posterUrl={posterUrl}
|
posterUrl={posterUrl}
|
||||||
isPosterUrlCorrect={isPosterUrlCorrect}
|
isPosterUrlCorrect={isPosterUrlCorrect}
|
||||||
posterList={posterList}
|
posterList={posterList}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { NoImageIcon } from 'icons'
|
import { NoImageIcon } from 'icons'
|
||||||
import { TextField } from '@material-ui/core'
|
import { IconButton, InputAdornment, TextField } from '@material-ui/core'
|
||||||
|
import { HighlightOff as HighlightOffIcon } from '@material-ui/icons'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ClearPosterButton,
|
ClearPosterButton,
|
||||||
@@ -12,16 +13,18 @@ import {
|
|||||||
PosterWrapper,
|
PosterWrapper,
|
||||||
RightSideContainer,
|
RightSideContainer,
|
||||||
} from './style'
|
} from './style'
|
||||||
import { checkImageURL } from './helpers'
|
import { checkImageURL, hashRegex } from './helpers'
|
||||||
|
|
||||||
export default function RightSideComponent({
|
export default function RightSideComponent({
|
||||||
setTitle,
|
setTitle,
|
||||||
|
setParsedTitle,
|
||||||
setPosterUrl,
|
setPosterUrl,
|
||||||
setIsPosterUrlCorrect,
|
setIsPosterUrlCorrect,
|
||||||
setIsUserInteractedWithPoster,
|
setIsUserInteractedWithPoster,
|
||||||
setPosterList,
|
setPosterList,
|
||||||
isTorrentSourceCorrect,
|
isTorrentSourceCorrect,
|
||||||
title,
|
title,
|
||||||
|
parsedTitle,
|
||||||
posterUrl,
|
posterUrl,
|
||||||
isPosterUrlCorrect,
|
isPosterUrlCorrect,
|
||||||
posterList,
|
posterList,
|
||||||
@@ -34,7 +37,10 @@ export default function RightSideComponent({
|
|||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const handleTitleChange = ({ target: { value } }) => setTitle(value)
|
const handleTitleChange = ({ target: { value } }) => {
|
||||||
|
setTitle(value)
|
||||||
|
setParsedTitle(value)
|
||||||
|
}
|
||||||
const handlePosterUrlChange = ({ target: { value } }) => {
|
const handlePosterUrlChange = ({ target: { value } }) => {
|
||||||
setPosterUrl(value)
|
setPosterUrl(value)
|
||||||
checkImageURL(value).then(setIsPosterUrlCorrect)
|
checkImageURL(value).then(setIsPosterUrlCorrect)
|
||||||
@@ -47,10 +53,35 @@ export default function RightSideComponent({
|
|||||||
setIsUserInteractedWithPoster(true)
|
setIsUserInteractedWithPoster(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sourceIsHash = torrentSource.match(hashRegex) !== null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RightSide>
|
<RightSide>
|
||||||
<RightSideContainer isHidden={!isTorrentSourceCorrect}>
|
<RightSideContainer isHidden={!isTorrentSourceCorrect}>
|
||||||
<TextField onChange={handleTitleChange} value={title} margin='dense' label={t('Title')} type='text' fullWidth />
|
<TextField
|
||||||
|
onChange={handleTitleChange}
|
||||||
|
value={title}
|
||||||
|
margin='dense'
|
||||||
|
label={t(sourceIsHash ? 'AddDialogTorrentTitle' : 'Title')}
|
||||||
|
type='text'
|
||||||
|
fullWidth
|
||||||
|
InputProps={{
|
||||||
|
endAdornment:
|
||||||
|
title === '' ? null : (
|
||||||
|
<InputAdornment position='end'>
|
||||||
|
<IconButton
|
||||||
|
aria-label='clear input'
|
||||||
|
onClick={() => {
|
||||||
|
setTitle('')
|
||||||
|
setParsedTitle('')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HighlightOffIcon />
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
onChange={handlePosterUrlChange}
|
onChange={handlePosterUrlChange}
|
||||||
value={posterUrl}
|
value={posterUrl}
|
||||||
@@ -81,7 +112,7 @@ export default function RightSideComponent({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newLanguage = posterSearchLanguage === 'en' ? 'ru' : 'en'
|
const newLanguage = posterSearchLanguage === 'en' ? 'ru' : 'en'
|
||||||
setPosterSearchLanguage(newLanguage)
|
setPosterSearchLanguage(newLanguage)
|
||||||
posterSearch(title, newLanguage, { shouldRefreshMainPoster: true })
|
posterSearch(parsedTitle, newLanguage, { shouldRefreshMainPoster: true })
|
||||||
}}
|
}}
|
||||||
showbutton={+isPosterUrlCorrect}
|
showbutton={+isPosterUrlCorrect}
|
||||||
color='primary'
|
color='primary'
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ export const checkImageURL = async url => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const magnetRegex = /^magnet:\?xt=urn:[a-z0-9].*/i
|
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
|
export 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
|
const torrentRegex = /^.*\.(torrent)$/i
|
||||||
export const chechTorrentSource = source =>
|
export const chechTorrentSource = source =>
|
||||||
source.match(hashRegex) !== null || source.match(magnetRegex) !== null || source.match(torrentRegex) !== null
|
source.match(hashRegex) !== null || source.match(magnetRegex) !== null || source.match(torrentRegex) !== null
|
||||||
|
|
||||||
export const parseTorrentTitle = (parsingSource, callback) => {
|
export const parseTorrentTitle = (parsingSource, callback) => {
|
||||||
parseTorrent.remote(parsingSource, (err, { name, files } = {}) => {
|
parseTorrent.remote(parsingSource, (err, { name, files } = {}) => {
|
||||||
if (!name || err) return callback(null)
|
if (!name || err) return callback({ parsedTitle: null, originalName: null })
|
||||||
|
|
||||||
const torrentName = ptt.parse(name).title
|
const torrentName = ptt.parse(name).title
|
||||||
const nameOfFileInsideTorrent = files ? ptt.parse(files[0].name).title : null
|
const nameOfFileInsideTorrent = files ? ptt.parse(files[0].name).title : null
|
||||||
@@ -50,6 +50,6 @@ export const parseTorrentTitle = (parsingSource, callback) => {
|
|||||||
newTitle = torrentName.length < nameOfFileInsideTorrent.length ? torrentName : nameOfFileInsideTorrent
|
newTitle = torrentName.length < nameOfFileInsideTorrent.length ? torrentName : nameOfFileInsideTorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(newTitle)
|
callback({ parsedTitle: newTitle, originalName: name })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"About": "About",
|
"About": "About",
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
"Add": "Add",
|
"Add": "Add",
|
||||||
|
"AddDialogTorrentTitle": "Title (empty for default torrent name)",
|
||||||
"AddFromLink": "Add from Link",
|
"AddFromLink": "Add from Link",
|
||||||
"AddNewTorrent": "Add new torrent",
|
"AddNewTorrent": "Add new torrent",
|
||||||
"AddPosterLinkInput": "Poster link",
|
"AddPosterLinkInput": "Poster link",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"About": "О сервере",
|
"About": "О сервере",
|
||||||
"Actions": "Действия",
|
"Actions": "Действия",
|
||||||
"Add": "Добавить",
|
"Add": "Добавить",
|
||||||
|
"AddDialogTorrentTitle": "Имя (пустой для имени из торрента)",
|
||||||
"AddFromLink": "Добавить",
|
"AddFromLink": "Добавить",
|
||||||
"AddNewTorrent": "Добавить новый торрент",
|
"AddNewTorrent": "Добавить новый торрент",
|
||||||
"AddPosterLinkInput": "Ссылка на постер",
|
"AddPosterLinkInput": "Ссылка на постер",
|
||||||
|
|||||||
Reference in New Issue
Block a user