mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
added more widgets
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
import { Rect } from 'react-konva'
|
||||
|
||||
export default function SingleBlock({
|
||||
x,
|
||||
y,
|
||||
percentage,
|
||||
isActive = false,
|
||||
inProgress = false,
|
||||
isReaderRange = false,
|
||||
isComplete = false,
|
||||
boxHeight,
|
||||
strokeWidth,
|
||||
}) {
|
||||
const strokeColor = isActive
|
||||
? '#000'
|
||||
: isComplete
|
||||
? '#3fb57a'
|
||||
: inProgress
|
||||
? '#00d0d0'
|
||||
: isReaderRange
|
||||
? '#9a9aff'
|
||||
: '#eef2f4'
|
||||
const backgroundColor = inProgress ? '#00d0d0' : '#eef2f4'
|
||||
const percentageProgressColor = '#3fb57a'
|
||||
const processCompletedColor = '#3fb57a'
|
||||
|
||||
return (
|
||||
<Rect
|
||||
x={x}
|
||||
y={y}
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
height={boxHeight}
|
||||
width={boxHeight}
|
||||
fillAfterStrokeEnabled
|
||||
preventDefault={false}
|
||||
{...(isComplete
|
||||
? { fill: processCompletedColor }
|
||||
: inProgress && {
|
||||
fillLinearGradientStartPointY: boxHeight,
|
||||
fillLinearGradientEndPointY: 0,
|
||||
fillLinearGradientColorStops: [
|
||||
0,
|
||||
percentageProgressColor,
|
||||
percentage,
|
||||
percentageProgressColor,
|
||||
percentage,
|
||||
backgroundColor,
|
||||
],
|
||||
})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import Typography from '@material-ui/core/Typography'
|
||||
import DialogTitle from '@material-ui/core/DialogTitle'
|
||||
import DialogContent from '@material-ui/core/DialogContent'
|
||||
import { getPeerString, humanizeSize } from 'utils/Utils'
|
||||
import { Stage, Layer } from 'react-konva'
|
||||
import Measure from 'react-measure'
|
||||
import { useUpdateCache, useCreateCacheMap } from 'components/DialogTorrentDetailsContent/customHooks'
|
||||
|
||||
import SingleBlock from './SingleBlock'
|
||||
|
||||
export default function DialogCacheInfo({ hash }) {
|
||||
const [dimensions, setDimensions] = useState({ width: -1, height: -1 })
|
||||
const [isShortView, setIsShortView] = useState(true)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [stageSettings, setStageSettings] = useState({
|
||||
boxHeight: null,
|
||||
strokeWidth: null,
|
||||
marginBetweenBlocks: null,
|
||||
stageOffset: null,
|
||||
})
|
||||
|
||||
const cache = useUpdateCache(hash)
|
||||
const cacheMap = useCreateCacheMap(cache, () => setIsLoading(false))
|
||||
|
||||
const updateStageSettings = (boxHeight, strokeWidth) => {
|
||||
setStageSettings({
|
||||
boxHeight,
|
||||
strokeWidth,
|
||||
marginBetweenBlocks: strokeWidth,
|
||||
stageOffset: strokeWidth * 2,
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// initializing stageSettings
|
||||
updateStageSettings(24, 4)
|
||||
}, [])
|
||||
|
||||
const { boxHeight, strokeWidth, marginBetweenBlocks, stageOffset } = stageSettings
|
||||
|
||||
const preloadPiecesAmount = Math.round(cache.Capacity / cache.PiecesLength - 1)
|
||||
const blockSizeWithMargin = boxHeight + strokeWidth + marginBetweenBlocks
|
||||
const piecesInOneRow = Math.floor((dimensions.width * 0.9) / blockSizeWithMargin)
|
||||
const amountOfBlocksToRenderInShortView =
|
||||
preloadPiecesAmount === piecesInOneRow
|
||||
? preloadPiecesAmount - 1
|
||||
: preloadPiecesAmount + piecesInOneRow - (preloadPiecesAmount % piecesInOneRow) - 1
|
||||
const amountOfRows = Math.ceil((isShortView ? amountOfBlocksToRenderInShortView : cacheMap.length) / piecesInOneRow)
|
||||
let activeId = null
|
||||
|
||||
return (
|
||||
<Measure bounds onResize={contentRect => setDimensions(contentRect.bounds)}>
|
||||
{({ measureRef }) => (
|
||||
<div ref={measureRef}>
|
||||
<DialogTitle id='form-dialog-title'>
|
||||
<Typography>
|
||||
<b>Hash </b> <span style={{ wordBreak: 'break-word' }}>{cache.Hash}</span>
|
||||
<br />
|
||||
<b>Capacity </b> {humanizeSize(cache.Capacity)}
|
||||
<br />
|
||||
<b>Filled </b> {humanizeSize(cache.Filled)}
|
||||
<br />
|
||||
<b>Torrent size </b>{' '}
|
||||
{cache.Torrent && cache.Torrent.torrent_size && humanizeSize(cache.Torrent.torrent_size)}
|
||||
<br />
|
||||
<b>Pieces length </b> {humanizeSize(cache.PiecesLength)}
|
||||
<br />
|
||||
<b>Pieces count </b> {cache.PiecesCount}
|
||||
<br />
|
||||
<b>Peers: </b> {getPeerString(cache.Torrent)}
|
||||
<br />
|
||||
<b>Download speed </b>{' '}
|
||||
{cache.Torrent && cache.Torrent.download_speed ? `${humanizeSize(cache.Torrent.download_speed)}/sec` : ''}
|
||||
<br />
|
||||
<b>Upload speed </b>{' '}
|
||||
{cache.Torrent && cache.Torrent.upload_speed ? `${humanizeSize(cache.Torrent.upload_speed)}/sec` : ''}
|
||||
<br />
|
||||
<b>Status </b> {cache.Torrent && cache.Torrent.stat_string && cache.Torrent.stat_string}
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<button
|
||||
type='button'
|
||||
onClick={() => {
|
||||
if (isShortView) {
|
||||
updateStageSettings(12, 2)
|
||||
setIsShortView(false)
|
||||
} else {
|
||||
updateStageSettings(24, 4)
|
||||
setIsShortView(true)
|
||||
}
|
||||
setIsLoading(true)
|
||||
}}
|
||||
>
|
||||
updateStageSettings
|
||||
</button>
|
||||
{isLoading ? (
|
||||
'loading'
|
||||
) : (
|
||||
<Stage
|
||||
style={{ display: 'flex', justifyContent: 'center' }}
|
||||
offset={{ x: -stageOffset, y: -stageOffset }}
|
||||
width={stageOffset + blockSizeWithMargin * piecesInOneRow}
|
||||
height={stageOffset + blockSizeWithMargin * amountOfRows}
|
||||
>
|
||||
<Layer>
|
||||
{cacheMap.map(({ id, percentage, isComplete, inProgress, isActive, isReaderRange }) => {
|
||||
const currentRow = Math.floor((isShortView ? id - activeId : id) / piecesInOneRow)
|
||||
|
||||
// -------- related only for short view -------
|
||||
if (isActive) activeId = id
|
||||
const shouldBeRendered =
|
||||
isActive || (id - activeId <= amountOfBlocksToRenderInShortView && id - activeId >= 0)
|
||||
// --------------------------------------------
|
||||
|
||||
return isShortView ? (
|
||||
shouldBeRendered && (
|
||||
<SingleBlock
|
||||
key={id}
|
||||
x={((id - activeId) % piecesInOneRow) * blockSizeWithMargin}
|
||||
y={currentRow * blockSizeWithMargin}
|
||||
percentage={percentage}
|
||||
inProgress={inProgress}
|
||||
isComplete={isComplete}
|
||||
isReaderRange={isReaderRange}
|
||||
isActive={isActive}
|
||||
boxHeight={boxHeight}
|
||||
strokeWidth={strokeWidth}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<SingleBlock
|
||||
key={id}
|
||||
x={(id % piecesInOneRow) * blockSizeWithMargin}
|
||||
y={currentRow * blockSizeWithMargin}
|
||||
percentage={percentage}
|
||||
inProgress={inProgress}
|
||||
isComplete={isComplete}
|
||||
isReaderRange={isReaderRange}
|
||||
isActive={isActive}
|
||||
boxHeight={boxHeight}
|
||||
strokeWidth={strokeWidth}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Layer>
|
||||
</Stage>
|
||||
)}
|
||||
</DialogContent>
|
||||
</div>
|
||||
)}
|
||||
</Measure>
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"Hash": "41e36c8de915d80db83fc134bee4e7e2d292657e",
|
||||
"Capacity": 209715200,
|
||||
"Filled": 2914808,
|
||||
"PiecesLength": 4194304,
|
||||
"PiecesCount": 2065,
|
||||
"DownloadSpeed": 32770.860273455524,
|
||||
"Pieces": {
|
||||
"2064": {
|
||||
"Id": 2064,
|
||||
"Length": 2914808,
|
||||
"Size": 162296,
|
||||
"Completed": false
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -9,6 +9,9 @@ import {
|
||||
ArrowUpward as ArrowUpwardIcon,
|
||||
SwapVerticalCircle as SwapVerticalCircleIcon,
|
||||
ViewAgenda as ViewAgendaIcon,
|
||||
Widgets as WidgetsIcon,
|
||||
PhotoSizeSelectSmall as PhotoSizeSelectSmallIcon,
|
||||
Build as BuildIcon,
|
||||
} from '@material-ui/icons'
|
||||
import axios from 'axios'
|
||||
import { playlistTorrHost, streamHost, torrentsHost, viewedHost } from 'utils/Hosts'
|
||||
@@ -117,9 +120,63 @@ export default function DialogTorrentDetailsContent({ closeDialog, torrent }) {
|
||||
'loading'
|
||||
) : isDetailedCacheView ? (
|
||||
<DetailedTorrentCacheViewWrapper>
|
||||
<div>PiecesCount: {PiecesCount}</div>
|
||||
<div>PiecesLength: {humanizeSize(PiecesLength)}</div>
|
||||
<div>status: {statString}</div>
|
||||
<StatisticsWrapper>
|
||||
<StatisticsField
|
||||
title='Download speed'
|
||||
value={humanizeSize(downloadSpeed) || '0 B'}
|
||||
iconBg='#118f00'
|
||||
valueBg='#13a300'
|
||||
icon={ArrowDownwardIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Upload speed'
|
||||
value={humanizeSize(uploadSpeed) || '0 B'}
|
||||
iconBg='#0146ad'
|
||||
valueBg='#0058db'
|
||||
icon={ArrowUpwardIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Peers'
|
||||
value={getPeerString(torrent)}
|
||||
iconBg='#cdc118'
|
||||
valueBg='#d8cb18'
|
||||
icon={SwapVerticalCircleIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Torrent size'
|
||||
value={humanizeSize(torrentSize)}
|
||||
iconBg='#01a292'
|
||||
valueBg='#01ad9b'
|
||||
icon={ViewAgendaIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Pieces count'
|
||||
value={PiecesCount}
|
||||
iconBg='#b6c95e'
|
||||
valueBg='#c0d076'
|
||||
icon={WidgetsIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Pieces length'
|
||||
value={humanizeSize(PiecesLength)}
|
||||
iconBg='#0982c8'
|
||||
valueBg='#098cd7'
|
||||
icon={PhotoSizeSelectSmallIcon}
|
||||
/>
|
||||
|
||||
<StatisticsField
|
||||
title='Torrent status'
|
||||
value={statString}
|
||||
iconBg='#aea25b'
|
||||
valueBg='#b4aa6e'
|
||||
icon={BuildIcon}
|
||||
/>
|
||||
</StatisticsWrapper>
|
||||
<TorrentCache cache={cache} cacheMap={cacheMap} />
|
||||
</DetailedTorrentCacheViewWrapper>
|
||||
) : (
|
||||
|
||||
@@ -91,20 +91,20 @@ export const SectionHeader = styled.div`
|
||||
`
|
||||
|
||||
export const DetailedTorrentCacheViewWrapper = styled.div`
|
||||
padding-top: 50px;
|
||||
padding: 40px;
|
||||
overflow: auto;
|
||||
min-height: 80vh;
|
||||
`
|
||||
|
||||
export const StatisticsWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(210px, min-content));
|
||||
grid-template-columns: repeat(auto-fit, minmax(max-content, 220px));
|
||||
gap: 20px;
|
||||
`
|
||||
|
||||
export const StatisticsFieldWrapper = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: 40px max-content;
|
||||
grid-template-columns: 40px 1fr;
|
||||
grid-template-rows: min-content 50px;
|
||||
grid-template-areas:
|
||||
'title title'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable camelcase */
|
||||
import 'fontsource-roboto'
|
||||
import { forwardRef, useState } from 'react'
|
||||
import HeightIcon from '@material-ui/icons/Height'
|
||||
@@ -38,7 +37,7 @@ export default function Torrent({ torrent }) {
|
||||
const openDeleteTorrentAlert = () => setIsDeleteTorrentOpened(true)
|
||||
const closeDeleteTorrentAlert = () => setIsDeleteTorrentOpened(false)
|
||||
|
||||
const { title, name, poster, torrent_size, download_speed, hash } = torrent
|
||||
const { title, name, poster, torrent_size: torrentSize, download_speed: downloadSpeed, hash } = torrent
|
||||
|
||||
const dropTorrent = () => axios.post(torrentsHost(), { action: 'drop', hash })
|
||||
const deleteTorrent = () => axios.post(torrentsHost(), { action: 'rem', hash })
|
||||
@@ -77,14 +76,14 @@ export default function Torrent({ torrent }) {
|
||||
<span>
|
||||
<TorrentCardDescriptionLabel>Size</TorrentCardDescriptionLabel>
|
||||
<TorrentCardDescriptionContent>
|
||||
{torrent_size > 0 && humanizeSize(torrent_size)}
|
||||
{torrentSize > 0 && humanizeSize(torrentSize)}
|
||||
</TorrentCardDescriptionContent>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<TorrentCardDescriptionLabel>Speed</TorrentCardDescriptionLabel>
|
||||
<TorrentCardDescriptionContent>
|
||||
{download_speed > 0 ? humanizeSize(download_speed) : '---'}
|
||||
{downloadSpeed > 0 ? humanizeSize(downloadSpeed) : '---'}
|
||||
</TorrentCardDescriptionContent>
|
||||
</span>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user