From c0ba4d4684e85a409925308937385b9274298e42 Mon Sep 17 00:00:00 2001 From: gwynm Date: Thu, 20 Feb 2025 07:49:28 +0000 Subject: [PATCH] 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. --- ui/src/common/List.jsx | 3 ++- ui/src/common/Pagination.jsx | 3 ++- ui/src/common/useAlbumsPerPage.jsx | 23 ++++++++++++++--------- ui/src/i18n/en.json | 1 + ui/src/personal/Personal.jsx | 2 ++ ui/src/personal/SelectPageSize.jsx | 28 ++++++++++++++++++++++++++++ ui/src/utils/pageSizes.js | 16 ++++++++++++++++ 7 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 ui/src/personal/SelectPageSize.jsx create mode 100644 ui/src/utils/pageSizes.js diff --git a/ui/src/common/List.jsx b/ui/src/common/List.jsx index f74ab027e..ea11c4592 100644 --- a/ui/src/common/List.jsx +++ b/ui/src/common/List.jsx @@ -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={} {...props} /> diff --git a/ui/src/common/Pagination.jsx b/ui/src/common/Pagination.jsx index e17d9e63e..3b1d8ca5b 100644 --- a/ui/src/common/Pagination.jsx +++ b/ui/src/common/Pagination.jsx @@ -1,6 +1,7 @@ import React from 'react' import { Pagination as RAPagination } from 'react-admin' +import { defaultPageSizes } from '../utils/pageSizes' export const Pagination = (props) => ( - + ) diff --git a/ui/src/common/useAlbumsPerPage.jsx b/ui/src/common/useAlbumsPerPage.jsx index 6a02bdeb7..d7c7f2af3 100644 --- a/ui/src/common/useAlbumsPerPage.jsx +++ b/ui/src/common/useAlbumsPerPage.jsx @@ -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) => { diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 75c5e12e5..e573373d2 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -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", diff --git a/ui/src/personal/Personal.jsx b/ui/src/personal/Personal.jsx index 84f9b63e6..acda6081c 100644 --- a/ui/src/personal/Personal.jsx +++ b/ui/src/personal/Personal.jsx @@ -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 = () => { + {config.enableReplayGain && } {config.lastFMEnabled && } diff --git a/ui/src/personal/SelectPageSize.jsx b/ui/src/personal/SelectPageSize.jsx new file mode 100644 index 000000000..d3a9ea4db --- /dev/null +++ b/ui/src/personal/SelectPageSize.jsx @@ -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 ( + { + localStorage.setItem('pageSizeMultiplier', event.target.value) + }} + /> + ) +} diff --git a/ui/src/utils/pageSizes.js b/ui/src/utils/pageSizes.js new file mode 100644 index 000000000..cae35ec87 --- /dev/null +++ b/ui/src/utils/pageSizes.js @@ -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())