import Measure from 'react-measure' import { useState, memo, useRef, useEffect } from 'react' import { useTranslation } from 'react-i18next' import isEqual from 'lodash/isEqual' import { useCreateCacheMap } from '../customHooks' import getShortCacheMap from './getShortCacheMap' import { SnakeWrapper, ScrollNotification } from './style' import { defaultBorderWidth, miniCacheMaxHeight, pieceSizeForMiniMap, defaultPieceSize, defaultBackgroundColor, defaultBorderColor, completeColor, activeColor, rangeColor, defaultGapBetweenPieces, miniBackgroundColor, miniBorderWidth, miniGapBetweenPieces, createGradient, } from './snakeSettings' const TorrentCache = ({ cache, isMini }) => { const { t } = useTranslation() const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) const { width } = dimensions const canvasRef = useRef(null) const ctxRef = useRef(null) const cacheMap = useCreateCacheMap(cache) const canvasWidth = isMini ? width * 0.93 : width const pieceSize = isMini ? pieceSizeForMiniMap : defaultPieceSize const gapBetweenPieces = isMini ? miniGapBetweenPieces : defaultGapBetweenPieces const pieceSizeWithGap = pieceSize + gapBetweenPieces const piecesInOneRow = Math.floor(canvasWidth / pieceSizeWithGap) let shotCacheMap if (isMini) { const preloadPiecesAmount = Math.round(cache.Capacity / cache.PiecesLength - 1) shotCacheMap = getShortCacheMap({ cacheMap, preloadPiecesAmount, piecesInOneRow }) } const source = isMini ? shotCacheMap : cacheMap const startingXPoint = Math.ceil((canvasWidth - pieceSizeWithGap * piecesInOneRow) / 2) // needed to center grid const height = Math.ceil(source.length / piecesInOneRow) * pieceSizeWithGap useEffect(() => { if (!canvasWidth || !height) return const canvas = canvasRef.current canvas.width = canvasWidth canvas.height = height ctxRef.current = canvas.getContext('2d') }, [canvasRef, height, canvasWidth]) useEffect(() => { const ctx = ctxRef.current if (!ctx) return ctx.clearRect(0, 0, canvasWidth, height) source.forEach(({ percentage, isReader, isReaderRange }, i) => { const inProgress = percentage > 0 && percentage < 100 const isCompleted = percentage === 100 const currentRow = i % piecesInOneRow const currentColumn = Math.floor(i / piecesInOneRow) const borderWidth = isMini ? miniBorderWidth : defaultBorderWidth const fixBlurStroke = borderWidth % 2 === 0 ? 0 : 0.5 const requiredFix = Math.ceil(borderWidth / 2) + 1 + fixBlurStroke const x = currentRow * pieceSize + currentRow * gapBetweenPieces + startingXPoint + requiredFix const y = currentColumn * pieceSize + currentColumn * gapBetweenPieces + requiredFix ctx.lineWidth = borderWidth ctx.fillStyle = inProgress ? createGradient(ctx, percentage, pieceSize) : isCompleted ? completeColor : isMini ? miniBackgroundColor : defaultBackgroundColor ctx.strokeStyle = isReader ? activeColor : inProgress || isCompleted ? completeColor : isReaderRange ? rangeColor : defaultBorderColor ctx.translate(x, y) ctx.fillRect(0, 0, pieceSize, pieceSize) ctx.strokeRect(0, 0, pieceSize, pieceSize) ctx.setTransform(1, 0, 0, 1, 0, 0) }) }, [cacheMap, height, canvasWidth, piecesInOneRow, isMini, startingXPoint, pieceSize, gapBetweenPieces, source]) return ( setDimensions(bounds)}> {({ measureRef }) => (
{isMini && height >= miniCacheMaxHeight && {t('ScrollDown')}}
)}
) } export default memo( TorrentCache, (prev, next) => isEqual(prev.cache.Pieces, next.cache.Pieces) && isEqual(prev.cache.Readers, next.cache.Readers), )