diff --git a/API.Tests/Parser/BookParserTests.cs b/API.Tests/Parser/BookParserTests.cs index cb91fc9479..2e8e89b312 100644 --- a/API.Tests/Parser/BookParserTests.cs +++ b/API.Tests/Parser/BookParserTests.cs @@ -7,6 +7,7 @@ public class BookParserTests [Theory] [InlineData("Gifting The Wonderful World With Blessings! - 3 Side Stories [yuNS][Unknown]", "Gifting The Wonderful World With Blessings!")] [InlineData("BBC Focus 00 The Science of Happiness 2nd Edition (2018)", "BBC Focus 00 The Science of Happiness 2nd Edition")] + [InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "Faust")] public void ParseSeriesTest(string filename, string expected) { Assert.Equal(expected, API.Parser.Parser.ParseSeries(filename)); @@ -14,6 +15,7 @@ public void ParseSeriesTest(string filename, string expected) [Theory] [InlineData("Harrison, Kim - Dates from Hell - Hollows Vol 2.5.epub", "2.5")] + [InlineData("Faust - Volume 01 [Del Rey][Scans_Compressed]", "1")] public void ParseVolumeTest(string filename, string expected) { Assert.Equal(expected, API.Parser.Parser.ParseVolume(filename)); diff --git a/API/Controllers/TachiyomiController.cs b/API/Controllers/TachiyomiController.cs index 5a9fdeded7..4f1fb965ec 100644 --- a/API/Controllers/TachiyomiController.cs +++ b/API/Controllers/TachiyomiController.cs @@ -49,9 +49,8 @@ public async Task> GetLatestChapter(int seriesId) // If prevChapterId is -1, this means either nothing is read or everything is read. if (prevChapterId == -1) { - var userWithProgress = await _unitOfWork.UserRepository.GetUserByIdAsync(userId, AppUserIncludes.Progress); - var userHasProgress = - userWithProgress.Progresses.Any(x => x.SeriesId == seriesId); + var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId); + var userHasProgress = series.PagesRead == 0 || series.PagesRead < series.Pages; // If the user doesn't have progress, then return null, which the extension will catch as 204 (no content) and report nothing as read if (!userHasProgress) return null; @@ -75,7 +74,8 @@ public async Task> GetLatestChapter(int seriesId) // There is progress, we now need to figure out the highest volume or chapter and return that. var prevChapter = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(prevChapterId); var volumeWithProgress = await _unitOfWork.VolumeRepository.GetVolumeDtoAsync(prevChapter.VolumeId, userId); - if (volumeWithProgress.Number != 0) + // We only encode for single-file volumes + if (volumeWithProgress.Number != 0 && volumeWithProgress.Chapters.Count == 1) { // The progress is on a volume, encode it as a fake chapterDTO return Ok(new ChapterDto() diff --git a/API/Parser/DefaultParser.cs b/API/Parser/DefaultParser.cs index 942210532a..2d4c520e9e 100644 --- a/API/Parser/DefaultParser.cs +++ b/API/Parser/DefaultParser.cs @@ -52,9 +52,9 @@ public ParserInfo Parse(string filePath, string rootPath, LibraryType type = Lib { ret = new ParserInfo() { - Chapters = type == LibraryType.Manga ? Parser.ParseChapter(fileName) : Parser.ParseComicChapter(fileName), - Series = type == LibraryType.Manga ? Parser.ParseSeries(fileName) : Parser.ParseComicSeries(fileName), - Volumes = type == LibraryType.Manga ? Parser.ParseVolume(fileName) : Parser.ParseComicVolume(fileName), + Chapters = type == LibraryType.Comic ? Parser.ParseComicChapter(fileName) : Parser.ParseChapter(fileName), + Series = type == LibraryType.Comic ? Parser.ParseComicSeries(fileName) : Parser.ParseSeries(fileName), + Volumes = type == LibraryType.Comic ? Parser.ParseComicVolume(fileName) : Parser.ParseVolume(fileName), Filename = Path.GetFileName(filePath), Format = Parser.ParseFormat(filePath), Title = Path.GetFileNameWithoutExtension(fileName), diff --git a/API/Services/Tasks/Scanner/LibraryWatcher.cs b/API/Services/Tasks/Scanner/LibraryWatcher.cs index fb4f8abb7c..16e8107100 100644 --- a/API/Services/Tasks/Scanner/LibraryWatcher.cs +++ b/API/Services/Tasks/Scanner/LibraryWatcher.cs @@ -200,7 +200,7 @@ private void ProcessChange(string filePath, bool isDirectoryChange = false) }; if (!_scanQueue.Contains(queueItem, _folderScanQueueableComparer)) { - _logger.LogDebug("[LibraryWatcher] Queuing job for {Folder}", fullPath); + _logger.LogDebug("[LibraryWatcher] Queuing job for {Folder} at {TimeStamp}", fullPath, DateTime.Now); _scanQueue.Enqueue(queueItem); } @@ -221,12 +221,12 @@ private void ProcessQueue() _logger.LogDebug("[LibraryWatcher] Scheduling ScanSeriesFolder for {Folder}", item.FolderPath); BackgroundJob.Enqueue(() => _scannerService.ScanFolder(item.FolderPath)); _scanQueue.Dequeue(); - i++; } else { - break; + i++; } + } if (_scanQueue.Count > 0) diff --git a/API/Services/Tasks/Scanner/ProcessSeries.cs b/API/Services/Tasks/Scanner/ProcessSeries.cs index 3a281cd728..4319639b5b 100644 --- a/API/Services/Tasks/Scanner/ProcessSeries.cs +++ b/API/Services/Tasks/Scanner/ProcessSeries.cs @@ -157,18 +157,21 @@ await _eventHub.SendMessageAsync(MessageFactory.Error, series.LastFolderScanned = DateTime.Now; _unitOfWork.SeriesRepository.Attach(series); - try + if (_unitOfWork.HasChanges()) { - await _unitOfWork.CommitAsync(); - } - catch (Exception ex) - { - await _unitOfWork.RollbackAsync(); - _logger.LogCritical(ex, "[ScannerService] There was an issue writing to the for series {@SeriesName}", series); + try + { + await _unitOfWork.CommitAsync(); + } + catch (Exception ex) + { + await _unitOfWork.RollbackAsync(); + _logger.LogCritical(ex, "[ScannerService] There was an issue writing to the for series {@SeriesName}", series); - await _eventHub.SendMessageAsync(MessageFactory.Error, - MessageFactory.ErrorEvent($"There was an issue writing to the DB for Series {series}", - string.Empty)); + await _eventHub.SendMessageAsync(MessageFactory.Error, + MessageFactory.ErrorEvent($"There was an issue writing to the DB for Series {series}", + ex.Message)); + } } } catch (Exception ex) diff --git a/UI/Web/src/app/collections/collection-detail/collection-detail.component.html b/UI/Web/src/app/collections/collection-detail/collection-detail.component.html index 9c580472dd..811e375273 100644 --- a/UI/Web/src/app/collections/collection-detail/collection-detail.component.html +++ b/UI/Web/src/app/collections/collection-detail/collection-detail.component.html @@ -29,6 +29,7 @@

[filterSettings]="filterSettings" [filterOpen]="filterOpen" [parentScroll]="scrollingBlock" + [trackByIdentity]="trackByIdentity" [jumpBarKeys]="jumpbarKeys" (applyFilter)="updateFilter($event)"> diff --git a/UI/Web/src/app/collections/collection-detail/collection-detail.component.ts b/UI/Web/src/app/collections/collection-detail/collection-detail.component.ts index b292efccd7..abf55b5503 100644 --- a/UI/Web/src/app/collections/collection-detail/collection-detail.component.ts +++ b/UI/Web/src/app/collections/collection-detail/collection-detail.component.ts @@ -53,6 +53,7 @@ export class CollectionDetailComponent implements OnInit, OnDestroy, AfterConten jumpbarKeys: Array = []; filterOpen: EventEmitter = new EventEmitter(); + trackByIdentity = (index: number, item: Series) => `${item.name}_${item.localizedName}_${item.pagesRead}`; private onDestory: Subject = new Subject(); diff --git a/UI/Web/src/theme/components/_modal.scss b/UI/Web/src/theme/components/_modal.scss index ede9e7030e..6adf93ca03 100644 --- a/UI/Web/src/theme/components/_modal.scss +++ b/UI/Web/src/theme/components/_modal.scss @@ -1,7 +1,3 @@ -.modal { - z-index: 1056; // ngb v12 bug: https://github.com/ng-bootstrap/ng-bootstrap/issues/2686 -} - .modal-content { background-color: var(--bs-body-bg); color: var(--body-text-color);