mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 21:46:11 +05:00
all snakes are div's now again
This commit is contained in:
@@ -25,8 +25,6 @@
|
|||||||
"react-measure": "^2.5.2",
|
"react-measure": "^2.5.2",
|
||||||
"react-query": "^3.17.0",
|
"react-query": "^3.17.0",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-virtualized-auto-sizer": "^1.0.5",
|
|
||||||
"react-window": "^1.8.6",
|
|
||||||
"styled-components": "^5.3.0",
|
"styled-components": "^5.3.0",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,59 +1,95 @@
|
|||||||
import { FixedSizeGrid as Grid } from 'react-window'
|
import styled, { css } from 'styled-components'
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer'
|
import Measure from 'react-measure'
|
||||||
import { memo } from 'react'
|
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 borderWidth = 1
|
||||||
const { columnCount, cacheMap, gutterSize, borderSize, pieces } = data
|
const defaultPieceSize = 14
|
||||||
const itemIndex = rowIndex * columnCount + columnIndex
|
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 = {
|
.piece {
|
||||||
...style,
|
width: ${pieceSize}px;
|
||||||
left: style.left + gutterSize,
|
height: ${pieceSize}px;
|
||||||
top: style.top + gutterSize,
|
background: ${defaultBackgroundColor};
|
||||||
width: style.width - gutterSize,
|
border: ${borderWidth}px solid ${defaultBorderColor};
|
||||||
height: style.height - gutterSize,
|
display: grid;
|
||||||
border: `${borderSize}px solid ${borderColor}`,
|
align-items: end;
|
||||||
display: itemIndex >= pieces ? 'none' : null,
|
|
||||||
background: backgroundColor,
|
&-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 <div style={newStyle} />
|
return isMini ? (
|
||||||
})
|
<Measure bounds onResize={({ bounds }) => setDimensions(bounds)}>
|
||||||
|
{({ measureRef }) => (
|
||||||
const gutterSize = 2
|
<SnakeWrapper ref={measureRef} pieceSize={pieceSize} piecesInOneRow={piecesInOneRow}>
|
||||||
const borderSize = 1
|
{shotCacheMap.map(({ className, id, percentage }) => (
|
||||||
const pieceSize = 12
|
<span key={id || uuidv4()} className={className}>
|
||||||
const pieceSizeWithSpacing = pieceSize + gutterSize
|
{percentage > 0 && percentage <= 100 && <PercentagePiece percentage={percentage} />}
|
||||||
|
</span>
|
||||||
export default function LargeSnake({ cacheMap }) {
|
))}
|
||||||
const pieces = cacheMap.length
|
</SnakeWrapper>
|
||||||
|
)}
|
||||||
return (
|
</Measure>
|
||||||
<div style={{ height: '60vh', overflow: 'hidden' }}>
|
) : (
|
||||||
<AutoSizer>
|
<SnakeWrapper pieceSize={pieceSize}>
|
||||||
{({ height, width }) => {
|
{cacheMap.map(({ className, id, percentage }) => (
|
||||||
const columnCount = Math.floor(width / (gutterSize + pieceSize)) - 1
|
<span key={id || uuidv4()} className={className}>
|
||||||
const rowCount = pieces / columnCount + 1
|
{percentage > 0 && percentage <= 100 && <PercentagePiece percentage={percentage} />}
|
||||||
|
</span>
|
||||||
return (
|
))}
|
||||||
<Grid
|
</SnakeWrapper>
|
||||||
columnCount={columnCount}
|
|
||||||
rowCount={rowCount}
|
|
||||||
columnWidth={pieceSizeWithSpacing}
|
|
||||||
rowHeight={pieceSizeWithSpacing}
|
|
||||||
height={height}
|
|
||||||
width={width}
|
|
||||||
itemData={{ columnCount, cacheMap, gutterSize, borderSize, pieces }}
|
|
||||||
>
|
|
||||||
{Cell}
|
|
||||||
</Grid>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</AutoSizer>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
export default ({ cacheMap, preloadPiecesAmount, piecesInOneRow }) => {
|
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 =>
|
const getFullAmountOfBlocks = amountOfBlocks =>
|
||||||
// this function counts existed amount of blocks with extra "empty blocks" to fill the row till the end
|
// 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
|
const extraBlocksAmount = finalAmountOfBlocksToRenderInShortView - cacheMapWithoutEmptyBlocks.length + 1
|
||||||
// amount of blocks needed to fill the line till the end
|
// 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]
|
return [...cacheMapWithoutEmptyBlocks, ...extraEmptyBlocksForFillingLine]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,14 @@ import isEqual from 'lodash/isEqual'
|
|||||||
|
|
||||||
import { useCreateCacheMap } from '../customHooks'
|
import { useCreateCacheMap } from '../customHooks'
|
||||||
import LargeSnake from './LargeSnake'
|
import LargeSnake from './LargeSnake'
|
||||||
import DefaultSnake from './DefaultSnake'
|
|
||||||
|
|
||||||
const TorrentCache = memo(
|
const TorrentCache = memo(
|
||||||
({ cache, isMini }) => {
|
({ cache, isMini }) => {
|
||||||
const cacheMap = useCreateCacheMap(cache)
|
const cacheMap = useCreateCacheMap(cache)
|
||||||
|
|
||||||
const preloadPiecesAmount = Math.round(cache.Capacity / cache.PiecesLength - 1)
|
const preloadPiecesAmount = Math.round(cache.Capacity / cache.PiecesLength - 1)
|
||||||
const isSnakeLarge = cacheMap.length > 1000
|
|
||||||
|
|
||||||
return isMini ? (
|
return <LargeSnake isMini={isMini} cacheMap={cacheMap} preloadPiecesAmount={preloadPiecesAmount} />
|
||||||
<DefaultSnake isMini cacheMap={cacheMap} preloadPiecesAmount={preloadPiecesAmount} />
|
|
||||||
) : isSnakeLarge ? (
|
|
||||||
<LargeSnake cacheMap={cacheMap} />
|
|
||||||
) : (
|
|
||||||
<DefaultSnake cacheMap={cacheMap} preloadPiecesAmount={preloadPiecesAmount} />
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
(prev, next) => isEqual(prev.cache.Pieces, next.cache.Pieces) && isEqual(prev.cache.Readers, next.cache.Readers),
|
(prev, next) => isEqual(prev.cache.Pieces, next.cache.Pieces) && isEqual(prev.cache.Readers, next.cache.Readers),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,32 +38,32 @@ export const useCreateCacheMap = cache => {
|
|||||||
const [cacheMap, setCacheMap] = useState([])
|
const [cacheMap, setCacheMap] = useState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!cache.PiecesCount || !cache.Pieces) return
|
const { PiecesCount, Pieces, Readers } = cache
|
||||||
|
|
||||||
const { Pieces, PiecesCount, Readers } = cache
|
|
||||||
|
|
||||||
const map = []
|
const map = []
|
||||||
|
|
||||||
for (let i = 0; i < PiecesCount; i++) {
|
for (let i = 0; i < PiecesCount; i++) {
|
||||||
const newPiece = { id: i }
|
const newPiece = { id: i }
|
||||||
|
|
||||||
const currentPiece = Pieces[i]
|
const activeBlock = Pieces[i]
|
||||||
if (currentPiece) {
|
const className = ['piece']
|
||||||
if (currentPiece.Completed && currentPiece.Size === currentPiece.Length) newPiece.isComplete = true
|
|
||||||
else {
|
if (activeBlock) {
|
||||||
newPiece.inProgress = true
|
const { Completed, Size, Length } = activeBlock
|
||||||
newPiece.percentage = (currentPiece.Size / currentPiece.Length).toFixed(2)
|
className.push(Completed && Size >= Length ? 'piece-complete' : 'piece-loading')
|
||||||
}
|
newPiece.percentage = ((Size / Length) * 100).toFixed(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
Readers.forEach(r => {
|
Readers.forEach(r => {
|
||||||
if (i === r.Reader) newPiece.isActive = true
|
if (i === r.Reader) {
|
||||||
if (i >= r.Start && i <= r.End) newPiece.isReaderRange = true
|
className.push('piece-reader')
|
||||||
|
} else if (i >= r.Start && i <= r.End) className.push('reader-range')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
newPiece.className = className.join(' ')
|
||||||
|
|
||||||
map.push(newPiece)
|
map.push(newPiece)
|
||||||
}
|
}
|
||||||
|
|
||||||
setCacheMap(map)
|
setCacheMap(map)
|
||||||
}, [cache])
|
}, [cache])
|
||||||
|
|
||||||
|
|||||||
@@ -1174,7 +1174,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
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"
|
version "7.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
|
||||||
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
|
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"
|
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
|
||||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
|
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:
|
memory-fs@^0.4.1:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
|
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"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
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:
|
react@^17.0.2:
|
||||||
version "17.0.2"
|
version "17.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||||
|
|||||||
Reference in New Issue
Block a user