diff --git a/web/src/components/DialogTorrentDetailsContent/index.jsx b/web/src/components/DialogTorrentDetailsContent/index.jsx index 675365e..808cac7 100644 --- a/web/src/components/DialogTorrentDetailsContent/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/index.jsx @@ -1,13 +1,18 @@ -import styled, { css } from 'styled-components' import { NoImageIcon } from 'icons' import { getPeerString, humanizeSize } from 'utils/Utils' -// import { viewedHost } from 'utils/Hosts' import { CopyToClipboard } from 'react-copy-to-clipboard' import { useEffect, useState } from 'react' -import { Button } from '@material-ui/core' -import { ArrowDownward, ArrowUpward, SwapVerticalCircle, ViewAgenda } from '@material-ui/icons' +import { Button, ButtonGroup, Typography } from '@material-ui/core' +import { + ArrowDownward as ArrowDownwardIcon, + ArrowUpward as ArrowUpwardIcon, + SwapVerticalCircle as SwapVerticalCircleIcon, + ViewAgenda as ViewAgendaIcon, + Cached as CachedIcon, +} from '@material-ui/icons' import axios from 'axios' -import { torrentsHost } from 'utils/Hosts' +import { streamHost, torrentsHost, viewedHost } from 'utils/Hosts' +import { GETTING_INFO, IN_DB } from 'torrentStates' import { useUpdateCache, useCreateCacheMap, useGetSettings } from './customHooks' import DialogHeader from './DialogHeader' @@ -35,32 +40,56 @@ const shortenText = (text, count) => text.slice(0, count) + (text.length > count export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { const [isLoading, setIsLoading] = useState(true) const [isDetailedCacheView, setIsDetailedCacheView] = useState(false) + const [viewedFileList, setViewedFileList] = useState() + const [playableFileList, setPlayableFileList] = useState() + const { poster, hash, title, name, + stat, download_speed: downloadSpeed, upload_speed: uploadSpeed, stat_string: statString, torrent_size: torrentSize, + file_stats: torrentFileList, } = torrent const cache = useUpdateCache(hash) const cacheMap = useCreateCacheMap(cache) const settings = useGetSettings(cache) - const dropTorrent = hash => axios.post(torrentsHost(), { action: 'drop', hash }) + const dropTorrent = () => axios.post(torrentsHost(), { action: 'drop', hash }) + const removeTorrentViews = () => + axios.post(viewedHost(), { action: 'rem', hash, file_index: -1 }).then(() => setViewedFileList()) + const preloadBuffer = fileId => fetch(`${streamHost()}?link=${hash}&index=${fileId}&preload`) + const getFileLink = (path, id) => + `${streamHost()}/${encodeURIComponent(path.split('\\').pop().split('/').pop())}?link=${hash}&index=${id}&play` const { Capacity, PiecesCount, PiecesLength, Filled } = cache + useEffect(() => { + setPlayableFileList(torrentFileList?.filter(file => playableExtList.includes(getExt(file.path)))) + }, [torrentFileList]) + useEffect(() => { const cacheLoaded = !!Object.entries(cache).length - const torrentLoaded = torrent.stat_string !== 'Torrent in db' && torrent.stat_string !== 'Torrent getting info' + const torrentLoaded = stat !== GETTING_INFO && stat !== IN_DB if (!cacheLoaded && !isLoading) setIsLoading(true) if (cacheLoaded && isLoading && torrentLoaded) setIsLoading(false) - }, [torrent, cache, isLoading]) + }, [stat, cache, isLoading]) + + useEffect(() => { + // getting viewed file list + axios.post(viewedHost(), { action: 'list', hash }).then(({ data }) => { + if (data) { + const lst = data.map(itm => itm.file_index) + setViewedFileList(lst) + } else setViewedFileList() + }) + }, [hash]) const bufferSize = settings?.PreloadBuffer ? Capacity : 33554432 // Default is 32mb if PreloadBuffer is false @@ -105,7 +134,7 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { value={humanizeSize(downloadSpeed) || '0 B'} iconBg='#118f00' valueBg='#13a300' - icon={ArrowDownward} + icon={ArrowDownwardIcon} /> @@ -141,7 +170,11 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { {!settings?.PreloadBuffer && ( Enable "Preload Buffer" in settings to change buffer size )} - + @@ -166,9 +199,9 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { - remove views + removeTorrentViews()}>remove views - dropTorrent(hash)}>drop torrent + dropTorrent()}>drop torrent download playlist @@ -177,6 +210,26 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { Torrent Content + + {!playableFileList?.length + ? 'No playable files in this torrent' + : playableFileList.map(({ id, path, length }) => ( + + + + + + ))} )} @@ -184,117 +237,68 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) { ) } -// function getPreload(torrent) { -// if (torrent.preloaded_bytes > 0 && torrent.preload_size > 0 && torrent.preloaded_bytes < torrent.preload_size) { -// const progress = ((torrent.preloaded_bytes * 100) / torrent.preload_size).toFixed(2) -// return `${humanizeSize(torrent.preloaded_bytes)} / ${humanizeSize(torrent.preload_size)} ${progress}%` -// } - -// if (!torrent.preloaded_bytes) return humanizeSize(0) - -// return humanizeSize(torrent.preloaded_bytes) -// } - -// function remViews(hash) { -// try { -// if (hash) -// fetch(viewedHost(), { -// method: 'post', -// body: JSON.stringify({ action: 'rem', hash, file_index: -1 }), -// headers: { -// Accept: 'application/json, text/plain, */*', -// 'Content-Type': 'application/json', -// }, -// }) -// } catch (e) { -// console.error(e) -// } -// } - -// function getViewed(hash, callback) { -// try { -// fetch(viewedHost(), { -// method: 'post', -// body: JSON.stringify({ action: 'list', hash }), -// headers: { -// Accept: 'application/json, text/plain, */*', -// 'Content-Type': 'application/json', -// }, -// }) -// .then(res => res.json()) -// .then(callback) -// } catch (e) { -// console.error(e) -// } -// } - -// function getPlayableFile(torrent) { -// if (!torrent || !torrent.file_stats) return null -// return torrent.file_stats.filter(file => extPlayable.includes(getExt(file.path))) -// } - -// function getExt(filename) { -// const ext = filename.split('.').pop() -// if (ext === filename) return '' -// return ext.toLowerCase() -// } -// const extPlayable = [ -// // video -// '3g2', -// '3gp', -// 'aaf', -// 'asf', -// 'avchd', -// 'avi', -// 'drc', -// 'flv', -// 'iso', -// 'm2v', -// 'm2ts', -// 'm4p', -// 'm4v', -// 'mkv', -// 'mng', -// 'mov', -// 'mp2', -// 'mp4', -// 'mpe', -// 'mpeg', -// 'mpg', -// 'mpv', -// 'mxf', -// 'nsv', -// 'ogg', -// 'ogv', -// 'ts', -// 'qt', -// 'rm', -// 'rmvb', -// 'roq', -// 'svi', -// 'vob', -// 'webm', -// 'wmv', -// 'yuv', -// // audio -// 'aac', -// 'aiff', -// 'ape', -// 'au', -// 'flac', -// 'gsm', -// 'it', -// 'm3u', -// 'm4a', -// 'mid', -// 'mod', -// 'mp3', -// 'mpa', -// 'pls', -// 'ra', -// 's3m', -// 'sid', -// 'wav', -// 'wma', -// 'xm', -// ] +function getExt(filename) { + const ext = filename.split('.').pop() + if (ext === filename) return '' + return ext.toLowerCase() +} +const playableExtList = [ + // video + '3g2', + '3gp', + 'aaf', + 'asf', + 'avchd', + 'avi', + 'drc', + 'flv', + 'iso', + 'm2v', + 'm2ts', + 'm4p', + 'm4v', + 'mkv', + 'mng', + 'mov', + 'mp2', + 'mp4', + 'mpe', + 'mpeg', + 'mpg', + 'mpv', + 'mxf', + 'nsv', + 'ogg', + 'ogv', + 'ts', + 'qt', + 'rm', + 'rmvb', + 'roq', + 'svi', + 'vob', + 'webm', + 'wmv', + 'yuv', + // audio + 'aac', + 'aiff', + 'ape', + 'au', + 'flac', + 'gsm', + 'it', + 'm3u', + 'm4a', + 'mid', + 'mod', + 'mp3', + 'mpa', + 'pls', + 'ra', + 's3m', + 'sid', + 'wav', + 'wma', + 'xm', +] diff --git a/web/src/components/DialogTorrentDetailsContent/style.js b/web/src/components/DialogTorrentDetailsContent/style.js index 4716897..bdb94b0 100644 --- a/web/src/components/DialogTorrentDetailsContent/style.js +++ b/web/src/components/DialogTorrentDetailsContent/style.js @@ -166,14 +166,22 @@ export const StatisticsFieldValue = styled.div` `} ` -export const LoadingProgress = styled.div.attrs(({ value, fullAmount }) => ({ - percentage: Math.min(100, (value * 100) / fullAmount), -}))` - ${({ percentage, label }) => css` +export const LoadingProgress = styled.div.attrs(({ value, fullAmount }) => { + const percentage = (value * 100) / fullAmount + const percentageMinmax = Math.min(100, percentage) + // console.log(percentage) + const stylePercentage = percentageMinmax === 100 ? 100 : percentageMinmax % 100 + + return { + style: { + background: `linear-gradient(to right, #b5dec9 0%, #b5dec9 ${stylePercentage}%, #fff ${stylePercentage}%, #fff 100%)`, + }, + } +})` + ${({ label }) => css` border: 1px solid; padding: 10px 20px; border-radius: 5px; - background: linear-gradient(to right, #b5dec9 0%, #b5dec9 ${percentage}%, #fff ${percentage}%, #fff 100%); :before { content: '${label}'; diff --git a/web/src/torrentStates.js b/web/src/torrentStates.js new file mode 100644 index 0000000..a2cef45 --- /dev/null +++ b/web/src/torrentStates.js @@ -0,0 +1 @@ +export const [GETTING_INFO, PRELOAD, WORKING, CLOSED, IN_DB] = [1, 2, 3, 4, 5]