mirror of
https://github.com/Kareadita/Kavita.git
synced 2026-05-27 10:02:34 -04:00
Foundational Cover Image Rework (#584)
* Updating wording on card item when total pages is 0, to be just "Cannot Read" since it could be a non-archive file * Refactored cover images to be stored on disk. This first commit has the extraction to disk and the metadata service to handle updating when applicable. * Refactored code to have the actual save to cover image directory done by ImageService. * Implemented the ability to override cover images. * Some cleanup on Image service * Implemented the ability to cleanup old covers nightly * Added a migration to migrate existing covers to new cover image format (files). * Refactored all CoverImages to just be the filename, leaving the Join with Cover directory to higher level code. * Ensure when getting user progress, we pick the first. * Added cleanup cover images for deleted tags. Don't pull any cover images that are blank. * After series update, clear out cover image. No change on UI, but just keeps things clear before metadata refresh hits * Refactored image formats for covers to ImageService. * Fixed an issue where after refactoring how images were stored, the cleanup service was deleting them after each scan. * Changed how ShouldUpdateCoverImage works to check if file exists or not even if cover image is locked. * Fixed unit tests * Added caching back to cover images. * Caching on series as well * Code Cleanup items * Ensure when checking if a file exists in MetadataService, that we join for cover image directory. After we scan library, do one last filter to delete any series that have 0 pages total. * Catch exceptions so we don't run cover migration if this is first time run. * After a scan, only clear out the cache directory and not do a deep clean. * Implemented the ability to backup custom locked covers only. * Fixed unit tests * Trying to figure out why GA crashes when running MetadataServiceTests.cs * Some debugging on GA tests not running * Commented out tests that were causing issues in GA. * Fixed an issue where series cover images wouldn't migrate * Fixed the updating of links to actually do all series and not just locked
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Comparators;
|
||||
@@ -24,10 +25,6 @@ namespace API.Services
|
||||
private readonly IImageService _imageService;
|
||||
private readonly IHubContext<MessageHub> _messageHub;
|
||||
private readonly ChapterSortComparerZeroFirst _chapterSortComparerForInChapterSorting = new ChapterSortComparerZeroFirst();
|
||||
/// <summary>
|
||||
/// Width of the Thumbnail generation
|
||||
/// </summary>
|
||||
public static readonly int ThumbnailWidth = 320; // 153w x 230h
|
||||
|
||||
public MetadataService(IUnitOfWork unitOfWork, ILogger<MetadataService> logger,
|
||||
IArchiveService archiveService, IBookService bookService, IImageService imageService, IHubContext<MessageHub> messageHub)
|
||||
@@ -41,41 +38,55 @@ namespace API.Services
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether an entity should regenerate cover image
|
||||
/// Determines whether an entity should regenerate cover image.
|
||||
/// </summary>
|
||||
/// <remarks>If a cover image is locked but the underlying file has been deleted, this will allow regenerating. </remarks>
|
||||
/// <param name="coverImage"></param>
|
||||
/// <param name="firstFile"></param>
|
||||
/// <param name="forceUpdate"></param>
|
||||
/// <param name="isCoverLocked"></param>
|
||||
/// <param name="coverImageDirectory">Directory where cover images are. Defaults to <see cref="DirectoryService.CoverImageDirectory"/></param>
|
||||
/// <returns></returns>
|
||||
public static bool ShouldUpdateCoverImage(byte[] coverImage, MangaFile firstFile, bool forceUpdate = false,
|
||||
bool isCoverLocked = false)
|
||||
public static bool ShouldUpdateCoverImage(string coverImage, MangaFile firstFile, bool forceUpdate = false,
|
||||
bool isCoverLocked = false, string coverImageDirectory = null)
|
||||
{
|
||||
if (isCoverLocked) return false;
|
||||
if (string.IsNullOrEmpty(coverImageDirectory))
|
||||
{
|
||||
coverImageDirectory = DirectoryService.CoverImageDirectory;
|
||||
}
|
||||
|
||||
var fileExists = File.Exists(Path.Join(coverImageDirectory, coverImage));
|
||||
if (isCoverLocked && fileExists) return false;
|
||||
if (forceUpdate) return true;
|
||||
return (firstFile != null && firstFile.HasFileBeenModified()) || !HasCoverImage(coverImage);
|
||||
return (firstFile != null && firstFile.HasFileBeenModified()) || !HasCoverImage(coverImage, fileExists);
|
||||
}
|
||||
|
||||
private static bool HasCoverImage(byte[] coverImage)
|
||||
|
||||
private static bool HasCoverImage(string coverImage)
|
||||
{
|
||||
return coverImage != null && coverImage.Any();
|
||||
return HasCoverImage(coverImage, File.Exists(coverImage));
|
||||
}
|
||||
|
||||
private byte[] GetCoverImage(MangaFile file, bool createThumbnail = true)
|
||||
private static bool HasCoverImage(string coverImage, bool fileExists)
|
||||
{
|
||||
return !string.IsNullOrEmpty(coverImage) && fileExists;
|
||||
}
|
||||
|
||||
private string GetCoverImage(MangaFile file, int volumeId, int chapterId)
|
||||
{
|
||||
file.LastModified = DateTime.Now;
|
||||
switch (file.Format)
|
||||
{
|
||||
case MangaFormat.Pdf:
|
||||
case MangaFormat.Epub:
|
||||
return _bookService.GetCoverImage(file.FilePath, createThumbnail);
|
||||
return _bookService.GetCoverImage(file.FilePath, ImageService.GetChapterFormat(chapterId, volumeId));
|
||||
case MangaFormat.Image:
|
||||
var coverImage = _imageService.GetCoverFile(file);
|
||||
return _imageService.GetCoverImage(coverImage, createThumbnail);
|
||||
return _imageService.GetCoverImage(coverImage, ImageService.GetChapterFormat(chapterId, volumeId));
|
||||
case MangaFormat.Archive:
|
||||
return _archiveService.GetCoverImage(file.FilePath, createThumbnail);
|
||||
return _archiveService.GetCoverImage(file.FilePath, ImageService.GetChapterFormat(chapterId, volumeId));
|
||||
default:
|
||||
return Array.Empty<byte>();
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -91,7 +102,7 @@ namespace API.Services
|
||||
|
||||
if (ShouldUpdateCoverImage(chapter.CoverImage, firstFile, forceUpdate, chapter.CoverImageLocked))
|
||||
{
|
||||
chapter.CoverImage = GetCoverImage(firstFile);
|
||||
chapter.CoverImage = GetCoverImage(firstFile, chapter.VolumeId, chapter.Id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,7 +141,7 @@ namespace API.Services
|
||||
{
|
||||
series.Volumes ??= new List<Volume>();
|
||||
var firstCover = series.Volumes.GetCoverImage(series.Format);
|
||||
byte[] coverImage = null;
|
||||
string coverImage = null;
|
||||
if (firstCover == null && series.Volumes.Any())
|
||||
{
|
||||
// If firstCover is null and one volume, the whole series is Chapters under Vol 0.
|
||||
|
||||
Reference in New Issue
Block a user