Release Shakeout Part 1 (#1184)

* Have actionables on series detail action bar and in title to make it easier to use.

* Fixed a bug where super long titles could render over the book content

* Fixed a bug in get continue point where it wasn't working in an edge case
This commit is contained in:
Joseph Milazzo 2022-03-30 07:42:55 -05:00 committed by GitHub
parent 006504d30f
commit 99585279c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 45 deletions

View File

@ -0,0 +1,17 @@
using System.Linq;
using API.Comparators;
using Xunit;
namespace API.Tests.Comparers;
public class SortComparerZeroLastTests
{
[Theory]
[InlineData(new[] {0, 1, 2,}, new[] {1, 2, 0})]
[InlineData(new[] {3, 1, 2}, new[] {1, 2, 3})]
[InlineData(new[] {0, 0, 1}, new[] {1, 0, 0})]
public void SortComparerZeroLastTest(int[] input, int[] expected)
{
Assert.Equal(expected, input.OrderBy(f => f, new SortComparerZeroLast()).ToArray());
}
}

View File

@ -1625,6 +1625,11 @@ public class ReaderServiceTests
EntityFactory.CreateChapter("2", false, new List<MangaFile>(), 1), EntityFactory.CreateChapter("2", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1), EntityFactory.CreateChapter("3", false, new List<MangaFile>(), 1),
}), }),
EntityFactory.CreateVolume("1", new List<Chapter>()
{
EntityFactory.CreateChapter("11", false, new List<MangaFile>(), 1),
EntityFactory.CreateChapter("22", false, new List<MangaFile>(), 1),
}),
} }
}); });
@ -1638,33 +1643,13 @@ public class ReaderServiceTests
var readerService = new ReaderService(_unitOfWork, Substitute.For<ILogger<ReaderService>>()); var readerService = new ReaderService(_unitOfWork, Substitute.For<ILogger<ReaderService>>());
// Save progress on first volume chapters and 1st of second volume // Save progress on first volume chapters and 1st of second volume
await readerService.SaveReadingProgress(new ProgressDto() var user = await _unitOfWork.UserRepository.GetUserByIdAsync(1, AppUserIncludes.Progress);
{ await readerService.MarkSeriesAsRead(user, 1);
PageNum = 1,
ChapterId = 1,
SeriesId = 1,
VolumeId = 1
}, 1);
await readerService.SaveReadingProgress(new ProgressDto()
{
PageNum = 1,
ChapterId = 2,
SeriesId = 1,
VolumeId = 1
}, 1);
await readerService.SaveReadingProgress(new ProgressDto()
{
PageNum = 1,
ChapterId = 3,
SeriesId = 1,
VolumeId = 1
}, 1);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
var nextChapter = await readerService.GetContinuePoint(1, 1); var nextChapter = await readerService.GetContinuePoint(1, 1);
Assert.Equal("1", nextChapter.Range); Assert.Equal("11", nextChapter.Range);
} }
[Fact] [Fact]

View File

@ -45,4 +45,18 @@ namespace API.Comparators
return x.CompareTo(y); return x.CompareTo(y);
} }
} }
public class SortComparerZeroLast : IComparer<double>
{
public int Compare(double x, double y)
{
if (x == 0.0 && y == 0.0) return 0;
// if x is 0, it comes last
if (x == 0.0) return 1;
// if y is 0, it comes last
if (y == 0.0) return -1;
return x.CompareTo(y);
}
}
} }

View File

@ -403,19 +403,19 @@ public class ReaderService : IReaderService
.ToList(); .ToList();
// If there are any volumes that have progress, return those. If not, move on. // If there are any volumes that have progress, return those. If not, move on.
var currentlyReadingChapter = volumeChapters.FirstOrDefault(chapter => chapter.PagesRead < chapter.Pages); // (removed for GetContinuePoint_ShouldReturnFirstVolumeChapter_WhenPreExistingProgress), not sure if needed && chapter.PagesRead > 0 var currentlyReadingChapter = volumeChapters.FirstOrDefault(chapter => chapter.PagesRead < chapter.Pages);
if (currentlyReadingChapter != null) return currentlyReadingChapter; if (currentlyReadingChapter != null) return currentlyReadingChapter;
// Check loose leaf chapters (and specials). First check if there are any // Order with volume 0 last so we prefer the natural order
var volume = volumes.SingleOrDefault(v => v.Number == 0); return FindNextReadingChapter(volumes.OrderBy(v => v.Number, new SortComparerZeroLast()).SelectMany(v => v.Chapters).ToList());
return FindNextReadingChapter(volume == null ? volumeChapters : volume.Chapters.OrderBy(c => float.Parse(c.Number)).ToList());
} }
private static ChapterDto FindNextReadingChapter(IList<ChapterDto> volumeChapters) private static ChapterDto FindNextReadingChapter(IList<ChapterDto> volumeChapters)
{ {
var chaptersWithProgress = volumeChapters.Where(c => c.PagesRead > 0).ToList(); var chaptersWithProgress = volumeChapters.Where(c => c.PagesRead > 0).ToList();
if (chaptersWithProgress.Count > 0) if (chaptersWithProgress.Count <= 0) return volumeChapters.First();
{
var last = chaptersWithProgress.FindLastIndex(c => c.PagesRead > 0); var last = chaptersWithProgress.FindLastIndex(c => c.PagesRead > 0);
if (last + 1 < chaptersWithProgress.Count) if (last + 1 < chaptersWithProgress.Count)
{ {
@ -434,7 +434,6 @@ public class ReaderService : IReaderService
{ {
return volumeChapters.ElementAt(lastIndexWithProgress + 1); return volumeChapters.ElementAt(lastIndexWithProgress + 1);
} }
}
return volumeChapters.First(); return volumeChapters.First();
} }

View File

@ -740,7 +740,8 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
setTimeout(() => { setTimeout(() => {
this.addLinkClickHandlers(); this.addLinkClickHandlers();
this.updateReaderStyles(); this.updateReaderStyles();
this.topOffset = this.stickyTopElemRef.nativeElement?.offsetHeight; // We need to get the offset after we ensure the title has rendered
requestAnimationFrame(() => this.topOffset = this.stickyTopElemRef.nativeElement?.getBoundingClientRect().height);
const imgs = this.readingSectionElemRef.nativeElement.querySelectorAll('img'); const imgs = this.readingSectionElemRef.nativeElement.querySelectorAll('img');
if (imgs === null || imgs.length === 0) { if (imgs === null || imgs.length === 0) {

View File

@ -31,6 +31,12 @@
</span> </span>
</button> </button>
</div> </div>
<div class="col-auto ms-2">
<div class="card-actions">
<app-card-actionables [disabled]="actionInProgress" (actionHandler)="performAction($event)" [actions]="seriesActions" [labelBy]="series.name" iconClass="fa-ellipsis-h" btnClass="btn-secondary"></app-card-actionables>
</div>
</div>
<div class="col-auto ms-2" *ngIf="isAdmin || hasDownloadingRole"> <div class="col-auto ms-2" *ngIf="isAdmin || hasDownloadingRole">
<button class="btn btn-secondary" (click)="downloadSeries()" title="Download Series" [disabled]="downloadInProgress"> <button class="btn btn-secondary" (click)="downloadSeries()" title="Download Series" [disabled]="downloadInProgress">
<ng-container *ngIf="downloadInProgress; else notDownloading"> <ng-container *ngIf="downloadInProgress; else notDownloading">