diff --git a/API/Controllers/AccountController.cs b/API/Controllers/AccountController.cs index 86b1ac778..3c9960402 100644 --- a/API/Controllers/AccountController.cs +++ b/API/Controllers/AccountController.cs @@ -95,7 +95,7 @@ namespace API.Controllers var settings = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync(); if (!settings.EnableAuthentication && !registerDto.IsAdmin) { - _logger.LogInformation("User {UserName} is being registered as non-admin with no server authentication. Using default password.", registerDto.Username); + _logger.LogInformation("User {UserName} is being registered as non-admin with no server authentication. Using default password", registerDto.Username); registerDto.Password = AccountService.DefaultPassword; } diff --git a/API/Services/ArchiveService.cs b/API/Services/ArchiveService.cs index 10d45f232..2eb59a9fc 100644 --- a/API/Services/ArchiveService.cs +++ b/API/Services/ArchiveService.cs @@ -138,6 +138,22 @@ namespace API.Services if (!string.IsNullOrEmpty(nonNestedFile)) return nonNestedFile; + // Check the first folder and sort within that to see if we can find a file, else fallback to first file with basic sort. + // Get first folder, then sort within that + var firstDirectoryFile = fullNames.OrderBy(Path.GetDirectoryName, new NaturalSortComparer()).FirstOrDefault(); + if (!string.IsNullOrEmpty(firstDirectoryFile)) + { + var firstDirectory = Path.GetDirectoryName(firstDirectoryFile); + if (!string.IsNullOrEmpty(firstDirectory)) + { + var firstDirectoryResult = fullNames.Where(f => firstDirectory.Equals(Path.GetDirectoryName(f))) + .OrderBy(Path.GetFileName, new NaturalSortComparer()) + .FirstOrDefault(); + + if (!string.IsNullOrEmpty(firstDirectoryResult)) return firstDirectoryResult; + } + } + var result = fullNames .OrderBy(Path.GetFileName, new NaturalSortComparer()) .FirstOrDefault(); @@ -159,7 +175,7 @@ namespace API.Services /// public string GetCoverImage(string archivePath, string fileName) { - if (archivePath == null || !IsValidArchive(archivePath)) return String.Empty; + if (archivePath == null || !IsValidArchive(archivePath)) return string.Empty; try { var libraryHandler = CanOpen(archivePath); diff --git a/API/Services/MetadataService.cs b/API/Services/MetadataService.cs index 5d86f0766..f7ac6ef5e 100644 --- a/API/Services/MetadataService.cs +++ b/API/Services/MetadataService.cs @@ -218,7 +218,7 @@ namespace API.Services var stopwatch = Stopwatch.StartNew(); var totalTime = 0L; _logger.LogInformation("[MetadataService] Refreshing Library {LibraryName}. Total Items: {TotalSize}. Total Chunks: {TotalChunks} with {ChunkSize} size", library.Name, chunkInfo.TotalSize, chunkInfo.TotalChunks, chunkInfo.ChunkSize); - await _messageHub.Clients.All.SendAsync(SignalREvents.ScanLibraryProgress, + await _messageHub.Clients.All.SendAsync(SignalREvents.RefreshMetadataProgress, MessageFactory.RefreshMetadataProgressEvent(library.Id, 0F)); var i = 0; @@ -281,11 +281,11 @@ namespace API.Services chunk * chunkInfo.ChunkSize, (chunk * chunkInfo.ChunkSize) + nonLibrarySeries.Count, chunkInfo.TotalSize, stopwatch.ElapsedMilliseconds, library.Name); } var progress = Math.Max(0F, Math.Min(100F, i * 1F / chunkInfo.TotalChunks)); - await _messageHub.Clients.All.SendAsync(SignalREvents.ScanLibraryProgress, + await _messageHub.Clients.All.SendAsync(SignalREvents.RefreshMetadataProgress, MessageFactory.RefreshMetadataProgressEvent(library.Id, progress)); } - await _messageHub.Clients.All.SendAsync(SignalREvents.ScanLibraryProgress, + await _messageHub.Clients.All.SendAsync(SignalREvents.RefreshMetadataProgress, MessageFactory.RefreshMetadataProgressEvent(library.Id, 100F)); _logger.LogInformation("[MetadataService] Updated metadata for {SeriesNumber} series in library {LibraryName} in {ElapsedMilliseconds} milliseconds total", chunkInfo.TotalSize, library.Name, totalTime); diff --git a/UI/Web/src/app/manga-reader/infinite-scroller/infinite-scroller.component.ts b/UI/Web/src/app/manga-reader/infinite-scroller/infinite-scroller.component.ts index b97f5f014..7b4ff0712 100644 --- a/UI/Web/src/app/manga-reader/infinite-scroller/infinite-scroller.component.ts +++ b/UI/Web/src/app/manga-reader/infinite-scroller/infinite-scroller.component.ts @@ -187,7 +187,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy { /** * On scroll in document, calculate if the user/javascript has scrolled to the current image element (and it's visible), update that scrolling has ended completely, - * and calculate the direction the scrolling is occuring. This is used for prefetching. + * and calculate the direction the scrolling is occuring. This is not used for prefetching. * @param event Scroll Event */ handleScrollEvent(event?: any) { @@ -247,11 +247,11 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy { if (this.atTop && this.pageNum > 0) { this.atTop = false; } - // debug mode will add an extra pixel from the image border + (this.debug ? 1 : 0) + if (totalScroll === totalHeight && !this.atBottom) { this.atBottom = true; this.setPageNum(this.totalPages); - this.debugLog('At last page, saving last page ', this.totalPages); + // Scroll user back to original location this.previousScrollHeightMinusTop = this.getScrollTop(); requestAnimationFrame(() => document.documentElement.scrollTop = this.previousScrollHeightMinusTop + (SPACER_SCROLL_INTO_PX / 2)); @@ -312,19 +312,6 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy { rect.left <= (window.innerWidth || document.documentElement.clientWidth) ) { const topX = (window.innerHeight || document.documentElement.clientHeight); - const bottomX = this.getScrollTop(); - - // Check if the image is mostly above the cuttoff point - const cuttoffPoint = bottomX - ((bottomX - topX) / 2); - // without this, it will only trigger once you get the top of the image to the top of the screen: && rect.bottom > cuttoffPoint - // with it, it will trigger at half way - //console.log('Cutoff point: ', cuttoffPoint); - //return rect.top <= cuttoffPoint ; // && rect.bottom > cuttoffPoint - // console.log('device height: ', topX); - // console.log('image ' + elem.getAttribute('page') + ' top: ', rect.top); - // console.log('amount scrolled down: ', rect.top / topX); - // console.log('cutoff point: ', cuttoffPoint); - return Math.abs(rect.top / topX) <= 0.25; } return false; @@ -428,6 +415,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy { * Performs the scroll for the current page element. Updates any state variables needed. */ scrollToCurrentPage() { + this.debugLog('Scrolling to ', this.pageNum); this.currentPageElem = document.querySelector('img#page-' + this.pageNum); if (!this.currentPageElem) { return; } diff --git a/UI/Web/src/app/manga-reader/manga-reader.component.ts b/UI/Web/src/app/manga-reader/manga-reader.component.ts index 08a3a5dc4..915cdfa27 100644 --- a/UI/Web/src/app/manga-reader/manga-reader.component.ts +++ b/UI/Web/src/app/manga-reader/manga-reader.component.ts @@ -426,7 +426,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { this.maxPages = results.chapterInfo.pages; let page = results.progress.pageNum; if (page > this.maxPages) { - page = this.maxPages - 1; + page = this.maxPages; } this.setPageNum(page); @@ -900,16 +900,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { loadPage() { if (!this.canvas || !this.ctx) { return; } - // Due to the fact that we start at image 0, but page 1, we need the last page to have progress as page + 1 to be completed - let pageNum = this.pageNum; - if (this.pageNum == this.maxPages - 1) { - pageNum = this.pageNum + 1; - } - - if (!this.incognitoMode) { - this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, pageNum).pipe(take(1)).subscribe(() => {/* No operation */}); - } - this.isLoading = true; this.canvasImage = this.cachedImages.current(); if (this.readerService.imageUrlToPageNum(this.canvasImage.src) !== this.pageNum || this.canvasImage.src === '' || !this.canvasImage.complete) { @@ -987,6 +977,16 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { }); } } + + // Due to the fact that we start at image 0, but page 1, we need the last page to have progress as page + 1 to be completed + let tempPageNum = this.pageNum; + if (this.pageNum == this.maxPages - 1) { + tempPageNum = this.pageNum + 1; + } + + if (!this.incognitoMode) { + this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, tempPageNum).pipe(take(1)).subscribe(() => {/* No operation */}); + } } goToPage(pageNum: number) { @@ -1066,8 +1066,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { handleWebtoonPageChange(updatedPageNum: number) { this.setPageNum(updatedPageNum); - if (this.incognitoMode) return; - this.readerService.saveProgress(this.seriesId, this.volumeId, this.chapterId, this.pageNum).pipe(take(1)).subscribe(() => {/* No operation */}); } /**