Inline browse artists pagination limits

This commit is contained in:
Jordan Wages 2025-09-24 03:57:31 -05:00
commit 9fa2dbbadc

View file

@ -1457,19 +1457,19 @@
} }
const baseCountSql = 'SELECT COUNT(*) AS count FROM artists'; const baseCountSql = 'SELECT COUNT(*) AS count FROM artists';
const baseRowsSql = ` const buildBaseRowsSql = (pageSize, offset) => `
SELECT id, name SELECT id, name
FROM artists FROM artists
ORDER BY name COLLATE NOCASE ORDER BY name COLLATE NOCASE
LIMIT ? OFFSET ? LIMIT ${pageSize} OFFSET ${offset}
`; `;
const countSql = 'SELECT COUNT(*) AS count FROM artists WHERE name LIKE ? ESCAPE "\\"'; const countSql = 'SELECT COUNT(*) AS count FROM artists WHERE name LIKE ? ESCAPE "\\"';
const rowsSql = ` const buildRowsSql = (likeValue, pageSize, offset) => `
SELECT id, name SELECT id, name
FROM artists FROM artists
WHERE name LIKE ? ESCAPE "\\" WHERE name LIKE ${escapeSqlText(likeValue)} ESCAPE "\\"
ORDER BY name COLLATE NOCASE ORDER BY name COLLATE NOCASE
LIMIT ? OFFSET ? LIMIT ${pageSize} OFFSET ${offset}
`; `;
const ftsCountSql = ` const ftsCountSql = `
SELECT COUNT(*) AS count FROM ( SELECT COUNT(*) AS count FROM (
@ -1481,7 +1481,7 @@
GROUP BY a.id GROUP BY a.id
) AS matches ) AS matches
`; `;
const ftsRowsSql = ` const buildFtsRowsSql = (pageSize, offset) => `
SELECT a.id, a.name SELECT a.id, a.name
FROM fts_tracks FROM fts_tracks
JOIN tracks t ON t.id = fts_tracks.rowid JOIN tracks t ON t.id = fts_tracks.rowid
@ -1489,7 +1489,7 @@
WHERE fts_tracks MATCH ? WHERE fts_tracks MATCH ?
GROUP BY a.id GROUP BY a.id
ORDER BY a.name COLLATE NOCASE ORDER BY a.name COLLATE NOCASE
LIMIT ? OFFSET ? LIMIT ${pageSize} OFFSET ${offset}
`; `;
function buildArtistFtsMatch(input) { function buildArtistFtsMatch(input) {
@ -1519,7 +1519,26 @@
const useUnfilteredQuery = !typedFilter && !state.prefix; const useUnfilteredQuery = !typedFilter && !state.prefix;
listState.showLoading('Loading…'); listState.showLoading('Loading…');
function sanitizeLimitAndOffset(rawPageSize, rawOffset) {
const numericPageSize = Number(rawPageSize);
const numericOffset = Number(rawOffset);
const pageSizeInt = Number.isFinite(numericPageSize) ? Math.floor(numericPageSize) : NaN;
const offsetInt = Number.isFinite(numericOffset) ? Math.floor(numericOffset) : NaN;
if (!Number.isFinite(pageSizeInt) || pageSizeInt < 1 || !Number.isFinite(offsetInt) || offsetInt < 0) {
console.error('Invalid pagination values for artists query', {
pageSize: rawPageSize,
offset: rawOffset,
});
listState.showError('Failed to load artists.');
return null;
}
return { pageSize: pageSizeInt, offset: offsetInt };
}
let { page, pageSize, offset } = getNormalizedPagination(); let { page, pageSize, offset } = getNormalizedPagination();
const initialSanitized = sanitizeLimitAndOffset(pageSize, offset);
if (!initialSanitized) return;
({ pageSize, offset } = initialSanitized);
let total = 0; let total = 0;
const rows = []; const rows = [];
let usedFts = false; let usedFts = false;
@ -1543,14 +1562,16 @@
view: VIEW_NAMES.browseArtists, view: VIEW_NAMES.browseArtists,
})) { })) {
({ page, pageSize, offset } = getNormalizedPagination()); ({ page, pageSize, offset } = getNormalizedPagination());
const sanitized = sanitizeLimitAndOffset(pageSize, offset);
if (!sanitized) return;
({ pageSize, offset } = sanitized);
} }
const ftsRowsStmt = prepareForView( const ftsRowsStmt = prepareForView(
db, db,
VIEW_NAMES.browseArtists, VIEW_NAMES.browseArtists,
applyFtsMatch(ftsRowsSql, ftsMatch), applyFtsMatch(buildFtsRowsSql(pageSize, offset), ftsMatch),
'fts-rows', 'fts-rows',
); );
ftsRowsStmt.bind([pageSize, offset]);
while (ftsRowsStmt.step()) rows.push(ftsRowsStmt.getAsObject()); while (ftsRowsStmt.step()) rows.push(ftsRowsStmt.getAsObject());
ftsRowsStmt.free(); ftsRowsStmt.free();
usedFts = true; usedFts = true;
@ -1581,16 +1602,19 @@
view: VIEW_NAMES.browseArtists, view: VIEW_NAMES.browseArtists,
})) { })) {
({ page, pageSize, offset } = getNormalizedPagination()); ({ page, pageSize, offset } = getNormalizedPagination());
const sanitized = sanitizeLimitAndOffset(pageSize, offset);
if (!sanitized) return;
({ pageSize, offset } = sanitized);
} }
const rowsStmt = prepareForView( const rowsStmt = prepareForView(
db, db,
VIEW_NAMES.browseArtists, VIEW_NAMES.browseArtists,
useUnfilteredQuery ? baseRowsSql : rowsSql, useUnfilteredQuery
? buildBaseRowsSql(pageSize, offset)
: buildRowsSql(likeTerm, pageSize, offset),
useUnfilteredQuery ? 'rows' : 'rows-filtered', useUnfilteredQuery ? 'rows' : 'rows-filtered',
); );
if (useUnfilteredQuery) rowsStmt.bind([pageSize, offset]);
else rowsStmt.bind([likeTerm, pageSize, offset]);
while (rowsStmt.step()) rows.push(rowsStmt.getAsObject()); while (rowsStmt.step()) rows.push(rowsStmt.getAsObject());
rowsStmt.free(); rowsStmt.free();
} }
@ -1606,12 +1630,14 @@
return; return;
} }
({ page, pageSize } = getNormalizedPagination()); const finalPagination = getNormalizedPagination();
const finalSanitized = sanitizeLimitAndOffset(finalPagination.pageSize, finalPagination.offset);
if (!finalSanitized) return;
listState.showRows({ listState.showRows({
rows, rows,
total, total,
page, page: finalPagination.page,
pageSize, pageSize: finalSanitized.pageSize,
}); });
} }