audiobookshelf/server/utils/queries/libraryBrowseStrategy.js
2026-03-14 02:19:50 -04:00

108 lines
3.5 KiB
JavaScript

function getTitleCursorKey() {
return global.ServerSettings && global.ServerSettings.sortingIgnorePrefix ? 'titleIgnorePrefix' : 'title'
}
function getProgressCursorKeys(sortBy, filterValue) {
const supportedFilters = ['finished', 'in-progress', 'audio-in-progress', 'ebook-in-progress', 'ebook-finished']
const supportedFinishedAtFilters = ['finished', 'ebook-finished']
if (sortBy === 'progress' && supportedFilters.includes(filterValue)) {
return ['mediaProgresses.updatedAt', 'id']
}
if (sortBy === 'progress.createdAt' && supportedFilters.includes(filterValue)) {
return ['mediaProgresses.createdAt', 'id']
}
if (sortBy === 'progress.finishedAt' && supportedFinishedAtFilters.includes(filterValue)) {
return ['mediaProgresses.finishedAt', 'id']
}
return []
}
function getKeysetCursorKeys({ mediaType, sortBy, filterGroup, filterValue, collapseseries }) {
if (mediaType === 'podcast') {
return []
}
if (sortBy === 'media.metadata.title' && collapseseries) {
return []
}
if (filterGroup === 'progress') {
return getProgressCursorKeys(sortBy, filterValue)
}
if (sortBy === 'media.metadata.title') {
return [getTitleCursorKey(), 'id']
}
if (sortBy === 'media.metadata.authorName') {
return ['authorNamesFirstLast', getTitleCursorKey(), 'id']
}
if (sortBy === 'media.metadata.authorNameLF') {
return ['authorNamesLastFirst', getTitleCursorKey(), 'id']
}
if (sortBy === 'addedAt') {
return ['createdAt', 'id']
}
if (sortBy === 'updatedAt') {
return ['updatedAt', 'id']
}
return []
}
function getPaginationMode({ mediaType, pageMode, sortBy, filterGroup, filterValue, collapseseries }) {
if (pageMode !== 'endless') {
return 'offset'
}
return getKeysetCursorKeys({ mediaType, sortBy, filterGroup, filterValue, collapseseries }).length ? 'keyset' : 'offset'
}
function getFamily({ mediaType, sortBy, filterGroup, collapseseries }) {
if (sortBy === 'random') return 'random-browse'
if (mediaType === 'podcast') return 'podcast-browse'
if (collapseseries && filterGroup === 'series') return 'collapsed-series-browse'
if (filterGroup === 'series') return 'series-browse'
if (filterGroup === 'progress') return 'progress-browse'
if (filterGroup === 'recent' || sortBy === 'addedAt') return 'recent-browse'
if (sortBy === 'media.metadata.authorName' || sortBy === 'media.metadata.authorNameLF') return 'author-browse'
if (filterGroup) return 'filtered-browse'
return 'plain-browse'
}
function getLibraryBrowseStrategy({ mediaType, sortBy, filterGroup, filterValue, pageMode, collapseseries } = {}) {
const normalizedSort = sortBy || 'media.metadata.title'
const cursorKeys = getKeysetCursorKeys({ mediaType, sortBy: normalizedSort, filterGroup, filterValue, collapseseries })
const paginationMode = getPaginationMode({ mediaType, pageMode, sortBy: normalizedSort, filterGroup, filterValue, collapseseries })
if (normalizedSort === 'random') {
return {
family: 'random-browse',
paginationMode: 'offset',
countMode: 'exact-on-initial-page',
deepScrollAllowed: false,
tieBreaker: 'id',
cursorKeys: []
}
}
return {
family: getFamily({ mediaType, sortBy: normalizedSort, filterGroup, collapseseries }),
paginationMode,
countMode: paginationMode === 'keyset' ? 'deferred-exact' : 'exact-on-initial-page',
deepScrollAllowed: paginationMode === 'keyset',
tieBreaker: 'id',
cursorKeys
}
}
module.exports = {
getLibraryBrowseStrategy
}