Reading List Detail Overhaul + More Bugfixes and Polish (#3687)

Co-authored-by: Yongun Seong <yseong.p@gmail.com>
This commit is contained in:
Joe Milazzo 2025-03-29 19:47:53 -05:00 committed by GitHub
parent b2ee651fb8
commit dad212bfb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 5056 additions and 729 deletions

View file

@ -213,7 +213,6 @@ public class LibraryController : BaseApiController
var ret = _unitOfWork.LibraryRepository.GetLibraryDtosForUsernameAsync(username);
await _libraryCacheProvider.SetAsync(CacheKey, ret, TimeSpan.FromHours(24));
_logger.LogDebug("Caching libraries for {Key}", cacheKey);
return Ok(ret);
}
@ -419,8 +418,7 @@ public class LibraryController : BaseApiController
.Distinct()
.Select(Services.Tasks.Scanner.Parser.Parser.NormalizePath);
var seriesFolder = _directoryService.FindHighestDirectoriesFromFiles(libraryFolder,
new List<string>() {dto.FolderPath});
var seriesFolder = _directoryService.FindHighestDirectoriesFromFiles(libraryFolder, [dto.FolderPath]);
_taskScheduler.ScanFolder(seriesFolder.Keys.Count == 1 ? seriesFolder.Keys.First() : dto.FolderPath);

View file

@ -46,8 +46,8 @@ public class LocaleController : BaseApiController
}
var ret = _localizationService.GetLocales().Where(l => l.TranslationCompletion > 0f);
await _localeCacheProvider.SetAsync(CacheKey, ret, TimeSpan.FromDays(7));
await _localeCacheProvider.SetAsync(CacheKey, ret, TimeSpan.FromDays(1));
return Ok();
return Ok(ret);
}
}

View file

@ -803,7 +803,7 @@ public class ReaderController : BaseApiController
/// <param name="seriesId"></param>
/// <returns></returns>
[HttpGet("time-left")]
[ResponseCache(CacheProfileName = "Hour", VaryByQueryKeys = ["seriesId"])]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = ["seriesId"])]
public async Task<ActionResult<HourEstimateRangeDto>> GetEstimateToCompletion(int seriesId)
{
var userId = User.GetUserId();

View file

@ -6,6 +6,7 @@ using API.Data;
using API.Data.Repositories;
using API.DTOs;
using API.DTOs.ReadingLists;
using API.Entities.Enums;
using API.Extensions;
using API.Helpers;
using API.Services;
@ -23,13 +24,15 @@ public class ReadingListController : BaseApiController
private readonly IUnitOfWork _unitOfWork;
private readonly IReadingListService _readingListService;
private readonly ILocalizationService _localizationService;
private readonly IReaderService _readerService;
public ReadingListController(IUnitOfWork unitOfWork, IReadingListService readingListService,
ILocalizationService localizationService)
ILocalizationService localizationService, IReaderService readerService)
{
_unitOfWork = unitOfWork;
_readingListService = readingListService;
_localizationService = localizationService;
_readerService = readerService;
}
/// <summary>
@ -128,7 +131,7 @@ public class ReadingListController : BaseApiController
}
/// <summary>
/// Deletes a list item from the list. Will reorder all item positions afterwards
/// Deletes a list item from the list. Item orders will update as a result.
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
@ -452,26 +455,38 @@ public class ReadingListController : BaseApiController
return Ok(await _localizationService.Translate(User.GetUserId(), "nothing-to-do"));
}
/// <summary>
/// Returns a list of characters associated with the reading list
/// Returns a list of a given role associated with the reading list
/// </summary>
/// <param name="readingListId"></param>
/// <param name="role">PersonRole</param>
/// <returns></returns>
[HttpGet("people")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.TenMinute, VaryByQueryKeys = ["readingListId", "role"])]
public ActionResult<IEnumerable<PersonDto>> GetPeopleByRoleForList(int readingListId, PersonRole role)
{
return Ok(_unitOfWork.ReadingListRepository.GetReadingListPeopleAsync(readingListId, role));
}
/// <summary>
/// Returns all people in given roles for a reading list
/// </summary>
/// <param name="readingListId"></param>
/// <returns></returns>
[HttpGet("characters")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.TenMinute)]
public ActionResult<IEnumerable<PersonDto>> GetCharactersForList(int readingListId)
[HttpGet("all-people")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.TenMinute, VaryByQueryKeys = ["readingListId"])]
public async Task<ActionResult<IEnumerable<PersonDto>>> GetAllPeopleForList(int readingListId)
{
return Ok(_unitOfWork.ReadingListRepository.GetReadingListCharactersAsync(readingListId));
return Ok(await _unitOfWork.ReadingListRepository.GetReadingListAllPeopleAsync(readingListId));
}
/// <summary>
/// Returns the next chapter within the reading list
/// </summary>
/// <param name="currentChapterId"></param>
/// <param name="readingListId"></param>
/// <returns>Chapter Id for next item, -1 if nothing exists</returns>
/// <returns>Chapter ID for next item, -1 if nothing exists</returns>
[HttpGet("next-chapter")]
public async Task<ActionResult<int>> GetNextChapter(int currentChapterId, int readingListId)
{
@ -577,4 +592,26 @@ public class ReadingListController : BaseApiController
return Ok();
}
/// <summary>
/// Returns random information about a Reading List
/// </summary>
/// <param name="readingListId"></param>
/// <returns></returns>
[HttpGet("info")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = ["readingListId"])]
public async Task<ActionResult<ReadingListInfoDto?>> GetReadingListInfo(int readingListId)
{
var result = await _unitOfWork.ReadingListRepository.GetReadingListInfoAsync(readingListId);
if (result == null) return Ok(null);
var timeEstimate = _readerService.GetTimeEstimate(result.WordCount, result.Pages, result.IsAllEpub);
result.MinHoursToRead = timeEstimate.MinHours;
result.AvgHoursToRead = timeEstimate.AvgHours;
result.MaxHoursToRead = timeEstimate.MaxHours;
return Ok(result);
}
}

View file

@ -238,7 +238,8 @@ public class SeriesController : BaseApiController
// Trigger a refresh when we are moving from a locked image to a non-locked
needsRefreshMetadata = true;
series.CoverImage = null;
series.CoverImageLocked = updateSeries.CoverImageLocked;
series.CoverImageLocked = false;
_logger.LogDebug("[SeriesCoverImageBug] Setting Series Cover Image to null: {SeriesId}", series.Id);
series.ResetColorScape();
}