From d1c25a92b4d8935076508e42b8510190a3aaa7b4 Mon Sep 17 00:00:00 2001 From: Daniel Shleifman Date: Tue, 15 Jun 2021 17:03:12 +0300 Subject: [PATCH] all snakes are div's now again --- web/package.json | 2 - .../TorrentCache/LargeSnake.jsx | 138 +++++++++++------- .../TorrentCache/getShortCacheMap.js | 8 +- .../TorrentCache/index.jsx | 10 +- .../customHooks.jsx | 26 ++-- web/yarn.lock | 20 +-- 6 files changed, 108 insertions(+), 96 deletions(-) diff --git a/web/package.json b/web/package.json index ce5efa6..d6ecd14 100644 --- a/web/package.json +++ b/web/package.json @@ -25,8 +25,6 @@ "react-measure": "^2.5.2", "react-query": "^3.17.0", "react-scripts": "4.0.3", - "react-virtualized-auto-sizer": "^1.0.5", - "react-window": "^1.8.6", "styled-components": "^5.3.0", "uuid": "^8.3.2" }, diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/LargeSnake.jsx b/web/src/components/DialogTorrentDetailsContent/TorrentCache/LargeSnake.jsx index 82e1d56..08e80e9 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/LargeSnake.jsx +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/LargeSnake.jsx @@ -1,59 +1,95 @@ -import { FixedSizeGrid as Grid } from 'react-window' -import AutoSizer from 'react-virtualized-auto-sizer' -import { memo } from 'react' +import styled, { css } from 'styled-components' +import Measure from 'react-measure' +import { useState } from 'react' +import { v4 as uuidv4 } from 'uuid' -import { getLargeSnakeColors } from './colors' +import { + defaultBackgroundColor, + defaultBorderColor, + progressColor, + completeColor, + activeColor, + rangeColor, +} from './colors' +import getShortCacheMap from './getShortCacheMap' -const Cell = memo(({ columnIndex, rowIndex, style, data }) => { - const { columnCount, cacheMap, gutterSize, borderSize, pieces } = data - const itemIndex = rowIndex * columnCount + columnIndex +const borderWidth = 1 +const defaultPieceSize = 14 +const pieceSizeForMiniMap = 23 +const gapBetweenPieces = 3 - const { borderColor, backgroundColor } = getLargeSnakeColors(cacheMap[itemIndex] || {}) +const SnakeWrapper = styled.div` + ${({ pieceSize, piecesInOneRow }) => css` + display: grid; + gap: ${gapBetweenPieces}px; + grid-template-columns: repeat(${piecesInOneRow || 'auto-fit'}, ${pieceSize}px); + grid-auto-rows: max-content; + justify-content: center; - const newStyle = { - ...style, - left: style.left + gutterSize, - top: style.top + gutterSize, - width: style.width - gutterSize, - height: style.height - gutterSize, - border: `${borderSize}px solid ${borderColor}`, - display: itemIndex >= pieces ? 'none' : null, - background: backgroundColor, + .piece { + width: ${pieceSize}px; + height: ${pieceSize}px; + background: ${defaultBackgroundColor}; + border: ${borderWidth}px solid ${defaultBorderColor}; + display: grid; + align-items: end; + + &-loading { + background: ${progressColor}; + border-color: ${progressColor}; + } + &-complete { + background: ${completeColor}; + border-color: ${completeColor}; + } + &-reader { + border-color: ${activeColor}; + } + } + + .reader-range { + border-color: ${rangeColor}; + } + `} +` + +const PercentagePiece = styled.div` + background: ${completeColor}; + height: ${({ percentage }) => (percentage / 100) * 12}px; +` + +export default function LargeSnake({ cacheMap, isMini, preloadPiecesAmount }) { + const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) + + const pieceSize = isMini ? pieceSizeForMiniMap : defaultPieceSize + + let piecesInOneRow + let shotCacheMap + if (isMini) { + const pieceSizeWithGap = pieceSize + gapBetweenPieces + piecesInOneRow = Math.floor(dimensions.width / pieceSizeWithGap) + shotCacheMap = isMini && getShortCacheMap({ cacheMap, preloadPiecesAmount, piecesInOneRow }) } - return
-}) - -const gutterSize = 2 -const borderSize = 1 -const pieceSize = 12 -const pieceSizeWithSpacing = pieceSize + gutterSize - -export default function LargeSnake({ cacheMap }) { - const pieces = cacheMap.length - - return ( -
- - {({ height, width }) => { - const columnCount = Math.floor(width / (gutterSize + pieceSize)) - 1 - const rowCount = pieces / columnCount + 1 - - return ( - - {Cell} - - ) - }} - -
+ return isMini ? ( + setDimensions(bounds)}> + {({ measureRef }) => ( + + {shotCacheMap.map(({ className, id, percentage }) => ( + + {percentage > 0 && percentage <= 100 && } + + ))} + + )} + + ) : ( + + {cacheMap.map(({ className, id, percentage }) => ( + + {percentage > 0 && percentage <= 100 && } + + ))} + ) } diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/getShortCacheMap.js b/web/src/components/DialogTorrentDetailsContent/TorrentCache/getShortCacheMap.js index 729c643..9aed090 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/getShortCacheMap.js +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/getShortCacheMap.js @@ -1,5 +1,7 @@ export default ({ cacheMap, preloadPiecesAmount, piecesInOneRow }) => { - const cacheMapWithoutEmptyBlocks = cacheMap.filter(({ isComplete, inProgress }) => inProgress || isComplete) + const cacheMapWithoutEmptyBlocks = cacheMap.filter( + ({ className }) => className.includes('piece-complete') || className.includes('piece-loading'), + ) const getFullAmountOfBlocks = amountOfBlocks => // this function counts existed amount of blocks with extra "empty blocks" to fill the row till the end @@ -21,7 +23,9 @@ export default ({ cacheMap, preloadPiecesAmount, piecesInOneRow }) => { const extraBlocksAmount = finalAmountOfBlocksToRenderInShortView - cacheMapWithoutEmptyBlocks.length + 1 // amount of blocks needed to fill the line till the end - const extraEmptyBlocksForFillingLine = extraBlocksAmount ? new Array(extraBlocksAmount).fill({}) : [] + const extraEmptyBlocksForFillingLine = extraBlocksAmount + ? new Array(extraBlocksAmount).fill({ className: 'piece' }) + : [] return [...cacheMapWithoutEmptyBlocks, ...extraEmptyBlocksForFillingLine] } diff --git a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx index 10c75fd..0c70c18 100644 --- a/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx +++ b/web/src/components/DialogTorrentDetailsContent/TorrentCache/index.jsx @@ -3,22 +3,14 @@ import isEqual from 'lodash/isEqual' import { useCreateCacheMap } from '../customHooks' import LargeSnake from './LargeSnake' -import DefaultSnake from './DefaultSnake' const TorrentCache = memo( ({ cache, isMini }) => { const cacheMap = useCreateCacheMap(cache) const preloadPiecesAmount = Math.round(cache.Capacity / cache.PiecesLength - 1) - const isSnakeLarge = cacheMap.length > 1000 - return isMini ? ( - - ) : isSnakeLarge ? ( - - ) : ( - - ) + return }, (prev, next) => isEqual(prev.cache.Pieces, next.cache.Pieces) && isEqual(prev.cache.Readers, next.cache.Readers), ) diff --git a/web/src/components/DialogTorrentDetailsContent/customHooks.jsx b/web/src/components/DialogTorrentDetailsContent/customHooks.jsx index 5eeed67..6c50096 100644 --- a/web/src/components/DialogTorrentDetailsContent/customHooks.jsx +++ b/web/src/components/DialogTorrentDetailsContent/customHooks.jsx @@ -38,32 +38,32 @@ export const useCreateCacheMap = cache => { const [cacheMap, setCacheMap] = useState([]) useEffect(() => { - if (!cache.PiecesCount || !cache.Pieces) return - - const { Pieces, PiecesCount, Readers } = cache + const { PiecesCount, Pieces, 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) - } + const activeBlock = Pieces[i] + const className = ['piece'] + + if (activeBlock) { + const { Completed, Size, Length } = activeBlock + className.push(Completed && Size >= Length ? 'piece-complete' : 'piece-loading') + newPiece.percentage = ((Size / Length) * 100).toFixed(2) } Readers.forEach(r => { - if (i === r.Reader) newPiece.isActive = true - if (i >= r.Start && i <= r.End) newPiece.isReaderRange = true + if (i === r.Reader) { + className.push('piece-reader') + } else if (i >= r.Start && i <= r.End) className.push('reader-range') }) + newPiece.className = className.join(' ') + map.push(newPiece) } - setCacheMap(map) }, [cache]) diff --git a/web/yarn.lock b/web/yarn.lock index 4e7b69f..96fd161 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1174,7 +1174,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.14.0", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.14.0", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.14.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== @@ -8306,11 +8306,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -"memoize-one@>=3.1.1 <6": - version "5.2.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" - integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== - memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -10594,19 +10589,6 @@ react-transition-group@^4.4.0: loose-envify "^1.4.0" prop-types "^15.6.2" -react-virtualized-auto-sizer@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.5.tgz#9eeeb8302022de56fbd7a860b08513120ce36509" - integrity sha512-kivjYVWX15TX2IUrm8F1jaCEX8EXrpy3DD+u41WGqJ1ZqbljWpiwscV+VxOM1l7sSIM1jwi2LADjhhAJkJ9dxA== - -react-window@^1.8.6: - version "1.8.6" - resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112" - integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg== - dependencies: - "@babel/runtime" "^7.0.0" - memoize-one ">=3.1.1 <6" - react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"