Open pwinnski opened 1 month ago
The typical implementation of this is to add a vertical bar on the right, next to the scroll bar with clickable letters on it. Clicking a letter either opens up a filtered view or scrolls to the desired location.
Indeed, while there does not need to be a visual change to the UI, this is an example from another program:
I'm not able to find the feature request at the moment, but this has the same issue as the alphabetical scroll bar feature request, where the client also does not know where to jump to. The client knows how many total items are in the library/filter, but does not know the breakdown of those items until the page is requested for getting the item information and cover images.
That does make this a more complicated request then, because it would need to start with being able to get offsets by letter or something similar. Hmmm.
Re-stating the issue: with a library of 6000+ audiobooks, scrolling through a name-sorted list is currently slow to the point of unusable. If I use the scrollbar to jump down quite a bit in search of books with a title beginning with T, I can drag the scrollbar, let go, and then wait to see how far I've missed, and will have to navigate more to get to the section I'm seeking.
I just tried this: The log contains quite a few "Cache miss" lines and shows queries for pages 1, 2, 4, 5, 3, 6, 7, 22, 41, 23, 42, 112, 113, 117, 115, 114, 105, 106, 104, and 103, in that order. These lines start at :58:17.008 and end at :59:40.551, 83 seconds from first query to last. Again, only after all of these complete can I even see how close I got to where I was seeking, at which point I have to scroll again.
Delays of 20+ seconds are commonplace, but delays long enough to brew a coffee are extreme!
Without any consideration of how to work within the current ApiCacheManager framework, if I were writing API code for this function alone, I would think there should be a way to return the relevant page of results by calculating the offset. For example:
time echo "
SELECT b.id,
b.title,
b.subtitle,
b.coverPath,
GROUP_CONCAT(a.name, ', ') authors,
s.name,
bs.sequence
FROM books b,
bookAuthors ba ON ba.bookId = b.id,
authors a ON a.id = ba.authorId
LEFT JOIN bookSeries bs ON b.id = bs.bookId
LEFT JOIN series s ON bs.seriesId = s.id
GROUP BY b.id
ORDER BY b.titleIgnorePrefix
LIMIT 54
OFFSET (SELECT offset_value
FROM (SELECT (COUNT(*) / 54) * 54 AS offset_value
FROM books
WHERE titleIgnorePrefix < 'L'));
" | sqlite3 config/absdatabase.sqlite
[skipped]
real 0m0.094s
user 0m0.068s
sys 0m0.025s
In this case, the 54
is from my daily log, and seems to be based on my display being set to four rows of nine, so it's set to six rows of nine, one before and one after my displayed rows. Let that be {page_size}
and the letter someone has typed or clicked be {letter}
and you get:
SELECT b.id,
b.title,
b.subtitle,
b.coverPath,
GROUP_CONCAT(a.name, ', ') authors,
s.name,
bs.sequence
FROM books b,
bookAuthors ba ON ba.bookId = b.id,
authors a ON a.id = ba.authorId
LEFT JOIN bookSeries bs ON b.id = bs.bookId
LEFT JOIN series s ON bs.seriesId = s.id
GROUP BY b.id
ORDER BY b.titleIgnorePrefix
LIMIT {page_size}
OFFSET (SELECT offset_value
FROM (SELECT (COUNT(*) / {page_size}) * {page_size} AS offset_value
FROM books
WHERE titleIgnorePrefix < '{letter}'));
On a completely-cold container, I've seen that take 6-7 seconds, but it's normally less than one-tenth of a second.
I know things get more complex when you have to filter for explicit content and allowed tags, and I just realized I'm not even limiting to a single library here, but that general approach would be ideal, IF ABS were set up to use direct queries like that. Instead everything goes through Sequelize, and next I'll look into how that works, and what queries are actually being done.
To limit to a single library, replace:
FROM books b,
bookAuthors ba ON ba.bookId = b.id,
with
FROM books b,
libraryItems l ON (b.id = l.mediaId AND l.libraryId = {library_id}),
bookAuthors ba ON ba.bookId = b.id,
And also in the OFFSET clause, replace:
FROM books
with
FROM books b,
libraryItems l ON (b.id = l.mediaId AND l.libraryId = {library_id})
Type of Enhancement
Web Interface/Frontend
Describe the Feature/Enhancement
When presented with a list that is sorted alphabetically, typing a letter should scroll to the first item starting with that letter.
Why would this be helpful?
A list with hundreds or thousands of items may take a long time to scroll, and depending on caching, it may not be clear where to stop scrolling. A Series listing is just unlabeled rectangles on a cache miss: And the same is true of a Library listing: If I can press 'R' to jump to the first book title or author name (depending on sort) or series name that starts with a 'R', that would speed things up considerably.
Future Implementation (Screenshot)
There doesn't need to be any visual change to the UI at all. Pressing 'R' (for example) would scroll to here: Because 'Rains, The' is the first series that "starts" with R.
Audiobookshelf Server Version
v2.13.4
Current Implementation (Screenshot)
Pressing any letter key leaves me at the top of the list.