Add "Page Size Multiplier" option

Some users (eg me) prefer in-browser search and scroll to clicking through pages.
This attempts to be a minimally-invasive change to enable that workflow.

Adds a "Page Size Multiplier" option to the Personal page to allow the user
to set the number of items per page to a multiple of the default page size.

Also abstracts some of the page sizes from bare integers into constants.
This commit is contained in:
gwynm 2025-02-20 07:49:28 +00:00
parent 46a963a02a
commit c0ba4d4684
7 changed files with 65 additions and 11 deletions

View File

@ -2,6 +2,7 @@ import React from 'react'
import { List as RAList } from 'react-admin'
import { Pagination } from './Pagination'
import { Title } from './index'
import { defaultPageSize } from '../utils/pageSizes'
export const List = (props) => {
const { resource } = props
@ -13,7 +14,7 @@ export const List = (props) => {
args={{ smart_count: 2 }}
/>
}
perPage={15}
perPage={defaultPageSize()}
pagination={<Pagination />}
{...props}
/>

View File

@ -1,6 +1,7 @@
import React from 'react'
import { Pagination as RAPagination } from 'react-admin'
import { defaultPageSizes } from '../utils/pageSizes'
export const Pagination = (props) => (
<RAPagination rowsPerPageOptions={[15, 25, 50]} {...props} />
<RAPagination rowsPerPageOptions={defaultPageSizes()} {...props} />
)

View File

@ -1,19 +1,24 @@
import { useSelector } from 'react-redux'
import { pageSizeMultiplier } from '../utils/pageSizes'
const getPerPage = (width) => {
if (width === 'xs') return 12
if (width === 'sm') return 12
if (width === 'md') return 12
if (width === 'lg') return 18
return 36
let baseSize
if (width === 'xs') baseSize = 12
else if (width === 'sm') baseSize = 12
else if (width === 'md') baseSize = 12
else if (width === 'lg') baseSize = 18
else baseSize = 36
return baseSize * pageSizeMultiplier()
}
const getPerPageOptions = (width) => {
const options = [3, 6, 12]
if (width === 'xs') return [12]
if (width === 'sm') return [12]
if (width === 'md') return options.map((v) => v * 4)
return options.map((v) => v * 6)
let sizeOptions
if (width === 'xs') sizeOptions = [12]
else if (width === 'sm') sizeOptions = [12]
else if (width === 'md') sizeOptions = options.map((v) => v * 4)
else sizeOptions = options.map((v) => v * 6)
return sizeOptions.map((size) => size * pageSizeMultiplier())
}
export const useAlbumsPerPage = (width) => {

View File

@ -390,6 +390,7 @@
"theme": "Theme",
"language": "Language",
"defaultView": "Default View",
"pageSizeMultiplier": "Page Size Multiplier",
"desktop_notifications": "Desktop Notifications",
"lastfmNotConfigured": "Last.fm API-Key is not configured",
"lastfmScrobbling": "Scrobble to Last.fm",

View File

@ -4,6 +4,7 @@ import { makeStyles } from '@material-ui/core/styles'
import { SelectLanguage } from './SelectLanguage'
import { SelectTheme } from './SelectTheme'
import { SelectDefaultView } from './SelectDefaultView'
import { SelectPageSize } from './SelectPageSize'
import { NotificationsToggle } from './NotificationsToggle'
import { LastfmScrobbleToggle } from './LastfmScrobbleToggle'
import { ListenBrainzScrobbleToggle } from './ListenBrainzScrobbleToggle'
@ -25,6 +26,7 @@ const Personal = () => {
<SelectTheme />
<SelectLanguage />
<SelectDefaultView />
<SelectPageSize />
{config.enableReplayGain && <ReplayGainToggle />}
<NotificationsToggle />
{config.lastFMEnabled && <LastfmScrobbleToggle />}

View File

@ -0,0 +1,28 @@
import { SelectInput, useTranslate } from 'react-admin'
import {
pageSizeMultipliers,
defaultPageSizeMultiplier,
} from '../utils/pageSizes'
export const SelectPageSize = (props) => {
const translate = useTranslate()
const current =
localStorage.getItem('pageSizeMultiplier') || defaultPageSizeMultiplier
const choices = pageSizeMultipliers.map((v) => ({
id: v,
name: `× ${v}`,
}))
return (
<SelectInput
{...props}
source="pageSize"
label={translate('menu.personal.options.pageSizeMultiplier')}
defaultValue={current}
choices={choices}
translateChoice={false}
onChange={(event) => {
localStorage.setItem('pageSizeMultiplier', event.target.value)
}}
/>
)
}

16
ui/src/utils/pageSizes.js Normal file
View File

@ -0,0 +1,16 @@
/* Groups page-size logic, since it's used in several different parts of the UI */
export const defaultPageSizeMultiplier = '1'
export const pageSizeMultipliers = ['1', '4', '10', '1000']
export const defaultBasePageSize = 15
export const defaultBasePageSizes = [15, 25, 50]
// Stored as a string for consistency, so we provide a getter. Function, not
// constant, because it's read from localStorage (which might change)
export const pageSizeMultiplier = () =>
parseInt(
localStorage.getItem('pageSizeMultiplier') || defaultPageSizeMultiplier,
)
export const defaultPageSize = () => defaultBasePageSize * pageSizeMultiplier()
export const defaultPageSizes = () =>
defaultBasePageSizes.map((size) => size * pageSizeMultiplier())