import { useEffect, useRef, 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 { cacheHost } from 'utils/Hosts' import { Stage, Layer } from 'react-konva' import Measure from 'react-measure' import SingleBlock from './SingleBlock' export default function DialogCacheInfo({ hash }) { const [cache, setCache] = useState({}) const [pMap, setPMap] = useState([]) const timerID = useRef(null) const componentIsMounted = useRef(true) const [dimensions, setDimensions] = useState({ width: -1, height: -1 }) const [stageSettings, setStageSettings] = useState({ boxHeight: null, strokeWidth: null, marginBetweenBlocks: null, stageOffset: null, }) const [isShortView, setIsShortView] = useState(true) const [isLoading, setIsLoading] = useState(true) const updateStageSettings = (boxHeight, strokeWidth) => { setStageSettings({ boxHeight, strokeWidth, marginBetweenBlocks: strokeWidth, stageOffset: strokeWidth * 2, }) } const { boxHeight, strokeWidth, marginBetweenBlocks, stageOffset } = stageSettings let activeId = null useEffect(() => { // initializing stageSettings updateStageSettings(24, 4) return () => { // this function is required to notify "getCache" when NOT to make state update componentIsMounted.current = false } }, []) useEffect(() => { if (hash) { timerID.current = setInterval(() => { getCache(hash, value => { // this is required to avoid memory leak if (componentIsMounted.current) setCache(value) }) }, 100) } else clearInterval(timerID.current) return () => { clearInterval(timerID.current) } }, [hash]) useEffect(() => { if (!cache?.PiecesCount || !cache?.Pieces) return const { Pieces, PiecesCount, Readers } = cache const map = [] for (let i = 0; i < PiecesCount; i++) { const newPiece = { id: i } const currentPiece = Pieces[i] if (currentPiece) { if (currentPiece.Completed && currentPiece.Size === currentPiece.Length) newPiece.isComplete = true else { newPiece.inProgress = true newPiece.percentage = (currentPiece.Size / currentPiece.Length).toFixed(2) } } Readers.forEach(r => { if (i === r.Reader) newPiece.isActive = true if (i >= r.Start && i <= r.End) newPiece.isReaderRange = true }) map.push(newPiece) } setPMap(map) setIsLoading(false) }, [cache]) 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 : pMap.length) / piecesInOneRow) return ( setDimensions(contentRect.bounds)}> {({ measureRef }) => (
Hash {cache.Hash}
Capacity {humanizeSize(cache.Capacity)}
Filled {humanizeSize(cache.Filled)}
Torrent size {' '} {cache.Torrent && cache.Torrent.torrent_size && humanizeSize(cache.Torrent.torrent_size)}
Pieces length {humanizeSize(cache.PiecesLength)}
Pieces count {cache.PiecesCount}
Peers: {getPeerString(cache.Torrent)}
Download speed {' '} {cache.Torrent && cache.Torrent.download_speed ? `${humanizeSize(cache.Torrent.download_speed)}/sec` : ''}
Upload speed {' '} {cache.Torrent && cache.Torrent.upload_speed ? `${humanizeSize(cache.Torrent.upload_speed)}/sec` : ''}
Status {cache.Torrent && cache.Torrent.stat_string && cache.Torrent.stat_string}
{isLoading ? ( 'loading' ) : ( {pMap.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 && ( ) ) : ( ) })} )}
)}
) } const getCache = (hash, callback) => { try { fetch(cacheHost(), { method: 'post', body: JSON.stringify({ action: 'get', hash }), headers: { Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json', }, }) .then(res => res.json()) .then(callback, error => { callback({}) console.error(error) }) } catch (e) { console.error(e) callback({}) } } /* { "Hash": "41e36c8de915d80db83fc134bee4e7e2d292657e", "Capacity": 209715200, "Filled": 2914808, "PiecesLength": 4194304, "PiecesCount": 2065, "DownloadSpeed": 32770.860273455524, "Pieces": { "2064": { "Id": 2064, "Length": 2914808, "Size": 162296, "Completed": false } } } */