diff --git a/API.Tests/Services/ReaderServiceTests.cs b/API.Tests/Services/ReaderServiceTests.cs
index 01f94feae..36500093f 100644
--- a/API.Tests/Services/ReaderServiceTests.cs
+++ b/API.Tests/Services/ReaderServiceTests.cs
@@ -1986,6 +1986,184 @@ public class ReaderServiceTests
Assert.Equal(4, nextChapter.VolumeId);
}
+
+ ///
+ /// Volume 1-10 are fully read (single volumes),
+ /// Special 1 is fully read
+ /// Chapters 56-90 are read
+ /// Chapter 91 has partial progress on
+ ///
+ [Fact]
+ public async Task GetContinuePoint_ShouldReturnLastLooseChapter()
+ {
+ await ResetDb();
+ var series = new SeriesBuilder("Test")
+ .WithVolume(new VolumeBuilder("1")
+ .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
+ .Build())
+ .WithVolume(new VolumeBuilder("2")
+ .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("22").WithPages(1).Build())
+ .Build())
+ .WithVolume(new VolumeBuilder("0")
+ .WithChapter(new ChapterBuilder("51").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("52").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("91").WithPages(2).Build())
+ .WithChapter(new ChapterBuilder("Special").WithIsSpecial(true).WithPages(1).Build())
+ .Build())
+ .Build();
+ series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
+
+ _context.Series.Add(series);
+
+ _context.AppUser.Add(new AppUser()
+ {
+ UserName = "majora2007"
+ });
+
+ await _context.SaveChangesAsync();
+
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ 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 = 2
+ }, 1);
+
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 4,
+ SeriesId = 1,
+ VolumeId = 2
+ }, 1);
+
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 5,
+ SeriesId = 1,
+ VolumeId = 2
+ }, 1);
+
+ // Chapter 91 has partial progress, hence it should resume there
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 6,
+ SeriesId = 1,
+ VolumeId = 2
+ }, 1);
+
+ // Special is fully read
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 7,
+ SeriesId = 1,
+ VolumeId = 2
+ }, 1);
+
+ await _context.SaveChangesAsync();
+
+ var nextChapter = await _readerService.GetContinuePoint(1, 1);
+
+ Assert.Equal("91", nextChapter.Range);
+ }
+
+ [Fact]
+ public async Task GetContinuePoint_DuplicateIssueNumberBetweenChapters()
+ {
+ await ResetDb();
+ var series = new SeriesBuilder("Test")
+ .WithVolume(new VolumeBuilder("1")
+ .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("22").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
+ .Build())
+ .WithVolume(new VolumeBuilder("2")
+ .WithChapter(new ChapterBuilder("1").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("2").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("21").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("22").WithPages(1).Build())
+ .WithChapter(new ChapterBuilder("32").WithPages(1).Build())
+ .Build())
+ .Build();
+ series.Library = new LibraryBuilder("Test LIb", LibraryType.Manga).Build();
+
+ _context.Series.Add(series);
+
+ _context.AppUser.Add(new AppUser()
+ {
+ UserName = "majora2007"
+ });
+
+ await _context.SaveChangesAsync();
+
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 1,
+ SeriesId = 1,
+ VolumeId = 1
+ }, 1);
+
+ await _context.SaveChangesAsync();
+
+ var nextChapter = await _readerService.GetContinuePoint(1, 1);
+
+ Assert.Equal("2", nextChapter.Range);
+ Assert.Equal(1, nextChapter.VolumeId);
+
+ // Mark chapter 2 as read
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 2,
+ SeriesId = 1,
+ VolumeId = 1
+ }, 1);
+ await _context.SaveChangesAsync();
+
+ nextChapter = await _readerService.GetContinuePoint(1, 1);
+
+ Assert.Equal("21", nextChapter.Range);
+ Assert.Equal(1, nextChapter.VolumeId);
+
+ // Mark chapter 21 as read
+ await _readerService.SaveReadingProgress(new ProgressDto()
+ {
+ PageNum = 1,
+ ChapterId = 3,
+ SeriesId = 1,
+ VolumeId = 1
+ }, 1);
+ await _context.SaveChangesAsync();
+
+ nextChapter = await _readerService.GetContinuePoint(1, 1);
+
+ Assert.Equal("22", nextChapter.Range);
+ Assert.Equal(1, nextChapter.VolumeId);
+ }
+
+
#endregion
#region MarkChaptersUntilAsRead
diff --git a/API/Data/Repositories/AppUserProgressRepository.cs b/API/Data/Repositories/AppUserProgressRepository.cs
index a25b22fb9..44e6a21e2 100644
--- a/API/Data/Repositories/AppUserProgressRepository.cs
+++ b/API/Data/Repositories/AppUserProgressRepository.cs
@@ -26,6 +26,7 @@ public interface IAppUserProgressRepository
Task> GetUserProgressForSeriesAsync(int seriesId, int userId);
Task> GetAllProgress();
Task GetUserProgressDtoAsync(int chapterId, int userId);
+ Task AnyUserProgressForSeriesAsync(int seriesId, int userId);
}
public class AppUserProgressRepository : IAppUserProgressRepository
@@ -129,6 +130,13 @@ public class AppUserProgressRepository : IAppUserProgressRepository
.FirstOrDefaultAsync();
}
+ public async Task AnyUserProgressForSeriesAsync(int seriesId, int userId)
+ {
+ return await _context.AppUserProgresses
+ .Where(p => p.SeriesId == seriesId && p.AppUserId == userId && p.PagesRead > 0)
+ .AnyAsync();
+ }
+
public async Task GetUserProgressAsync(int chapterId, int userId)
{
return await _context.AppUserProgresses
diff --git a/API/Services/ReaderService.cs b/API/Services/ReaderService.cs
index 657431bf4..648f05dfa 100644
--- a/API/Services/ReaderService.cs
+++ b/API/Services/ReaderService.cs
@@ -478,10 +478,9 @@ public class ReaderService : IReaderService
///
public async Task GetContinuePoint(int seriesId, int userId)
{
- var progress = (await _unitOfWork.AppUserProgressRepository.GetUserProgressForSeriesAsync(seriesId, userId)).ToList();
var volumes = (await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId)).ToList();
- if (progress.Count == 0)
+ if (!await _unitOfWork.AppUserProgressRepository.AnyUserProgressForSeriesAsync(seriesId, userId))
{
// I think i need a way to sort volumes last
return volumes.OrderBy(v => double.Parse(v.Number + string.Empty), _chapterSortComparer).First().Chapters
@@ -523,13 +522,14 @@ public class ReaderService : IReaderService
return lastChapter;
}
- // If the last chapter didn't fit, then we need the next chapter without any progress
- var firstChapterWithoutProgress = volumeChapters.FirstOrDefault(c => c.PagesRead == 0);
+ // If the last chapter didn't fit, then we need the next chapter without full progress
+ var firstChapterWithoutProgress = volumeChapters.FirstOrDefault(c => c.PagesRead < c.Pages);
if (firstChapterWithoutProgress != null)
{
return firstChapterWithoutProgress;
}
+
// chaptersWithProgress are all read, then we need to get the next chapter that doesn't have progress
var lastIndexWithProgress = volumeChapters.IndexOf(lastChapter);
if (lastIndexWithProgress + 1 < volumeChapters.Count)
diff --git a/openapi.json b/openapi.json
index ee8713e0e..f3666479e 100644
--- a/openapi.json
+++ b/openapi.json
@@ -7,7 +7,7 @@
"name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
},
- "version": "0.7.2.14"
+ "version": "0.7.2.16"
},
"servers": [
{