OPDS Enhancements (#1687)

* Bump express from 4.17.2 to 4.18.2 in /UI/Web

Bumps [express](https://github.com/expressjs/express) from 4.17.2 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump decode-uri-component from 0.2.0 to 0.2.2 in /UI/Web

Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump qs and express in /UI/Web

Bumps [qs](https://github.com/ljharb/qs) and [express](https://github.com/expressjs/express). These dependencies needed to be updated together.

Updates `qs` from 6.5.3 to 6.11.0
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.5.3...v6.11.0)

Updates `express` from 4.17.2 to 4.18.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Added genre and authors to Series level, added summary to volume and chapter level.

Force order on reading list title as Chunky enforces their own sort order and doesn't respect the spec.

* Moved all the reading list formatting logic to the backend. This allows us to re-use the UI logic for OPDS streams.

* Fixed a broken unit test

* Code smells

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
Joe Milazzo 2022-12-10 11:07:55 -06:00 committed by GitHub
parent fbd9b36e35
commit 1a729adf40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 369 additions and 344 deletions

View file

@ -51,6 +51,7 @@ public interface ILibraryRepository
Task<bool> DoAnySeriesFoldersMatch(IEnumerable<string> folders);
Task<string> GetLibraryCoverImageAsync(int libraryId);
Task<IList<string>> GetAllCoverImagesAsync();
Task<IDictionary<int, LibraryType>> GetLibraryTypesForIdsAsync(IEnumerable<int> libraryIds);
}
public class LibraryRepository : ILibraryRepository
@ -397,4 +398,26 @@ public class LibraryRepository : ILibraryRepository
.AsNoTracking()
.ToListAsync();
}
public async Task<IDictionary<int, LibraryType>> GetLibraryTypesForIdsAsync(IEnumerable<int> libraryIds)
{
var types = await _context.Library
.Where(l => libraryIds.Contains(l.Id))
.AsNoTracking()
.Select(l => new
{
LibraryId = l.Id,
LibraryType = l.Type
})
.ToListAsync();
var dict = new Dictionary<int, LibraryType>();
foreach (var type in types)
{
dict.TryAdd(type.LibraryId, type.LibraryType);
}
return dict;
}
}

View file

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using API.DTOs.ReadingLists;
using API.Entities;
using API.Entities.Enums;
using API.Helpers;
using AutoMapper;
using AutoMapper.QueryableExtensions;
@ -145,36 +146,41 @@ public class ReadingListRepository : IReadingListRepository
TotalPages = chapter.Pages,
ChapterNumber = chapter.Range,
ReleaseDate = chapter.ReleaseDate,
readingListItem = data
ReadingListItem = data,
ChapterTitleName = chapter.TitleName,
})
.Join(_context.Volume, s => s.readingListItem.VolumeId, volume => volume.Id, (data, volume) => new
.Join(_context.Volume, s => s.ReadingListItem.VolumeId, volume => volume.Id, (data, volume) => new
{
data.readingListItem,
data.ReadingListItem,
data.TotalPages,
data.ChapterNumber,
data.ReleaseDate,
data.ChapterTitleName,
VolumeId = volume.Id,
VolumeNumber = volume.Name,
})
.Join(_context.Series, s => s.readingListItem.SeriesId, series => series.Id,
.Join(_context.Series, s => s.ReadingListItem.SeriesId, series => series.Id,
(data, s) => new
{
SeriesName = s.Name,
SeriesFormat = s.Format,
s.LibraryId,
data.readingListItem,
data.ReadingListItem,
data.TotalPages,
data.ChapterNumber,
data.VolumeNumber,
data.VolumeId,
data.ReleaseDate,
data.ChapterTitleName,
LibraryType = _context.Library.Where(l => l.Id == s.LibraryId).Select(l => l.Type).Single()
})
.Select(data => new ReadingListItemDto()
{
Id = data.readingListItem.Id,
ChapterId = data.readingListItem.ChapterId,
Order = data.readingListItem.Order,
SeriesId = data.readingListItem.SeriesId,
Id = data.ReadingListItem.Id,
ChapterId = data.ReadingListItem.ChapterId,
Order = data.ReadingListItem.Order,
SeriesId = data.ReadingListItem.SeriesId,
SeriesName = data.SeriesName,
SeriesFormat = data.SeriesFormat,
PagesTotal = data.TotalPages,
@ -182,8 +188,10 @@ public class ReadingListRepository : IReadingListRepository
VolumeNumber = data.VolumeNumber,
LibraryId = data.LibraryId,
VolumeId = data.VolumeId,
ReadingListId = data.readingListItem.ReadingListId,
ReleaseDate = data.ReleaseDate
ReadingListId = data.ReadingListItem.ReadingListId,
ReleaseDate = data.ReleaseDate,
LibraryType = data.LibraryType,
ChapterTitleName = data.ChapterTitleName
})
.Where(o => userLibraries.Contains(o.LibraryId))
.OrderBy(rli => rli.Order)
@ -191,6 +199,11 @@ public class ReadingListRepository : IReadingListRepository
.AsNoTracking()
.ToListAsync();
foreach (var item in items)
{
item.Title = ReadingListHelper.FormatTitle(item);
}
// Attach progress information
var fetchedChapterIds = items.Select(i => i.ChapterId);
var progresses = await _context.AppUserProgresses

View file

@ -124,6 +124,8 @@ public interface ISeriesRepository
/// </summary>
/// <returns></returns>
Task<IDictionary<int, int>> GetLibraryIdsForSeriesAsync();
Task<IList<SeriesMetadataDto>> GetSeriesMetadataForIds(IEnumerable<int> seriesIds);
}
public class SeriesRepository : ISeriesRepository
@ -526,6 +528,19 @@ public class SeriesRepository : ISeriesRepository
return seriesChapters;
}
public async Task<IList<SeriesMetadataDto>> GetSeriesMetadataForIds(IEnumerable<int> seriesIds)
{
return await _context.SeriesMetadata
.Where(metadata => seriesIds.Contains(metadata.SeriesId))
.Include(m => m.Genres.OrderBy(g => g.NormalizedTitle))
.Include(m => m.Tags.OrderBy(g => g.NormalizedTitle))
.Include(m => m.People)
.AsNoTracking()
.ProjectTo<SeriesMetadataDto>(_mapper.ConfigurationProvider)
.AsSplitQuery()
.ToListAsync();
}
public async Task AddSeriesModifiers(int userId, List<SeriesDto> series)
{
var userProgress = await _context.AppUserProgresses