mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Continue Reading Bugfix (#2010)
* Fixed an edge case where continue point wasn't considering any chapters that had progress. Continue point is now slightly faster and uses less memory. * Added a unit test for a user's case. Still not reproducible
This commit is contained in:
parent
84d45a15d0
commit
7fcec4a112
@ -1986,6 +1986,184 @@ public class ReaderServiceTests
|
|||||||
Assert.Equal(4, nextChapter.VolumeId);
|
Assert.Equal(4, nextChapter.VolumeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Volume 1-10 are fully read (single volumes),
|
||||||
|
/// Special 1 is fully read
|
||||||
|
/// Chapters 56-90 are read
|
||||||
|
/// Chapter 91 has partial progress on
|
||||||
|
/// </summary>
|
||||||
|
[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
|
#endregion
|
||||||
|
|
||||||
#region MarkChaptersUntilAsRead
|
#region MarkChaptersUntilAsRead
|
||||||
|
@ -26,6 +26,7 @@ public interface IAppUserProgressRepository
|
|||||||
Task<IEnumerable<AppUserProgress>> GetUserProgressForSeriesAsync(int seriesId, int userId);
|
Task<IEnumerable<AppUserProgress>> GetUserProgressForSeriesAsync(int seriesId, int userId);
|
||||||
Task<IEnumerable<AppUserProgress>> GetAllProgress();
|
Task<IEnumerable<AppUserProgress>> GetAllProgress();
|
||||||
Task<ProgressDto> GetUserProgressDtoAsync(int chapterId, int userId);
|
Task<ProgressDto> GetUserProgressDtoAsync(int chapterId, int userId);
|
||||||
|
Task<bool> AnyUserProgressForSeriesAsync(int seriesId, int userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AppUserProgressRepository : IAppUserProgressRepository
|
public class AppUserProgressRepository : IAppUserProgressRepository
|
||||||
@ -129,6 +130,13 @@ public class AppUserProgressRepository : IAppUserProgressRepository
|
|||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> AnyUserProgressForSeriesAsync(int seriesId, int userId)
|
||||||
|
{
|
||||||
|
return await _context.AppUserProgresses
|
||||||
|
.Where(p => p.SeriesId == seriesId && p.AppUserId == userId && p.PagesRead > 0)
|
||||||
|
.AnyAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<AppUserProgress?> GetUserProgressAsync(int chapterId, int userId)
|
public async Task<AppUserProgress?> GetUserProgressAsync(int chapterId, int userId)
|
||||||
{
|
{
|
||||||
return await _context.AppUserProgresses
|
return await _context.AppUserProgresses
|
||||||
|
@ -478,10 +478,9 @@ public class ReaderService : IReaderService
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<ChapterDto> GetContinuePoint(int seriesId, int userId)
|
public async Task<ChapterDto> GetContinuePoint(int seriesId, int userId)
|
||||||
{
|
{
|
||||||
var progress = (await _unitOfWork.AppUserProgressRepository.GetUserProgressForSeriesAsync(seriesId, userId)).ToList();
|
|
||||||
var volumes = (await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(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
|
// I think i need a way to sort volumes last
|
||||||
return volumes.OrderBy(v => double.Parse(v.Number + string.Empty), _chapterSortComparer).First().Chapters
|
return volumes.OrderBy(v => double.Parse(v.Number + string.Empty), _chapterSortComparer).First().Chapters
|
||||||
@ -523,13 +522,14 @@ public class ReaderService : IReaderService
|
|||||||
return lastChapter;
|
return lastChapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the last chapter didn't fit, then we need the next chapter without any progress
|
// If the last chapter didn't fit, then we need the next chapter without full progress
|
||||||
var firstChapterWithoutProgress = volumeChapters.FirstOrDefault(c => c.PagesRead == 0);
|
var firstChapterWithoutProgress = volumeChapters.FirstOrDefault(c => c.PagesRead < c.Pages);
|
||||||
if (firstChapterWithoutProgress != null)
|
if (firstChapterWithoutProgress != null)
|
||||||
{
|
{
|
||||||
return firstChapterWithoutProgress;
|
return firstChapterWithoutProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// chaptersWithProgress are all read, then we need to get the next chapter that doesn't have progress
|
// chaptersWithProgress are all read, then we need to get the next chapter that doesn't have progress
|
||||||
var lastIndexWithProgress = volumeChapters.IndexOf(lastChapter);
|
var lastIndexWithProgress = volumeChapters.IndexOf(lastChapter);
|
||||||
if (lastIndexWithProgress + 1 < volumeChapters.Count)
|
if (lastIndexWithProgress + 1 < volumeChapters.Count)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"name": "GPL-3.0",
|
"name": "GPL-3.0",
|
||||||
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
|
||||||
},
|
},
|
||||||
"version": "0.7.2.14"
|
"version": "0.7.2.16"
|
||||||
},
|
},
|
||||||
"servers": [
|
"servers": [
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user