Conversation
Recognize additional lossless codecs (alac, aiff, ape, dsd, wv, wav) in both frontend and backend quality detection and add tests for WavPack. Refactor library wanted-flag computation to prefer DB file rows while honoring the legacy FilePath during upgrade: introduce ComputeWantedFlag overload, avoid touching the filesystem on list endpoints, and expose the transitional FilePath on the DTO with a comment. Consolidate active download statuses into a shared static array and adjust queries to use it. Update AudiobookStatusEvaluator ComputeStatus signature/logic to use hasAnyFile (legacy summary + tracked files) and to treat absence of tracked files but presence of a legacy summary as a quality-match; update tests accordingly.
There was a problem hiding this comment.
Pull request overview
This PR optimizes library list loading by moving status/wanted evaluation to shared helpers and returning a slimmer /library payload, while improving robustness of quality/status computation (including legacy file summaries and additional lossless formats) and adding regression coverage.
Changes:
- Updated backend library list endpoint to compute
wanted/statuswithout per-item filesystem checks and to support legacyFilePathsummaries. - Updated shared audiobook status evaluation (backend + frontend) to handle legacy summaries and treat additional formats (e.g., WavPack) as lossless.
- Added/updated backend and frontend tests for wanted/status behavior and lossless detection.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| listenarr.api/Controllers/LibraryController.cs | Slim /library list composition; set-based lookups for files/profiles/downloads; wanted/status computation updates. |
| listenarr.api/Services/AudiobookStatusEvaluator.cs | Status evaluation signature change (hasAnyFile), legacy-summary handling, expanded lossless detection. |
| listenarr.api/Models/LibraryAudiobookListItemDto.cs | Retains legacy file summary fields in slim list DTO (with clarifying comment). |
| tests/Listenarr.Api.Tests/LibraryController_WantedFlagRegressionTests.cs | Adds regression test ensuring legacy FilePath doesn’t flip items to Wanted. |
| tests/Listenarr.Api.Tests/AudiobookStatusEvaluatorTests.cs | Updates tests for new evaluator signature; adds legacy-summary and WavPack lossless tests. |
| fe/src/utils/audiobookStatus.ts | Expands lossless detection to include additional containers/codecs (incl. wv). |
| fe/src/tests/audiobookStatus.spec.ts | Adds WavPack lossless status unit test. |
Comments suppressed due to low confidence (2)
listenarr.api/Controllers/LibraryController.cs:637
audiobookIds.Contains(f.AudiobookId)will translate to a large SQLIN (...)list. With SQLite this can hit the provider parameter limit (commonly 999) for users with large libraries, causing/libraryto fail—the exact scenario this PR targets. Consider rewriting this filter as a join/subquery (so the DB can evaluate it without expanding thousands of parameters), or chunkaudiobookIdsinto batches and union the results in memory.
var audiobookIds = audiobooks.Select(a => a.Id).ToArray();
var fileSummaries = await _dbContext.AudiobookFiles
.AsNoTracking()
.Where(f => audiobookIds.Contains(f.AudiobookId))
.Select(f => new AudiobookFileStatusInfo
tests/Listenarr.Api.Tests/AudiobookStatusEvaluatorTests.cs:21
- The test name
ComputeStatus_ReturnsNoFile_WhenWantedno longer matches the behavior under test (thewantedparameter was removed; this is now assertingNoFilewhenhasAnyFileis false). Renaming the test to reflect the new inputs/meaning would keep the suite readable and prevent confusion during future refactors.
[Fact]
public void ComputeStatus_ReturnsNoFile_WhenWanted()
{
var status = AudiobookStatusEvaluator.ComputeStatus(
isDownloading: false,
hasAnyFile: false,
audiobookQuality: null,
qualityProfile: null,
files: null);
Assert.Equal(AudiobookStatusEvaluator.NoFile, status);
}
You can also share your feedback on Copilot code review. Take the survey.
|
@tsolo4ever Sorry I merged before I saw your comment. Thanks for that, it was a useful pass. The only thing I didn't address from your comment was about the |
Stop expanding an in-memory audiobook ID array into the DB query — fetch AudiobookFiles summaries directly since the endpoint already loads the audiobook table, avoiding large IN() expansion and potential performance issues. Also rename the unit test ComputeStatus_ReturnsNoFile_WhenWanted to ComputeStatus_ReturnsNoFile_WhenHasNoFiles to better reflect the tested condition.
Small optimization release. I noticed that for users with larger libraries, the library page would take a long time to load. This was due to some redundant and unnecessary checks. Also the the api endpoint was returning a lot of data that was not needed for the page. Additionally I have added url resolution normalizations to download client host/ip:port connection strings so the connection tests are more robust.
Added
/libraryGET /library/librarypayload behaviorChanged
GET /libraryfrom a hybrid list/detail payload into a lighter list responseGET /library/{id}as the rich full-detail audiobook endpoint/libraryrequests into a single in-flight fetchFixed
/libraryresponses caused by per-audiobook filesystem existence checks during list loading/libraryrequests during startup and view initializationName or service not known (http:80)Removed
/librarylist pathfiles[]metadata in library list views for status calculationContinue #401