mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
Fixed: (UI) Regain jump to character
functionality for search releases
This commit is contained in:
@@ -39,7 +39,8 @@ class VirtualTable extends Component {
|
||||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
width: 0
|
||||
width: 0,
|
||||
scrollRestored: false
|
||||
};
|
||||
|
||||
this._grid = null;
|
||||
@@ -48,20 +49,25 @@ class VirtualTable extends Component {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const {
|
||||
items,
|
||||
scrollIndex
|
||||
scrollIndex,
|
||||
scrollTop
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
width
|
||||
width,
|
||||
scrollRestored
|
||||
} = this.state;
|
||||
|
||||
if (this._grid &&
|
||||
(prevState.width !== width ||
|
||||
hasDifferentItemsOrOrder(prevProps.items, items))) {
|
||||
if (this._grid && (prevState.width !== width || hasDifferentItemsOrOrder(prevProps.items, items))) {
|
||||
// recomputeGridSize also forces Grid to discard its cache of rendered cells
|
||||
this._grid.recomputeGridSize();
|
||||
}
|
||||
|
||||
if (this._grid && scrollTop !== undefined && scrollTop !== 0 && !scrollRestored) {
|
||||
this.setState({ scrollRestored: true });
|
||||
this._grid.scrollToPosition({ scrollTop });
|
||||
}
|
||||
|
||||
if (scrollIndex != null && scrollIndex !== prevProps.scrollIndex) {
|
||||
this._grid.scrollToCell({
|
||||
rowIndex: scrollIndex,
|
||||
@@ -98,6 +104,7 @@ class VirtualTable extends Component {
|
||||
focusScroller,
|
||||
header,
|
||||
headerHeight,
|
||||
rowHeight,
|
||||
rowRenderer,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
@@ -141,6 +148,7 @@ class VirtualTable extends Component {
|
||||
{header}
|
||||
<div ref={registerChild}>
|
||||
<Grid
|
||||
{...otherProps}
|
||||
ref={this.setGridRef}
|
||||
autoContainerWidth={true}
|
||||
autoHeight={true}
|
||||
@@ -148,7 +156,7 @@ class VirtualTable extends Component {
|
||||
width={width}
|
||||
height={height}
|
||||
headerHeight={height - headerHeight}
|
||||
rowHeight={ROW_HEIGHT}
|
||||
rowHeight={rowHeight}
|
||||
rowCount={items.length}
|
||||
columnCount={1}
|
||||
columnWidth={width}
|
||||
@@ -162,7 +170,6 @@ class VirtualTable extends Component {
|
||||
className={styles.tableBodyContainer}
|
||||
style={gridStyle}
|
||||
containerStyle={containerStyle}
|
||||
{...otherProps}
|
||||
/>
|
||||
</div>
|
||||
</Scroller>
|
||||
@@ -180,16 +187,19 @@ VirtualTable.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
scrollIndex: PropTypes.number,
|
||||
scrollTop: PropTypes.number,
|
||||
scroller: PropTypes.instanceOf(Element).isRequired,
|
||||
focusScroller: PropTypes.bool.isRequired,
|
||||
header: PropTypes.node.isRequired,
|
||||
headerHeight: PropTypes.number.isRequired,
|
||||
rowRenderer: PropTypes.func.isRequired
|
||||
rowRenderer: PropTypes.func.isRequired,
|
||||
rowHeight: PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
VirtualTable.defaultProps = {
|
||||
className: styles.tableContainer,
|
||||
headerHeight: 38,
|
||||
rowHeight: ROW_HEIGHT,
|
||||
focusScroller: true
|
||||
};
|
||||
|
||||
|
@@ -158,7 +158,7 @@ const IndexerIndex = withScrollPosition((props: IndexerIndexProps) => {
|
||||
const characters = items.reduce((acc, item) => {
|
||||
let char = item.sortName.charAt(0);
|
||||
|
||||
if (!isNaN(char)) {
|
||||
if (!isNaN(Number(char))) {
|
||||
char = '#';
|
||||
}
|
||||
|
||||
|
@@ -92,11 +92,9 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
|
||||
|
||||
const columns = useSelector(columnsSelector);
|
||||
const { showBanners } = useSelector(selectTableOptions);
|
||||
const listRef: React.MutableRefObject<List> = useRef();
|
||||
const listRef = useRef<List>(null);
|
||||
const [measureRef, bounds] = useMeasure();
|
||||
const [size, setSize] = useState({ width: 0, height: 0 });
|
||||
const windowWidth = window.innerWidth;
|
||||
const windowHeight = window.innerHeight;
|
||||
|
||||
const rowHeight = useMemo(() => {
|
||||
return showBanners ? 70 : 38;
|
||||
@@ -107,8 +105,8 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
|
||||
|
||||
if (isSmallScreen) {
|
||||
setSize({
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -121,14 +119,14 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
|
||||
|
||||
setSize({
|
||||
width: width - padding * 2,
|
||||
height: windowHeight,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
}
|
||||
}, [isSmallScreen, windowWidth, windowHeight, scrollerRef, bounds]);
|
||||
}, [isSmallScreen, scrollerRef, bounds]);
|
||||
|
||||
useEffect(() => {
|
||||
const currentScrollListener = isSmallScreen ? window : scrollerRef.current;
|
||||
const currentScrollerRef = scrollerRef.current;
|
||||
const currentScrollerRef = scrollerRef.current as HTMLElement;
|
||||
const currentScrollListener = isSmallScreen ? window : currentScrollerRef;
|
||||
|
||||
const handleScroll = throttle(() => {
|
||||
const { offsetTop = 0 } = currentScrollerRef;
|
||||
@@ -137,7 +135,7 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
|
||||
? getWindowScrollTopPosition()
|
||||
: currentScrollerRef.scrollTop) - offsetTop;
|
||||
|
||||
listRef.current.scrollTo(scrollTop);
|
||||
listRef.current?.scrollTo(scrollTop);
|
||||
}, 10);
|
||||
|
||||
currentScrollListener.addEventListener('scroll', handleScroll);
|
||||
@@ -166,8 +164,8 @@ function IndexerIndexTable(props: IndexerIndexTableProps) {
|
||||
scrollTop += offset;
|
||||
}
|
||||
|
||||
listRef.current.scrollTo(scrollTop);
|
||||
scrollerRef.current.scrollTo(0, scrollTop);
|
||||
listRef.current?.scrollTo(scrollTop);
|
||||
scrollerRef.current?.scrollTo(0, scrollTop);
|
||||
}
|
||||
}
|
||||
}, [jumpToCharacter, rowHeight, items, scrollerRef, listRef]);
|
||||
|
@@ -154,7 +154,7 @@ class SearchIndex extends Component {
|
||||
const characters = _.reduce(items, (acc, item) => {
|
||||
let char = item.sortTitle.charAt(0);
|
||||
|
||||
if (!isNaN(char)) {
|
||||
if (!isNaN(Number(char))) {
|
||||
char = '#';
|
||||
}
|
||||
|
||||
|
@@ -9,12 +9,12 @@ function createUnoptimizedSelector(uiSection) {
|
||||
const items = indexers.items.map((s) => {
|
||||
const {
|
||||
id,
|
||||
name
|
||||
sortName
|
||||
} = s;
|
||||
|
||||
return {
|
||||
id,
|
||||
sortName: name
|
||||
sortName
|
||||
};
|
||||
});
|
||||
|
||||
|
@@ -9,13 +9,13 @@ function createUnoptimizedSelector(uiSection) {
|
||||
const items = releases.items.map((s) => {
|
||||
const {
|
||||
guid,
|
||||
title,
|
||||
sortTitle,
|
||||
indexerId
|
||||
} = s;
|
||||
|
||||
return {
|
||||
guid,
|
||||
sortTitle: title,
|
||||
sortTitle,
|
||||
indexerId
|
||||
};
|
||||
});
|
||||
@@ -40,7 +40,7 @@ const createMovieEqualSelector = createSelectorCreator(
|
||||
function createReleaseClientSideCollectionItemsSelector(uiSection) {
|
||||
return createMovieEqualSelector(
|
||||
createUnoptimizedSelector(uiSection),
|
||||
(movies) => movies
|
||||
(releases) => releases
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
export default function getIndexOfFirstCharacter(items, character) {
|
||||
return items.findIndex((item) => {
|
||||
const firstCharacter = item.sortTitle.charAt(0);
|
||||
const firstCharacter = 'sortName' in item ? item.sortName.charAt(0) : item.sortTitle.charAt(0);
|
||||
|
||||
if (character === '#') {
|
||||
return !isNaN(firstCharacter);
|
||||
return !isNaN(Number(firstCharacter));
|
||||
}
|
||||
|
||||
return firstCharacter === character;
|
||||
|
Reference in New Issue
Block a user