You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Prowlarr/frontend/src/Components/Page/PageJumpBar.js

159 lines
3.4 KiB

import PropTypes from 'prop-types';
import React, { Component } from 'react';
import dimensions from 'Styles/Variables/dimensions';
import Measure from 'Components/Measure';
import PageJumpBarItem from './PageJumpBarItem';
import styles from './PageJumpBar.css';
const ITEM_HEIGHT = parseInt(dimensions.jumpBarItemHeight);
class PageJumpBar extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
height: 0,
visibleItems: props.items.order
};
}
componentDidMount() {
this.computeVisibleItems();
}
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.items !== this.props.items ||
nextState.height !== this.state.height ||
nextState.visibleItems !== this.state.visibleItems
);
}
componentDidUpdate(prevProps, prevState) {
if (
prevProps.items !== this.props.items ||
prevState.height !== this.state.height
) {
this.computeVisibleItems();
}
}
//
// Control
computeVisibleItems() {
const {
items,
minimumItems
} = this.props;
if (!items) {
return;
}
const {
characters,
order
} = items;
const height = this.state.height;
const maximumItems = Math.floor(height / ITEM_HEIGHT);
const diff = order.length - maximumItems;
if (diff < 0) {
this.setState({ visibleItems: order });
return;
}
if (order.length < minimumItems) {
this.setState({ visibleItems: order });
return;
}
// get first, last, and most common in between to make up numbers
const visibleItems = [order[0]];
const sorted = order.slice(1, -1).map((x) => characters[x]).sort((a, b) => b - a);
const minCount = sorted[maximumItems - 3];
const greater = sorted.reduce((acc, value) => acc + (value > minCount ? 1 : 0), 0);
let minAllowed = maximumItems - 2 - greater;
for (let i = 1; i < order.length - 1; i++) {
if (characters[order[i]] > minCount) {
visibleItems.push(order[i]);
} else if (characters[order[i]] === minCount && minAllowed > 0) {
visibleItems.push(order[i]);
minAllowed--;
}
}
visibleItems.push(order[order.length - 1]);
this.setState({ visibleItems });
}
//
// Listeners
onMeasure = ({ height }) => {
this.setState({ height });
}
//
// Render
render() {
const {
minimumItems,
onItemPress
} = this.props;
const {
visibleItems
} = this.state;
if (!visibleItems.length || visibleItems.length < minimumItems) {
return null;
}
return (
<div className={styles.jumpBar}>
<Measure
whitelist={['height']}
onMeasure={this.onMeasure}
>
<div className={styles.jumpBarItems}>
{
visibleItems.map((item) => {
return (
<PageJumpBarItem
key={item}
label={item}
onItemPress={onItemPress}
/>
);
})
}
</div>
</Measure>
</div>
);
}
}
PageJumpBar.propTypes = {
items: PropTypes.object.isRequired,
minimumItems: PropTypes.number.isRequired,
onItemPress: PropTypes.func.isRequired
};
PageJumpBar.defaultProps = {
minimumItems: 5
};
export default PageJumpBar;