Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reader Polish #2465

Merged
merged 19 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d94295e
Refactored services to the inject style
majora2007 Nov 21, 2023
bbbd46c
Cleaned up the css on the Next Expected Chapter.
majora2007 Nov 27, 2023
1dd263a
Polished the Next Chapter card
majora2007 Nov 27, 2023
d23668f
If a series has a total count of 1 and there is only a special, consi…
majora2007 Nov 27, 2023
76c69fd
Corrected the tag badge to point to new docker container. Left the pu…
majora2007 Nov 27, 2023
d831db9
Disable drag and drop on customize flows for mobile/tablet. There isn…
majora2007 Nov 27, 2023
1e8485c
Converted all accordions to the new API
majora2007 Nov 27, 2023
9c44a4a
Bumped a lot of ui dependencies
majora2007 Nov 27, 2023
f10caff
Bumped a lot of ui dependencies
majora2007 Nov 27, 2023
a23ecc1
Ui Dependencies up to date
majora2007 Nov 27, 2023
dfd1315
[BugFix] Fix page turning when dismissing book settings drawer (#2433)
Hobogrammer Nov 27, 2023
f002c3a
Fixed a bug where you could move twice with action bar pagination but…
majora2007 Nov 27, 2023
735cb98
Fixed a bug where the library type wasn't properly updating the defau…
majora2007 Nov 29, 2023
3165ae6
Code Cleanup
majora2007 Nov 30, 2023
e05d1c2
In the manga reader, added a bit of polishing and hooks to re-render …
majora2007 Nov 30, 2023
478ed42
Cleaned up some code around locking metadata fields and sorted series…
majora2007 Nov 30, 2023
43f1990
Fixed up a lot of the bugs around gazy's highlight under the paginati…
majora2007 Nov 30, 2023
71abf3c
Merge branch 'develop' into bugfix/manga-polish
majora2007 Nov 30, 2023
ecb9b52
Removed a console.log
majora2007 Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions API/Controllers/OPDSController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public async Task<IActionResult> GetSmartFilters(string apiKey)
var userId = await GetUser(apiKey);
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
return BadRequest(await _localizationService.Translate(userId, "opds-disabled"));
var (baseUrl, prefix) = await GetPrefix();
var (_, prefix) = await GetPrefix();

var filters = _unitOfWork.AppUserSmartFilterRepository.GetAllDtosByUserId(userId);
var feed = CreateFeed(await _localizationService.Translate(userId, "smartFilters"), $"{prefix}{apiKey}/smart-filters", apiKey, prefix);
Expand Down Expand Up @@ -337,7 +337,7 @@ public async Task<IActionResult> GetExternalSources(string apiKey)
var userId = await GetUser(apiKey);
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
return BadRequest(await _localizationService.Translate(userId, "opds-disabled"));
var (baseUrl, prefix) = await GetPrefix();
var (_, prefix) = await GetPrefix();

var externalSources = await _unitOfWork.AppUserExternalSourceRepository.GetExternalSources(userId);
var feed = CreateFeed(await _localizationService.Translate(userId, "external-sources"), $"{prefix}{apiKey}/external-sources", apiKey, prefix);
Expand Down Expand Up @@ -370,15 +370,13 @@ public async Task<IActionResult> GetLibraries(string apiKey)
if (!(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync()).EnableOpds)
return BadRequest(await _localizationService.Translate(userId, "opds-disabled"));
var (baseUrl, prefix) = await GetPrefix();
var libraries = await _unitOfWork.LibraryRepository.GetLibrariesForUserIdAsync(userId);
var feed = CreateFeed(await _localizationService.Translate(userId, "libraries"), $"{prefix}{apiKey}/libraries", apiKey, prefix);
SetFeedId(feed, "libraries");

// Ensure libraries follow SideNav order
var userSideNavStreams = await _unitOfWork.UserRepository.GetSideNavStreams(userId, false);
foreach (var sideNavStream in userSideNavStreams.Where(s => s.StreamType == SideNavStreamType.Library))
foreach (var library in userSideNavStreams.Where(s => s.StreamType == SideNavStreamType.Library).Select(sideNavStream => sideNavStream.Library))
{
var library = sideNavStream.Library;
feed.Entries.Add(new FeedEntry()
{
Id = library!.Id.ToString(),
Expand Down Expand Up @@ -779,13 +777,13 @@ public async Task<IActionResult> GetSeries(string apiKey, int seriesId)
var chapters = (await _unitOfWork.ChapterRepository.GetChaptersAsync(volume.Id)).OrderBy(x => double.Parse(x.Number, CultureInfo.InvariantCulture),
_chapterSortComparer);

foreach (var chapter in chapters)
foreach (var chapterId in chapters.Select(c => c.Id))
{
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapter.Id);
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapter.Id);
var files = await _unitOfWork.ChapterRepository.GetFilesForChapterAsync(chapterId);
var chapterTest = await _unitOfWork.ChapterRepository.GetChapterDtoAsync(chapterId);
foreach (var mangaFile in files)
{
feed.Entries.Add(await CreateChapterWithFile(userId, seriesId, volume.Id, chapter.Id, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
feed.Entries.Add(await CreateChapterWithFile(userId, seriesId, volume.Id, chapterId, mangaFile, series, chapterTest, apiKey, prefix, baseUrl));
}
}

Expand Down
15 changes: 10 additions & 5 deletions API/Controllers/ReaderController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,23 @@ public async Task<ActionResult> GetPdf(int chapterId, string apiKey)
/// <param name="extractPdf">Should Kavita extract pdf into images. Defaults to false.</param>
/// <returns></returns>
[HttpGet("image")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"chapterId","page", "extractPdf", "apiKey"})]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"chapterId", "page", "extractPdf", "apiKey"})]
[AllowAnonymous]
public async Task<ActionResult> GetImage(int chapterId, int page, string apiKey, bool extractPdf = false)
{
if (page < 0) page = 0;
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
if (userId == 0) return BadRequest();
var chapter = await _cacheService.Ensure(chapterId, extractPdf);
if (chapter == null) return NoContent();

try
{
if (new Random().Next(1, 10) > 5)
{
await Task.Delay(1000);
}
var chapter = await _cacheService.Ensure(chapterId, extractPdf);
if (chapter == null) return NoContent();
_logger.LogInformation("Fetching Page {PageNum} on Chapter {ChapterId}", page, chapterId);
var path = _cacheService.GetCachedPagePath(chapter.Id, page);
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
return BadRequest(await _localizationService.Translate(userId, "no-image-for-page", page));
Expand Down Expand Up @@ -245,8 +250,8 @@ public async Task<ActionResult<ChapterInfoDto>> GetChapterInfo(int chapterId, bo
LibraryId = dto.LibraryId,
IsSpecial = dto.IsSpecial,
Pages = dto.Pages,
SeriesTotalPages = series?.Pages ?? 0,
SeriesTotalPagesRead = series?.PagesRead ?? 0,
SeriesTotalPages = series.Pages,
SeriesTotalPagesRead = series.PagesRead,
ChapterTitle = dto.ChapterTitle ?? string.Empty,
Subtitle = string.Empty,
Title = dto.SeriesName,
Expand Down
2 changes: 1 addition & 1 deletion API/Data/Repositories/LibraryRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ private static LanguageDto GetCulture(string s)
{
Title = s,
IsoCode = s
};;
};
}

public IEnumerable<PublicationStatusDto> GetAllPublicationStatusesDtosForLibrariesAsync(List<int> libraryIds)
Expand Down
1 change: 1 addition & 0 deletions API/Services/DirectoryService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ public string GetParentDirectoryName(string fileOrFolder)
/// Scans a directory by utilizing a recursive folder search. If a .kavitaignore file is found, will ignore matching patterns
/// </summary>
/// <param name="folderPath"></param>
/// <param name="supportedExtensions"></param>
/// <param name="matcher"></param>
/// <returns></returns>
public IList<string> ScanFiles(string folderPath, string supportedExtensions, GlobMatcher? matcher = null)
Expand Down
2 changes: 1 addition & 1 deletion API/Services/ReaderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ public async Task<int> GetNextChapterIdAsync(int seriesId, int volumeId, int cur
// Handle Chapters within next Volume
// ! When selecting the chapter for the next volume, we need to make sure a c0 comes before a c1+
var chapters = volume.Chapters.OrderBy(x => x.Number.AsDouble(), _chapterSortComparer).ToList();
if (currentChapter.Number.Equals(Parser.DefaultChapter) && chapters.Last().Number.Equals(Parser.DefaultChapter))
if (currentChapter.Number.Equals(Parser.DefaultChapter) && chapters[^1].Number.Equals(Parser.DefaultChapter))
{
// We need to handle an extra check if the current chapter is the last special, as we should return -1
if (currentChapter.IsSpecial) return -1;
Expand Down
2 changes: 1 addition & 1 deletion API/Services/SeriesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ public async Task<NextExpectedChapterDto> GetEstimatedChapterCreationDate(int se

private static double ExponentialSmoothing(IList<double> data, double alpha)
{
var forecast = data.First();
var forecast = data[0];

foreach (var value in data)
{
Expand Down
4 changes: 2 additions & 2 deletions API/Services/StreamService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public async Task<DashboardStreamDto> CreateDashboardStreamFromSmartFilter(int u
var smartFilter = await _unitOfWork.AppUserSmartFilterRepository.GetById(smartFilterId);
if (smartFilter == null) throw new KavitaException(await _localizationService.Translate(userId, "smart-filter-doesnt-exist"));

var stream = user?.DashboardStreams.FirstOrDefault(d => d.SmartFilter?.Id == smartFilterId);
var stream = user.DashboardStreams.FirstOrDefault(d => d.SmartFilter?.Id == smartFilterId);
if (stream != null) throw new KavitaException(await _localizationService.Translate(userId, "smart-filter-already-in-use"));

var maxOrder = user!.DashboardStreams.Max(d => d.Order);
Expand Down Expand Up @@ -159,7 +159,7 @@ public async Task<SideNavStreamDto> CreateSideNavStreamFromSmartFilter(int userI
var smartFilter = await _unitOfWork.AppUserSmartFilterRepository.GetById(smartFilterId);
if (smartFilter == null) throw new KavitaException(await _localizationService.Translate(userId, "smart-filter-doesnt-exist"));

var stream = user?.SideNavStreams.FirstOrDefault(d => d.SmartFilter?.Id == smartFilterId);
var stream = user.SideNavStreams.FirstOrDefault(d => d.SmartFilter?.Id == smartFilterId);
if (stream != null) throw new KavitaException(await _localizationService.Translate(userId, "smart-filter-already-in-use"));

var maxOrder = user!.SideNavStreams.Max(d => d.Order);
Expand Down
2 changes: 1 addition & 1 deletion API/Services/TachiyomiService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public TachiyomiService(IUnitOfWork unitOfWork, IMapper mapper, ILogger<ReaderSe
if (looseLeafChapterVolume == null)
{
var volumeChapter = _mapper.Map<ChapterDto>(volumes
.Last().Chapters
[^1].Chapters
.OrderBy(c => c.Number.AsFloat(), ChapterSortComparerZeroFirst.Default)
.Last());
if (volumeChapter.Number == "0")
Expand Down
2 changes: 1 addition & 1 deletion API/Services/Tasks/Scanner/LibraryWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private void OnDeleted(object sender, FileSystemEventArgs e) {
/// <param name="e"></param>
private void OnError(object sender, ErrorEventArgs e)
{
_logger.LogError(e.GetException(), "[LibraryWatcher] An error occured, likely too many changes occured at once or the folder being watched was deleted. Restarting Watchers");
_logger.LogError(e.GetException(), "[LibraryWatcher] An error occured, likely too many changes occured at once or the folder being watched was deleted. Restarting Watchers {Current}/{Total}", _bufferFullCounter, 3);
bool condition;
lock (Lock)
{
Expand Down
1 change: 0 additions & 1 deletion API/Services/Tasks/Scanner/ParseScannedFiles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,6 @@ public async Task ScanLibrariesForSeries(Library library,
}

await _eventHub.SendMessageAsync(MessageFactory.NotificationProgress, MessageFactory.FileScanProgressEvent("File Scan Done", library.Name, ProgressEventType.Ended));
return;

async Task ProcessFolder(IList<string> files, string folder)
{
Expand Down
2 changes: 1 addition & 1 deletion API/Services/Tasks/Scanner/ProcessSeries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ public void UpdateSeriesMetadata(Series series, Library library)
if (series.Format == MangaFormat.Epub || series.Format == MangaFormat.Pdf && chapters.Count == 1)
{
series.Metadata.MaxCount = 1;
} else if (series.Metadata.TotalCount == 1 && chapters.Count == 1 && chapters.First().IsSpecial)
} else if (series.Metadata.TotalCount == 1 && chapters.Count == 1 && chapters[0].IsSpecial)
{
// If a series has a TotalCount of 1 and there is only a Special, mark it as Complete
series.Metadata.MaxCount = series.Metadata.TotalCount;
Expand Down
1 change: 1 addition & 0 deletions API/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJo
=>
{
opts.EnrichDiagnosticContext = LogEnricher.EnrichFromRequest;
opts.IncludeQueryInRequestPath = true;
});

app.Use(async (context, next) =>
Expand Down
4 changes: 3 additions & 1 deletion UI/Web/src/app/_models/series-detail/relation-kind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export enum RelationKind {
Edition = 13
}

export const RelationKinds = [
const RelationKindsUnsorted = [
{text: 'Prequel', value: RelationKind.Prequel},
{text: 'Sequel', value: RelationKind.Sequel},
{text: 'Spin Off', value: RelationKind.SpinOff},
Expand All @@ -31,3 +31,5 @@ export const RelationKinds = [
{text: 'Doujinshi', value: RelationKind.Doujinshi},
{text: 'Other', value: RelationKind.Other},
];

export const RelationKinds = RelationKindsUnsorted.slice().sort((a, b) => a.text.localeCompare(b.text));
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class BookLineOverlayComponent implements OnInit {
@Input({required: true}) pageNumber: number = 0;
@Input({required: true}) parent: ElementRef | undefined;
@Output() refreshToC: EventEmitter<void> = new EventEmitter();
@Output() isOpen: EventEmitter<boolean> = new EventEmitter(false);

xPath: string = '';
selectedText: string = '';
Expand Down Expand Up @@ -84,6 +85,8 @@ export class BookLineOverlayComponent implements OnInit {
if (!event.target) return;

if ((!selection || selection.toString().trim() === '' || selection.toString().trim() === this.selectedText)) {
event.preventDefault();
event.stopPropagation();
this.reset();
return;
}
Expand All @@ -96,6 +99,7 @@ export class BookLineOverlayComponent implements OnInit {
this.xPath = '//' + this.xPath;
}

this.isOpen.emit(true);
event.preventDefault();
event.stopPropagation();
}
Expand Down Expand Up @@ -137,6 +141,7 @@ export class BookLineOverlayComponent implements OnInit {
if (selection) {
selection.removeAllRanges();
}
this.isOpen.emit(false);
this.cdRef.markForCheck();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
<ng-container *transloco="let t; read: 'book-reader'">
<div class="fixed-top" #stickyTop>
<a class="visually-hidden-focusable focus-visible" href="javascript:void(0);" (click)="moveFocus()">{{t('skip-header')}}</a>
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
<ng-container [ngTemplateOutlet]="actionBar" [ngTemplateOutletContext]="{isTop: true}"></ng-container>
<app-book-line-overlay [parent]="bookContainerElemRef" *ngIf="page !== undefined"
[libraryId]="libraryId"
[volumeId]="volumeId"
[chapterId]="chapterId"
[seriesId]="seriesId"
[pageNumber]="pageNum"
(isOpen)="updateLineOverlayOpen($event)"
(refreshToC)="refreshPersonalToC()">
</app-book-line-overlay>
<app-drawer #commentDrawer="drawer" [(isOpen)]="drawerOpen" [options]="{topOffset: topOffset}">
Expand All @@ -18,11 +19,6 @@ <h5 class="mb-0">{{t('title')}}</h5>
<span style="font-size: 14px; color: var(--primary-color)" tabindex="0" role="button" (click)="closeReader()">{{t('close-reader')}}</span>
</div>
<div subheader>
<!-- <div class="g-0 text-center" *ngIf="!isLoading">-->
<!-- <span *ngIf="incognitoMode" (click)="turnOffIncognito()" role="button" [attr.aria-label]="t('incognito-mode-alt')">-->
<!-- (<i class="fa fa-glasses" aria-hidden="true"></i><span class="visually-hidden">{{t('incognito-mode-label')}}</span>)</span>-->
<!-- <span class="book-title-text ms-1" [ngbTooltip]="bookTitle">{{bookTitle}}</span>-->
<!-- </div>-->
<div class="pagination-cont">
<ng-container *ngIf="layoutMode !== BookPageLayoutMode.Default">
<div class="virt-pagination-cont">
Expand Down Expand Up @@ -129,13 +125,14 @@ <h5 class="mb-0">{{t('title')}}</h5>
<div *ngIf="page !== undefined && (scrollbarNeeded || layoutMode !== BookPageLayoutMode.Default) && !(writingStyle === WritingStyle.Vertical && layoutMode === BookPageLayoutMode.Default)"
(click)="$event.stopPropagation();"
[ngClass]="{'bottom-bar': layoutMode !== BookPageLayoutMode.Default}">
<ng-container [ngTemplateOutlet]="actionBar"></ng-container>
<ng-container [ngTemplateOutlet]="actionBar" [ngTemplateOutletContext]="{isTop: false}"></ng-container>
</div>
</div>
</div>
<ng-template #actionBar>
<ng-template #actionBar let-isTop>
<div class="action-bar row g-0 justify-content-between" *ngIf="!immersiveMode || drawerOpen || actionBarVisible">
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1" (click)="movePage(readingDirection === ReadingDirection.LeftToRight ? PAGING_DIRECTION.BACKWARDS : PAGING_DIRECTION.FORWARD)"
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
(click)="!isTop && movePage(readingDirection === ReadingDirection.LeftToRight ? PAGING_DIRECTION.BACKWARDS : PAGING_DIRECTION.FORWARD)"
[disabled]="readingDirection === ReadingDirection.LeftToRight ? IsPrevDisabled : IsNextDisabled"
title="{{readingDirection === ReadingDirection.LeftToRight ? t('previous') : t('next')}} Page">
<i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsPrevChapter : IsNextChapter) ? 'fa-angle-double-left' : 'fa-angle-left'}} {{readingDirection === ReadingDirection.RightToLeft ? 'next-page-highlight' : ''}}" aria-hidden="true"></i>
Expand All @@ -146,20 +143,20 @@ <h5 class="mb-0">{{t('title')}}</h5>
<button class="btn btn-secondary col-2 col-xs-1" (click)="toggleDrawer()">
<i class="fa fa-bars" aria-hidden="true"></i></button>
<div class="book-title col-2 d-none d-sm-block">
<ng-container *ngIf="isLoading; else showTitle">
@if(isLoading) {
<div class="spinner-border spinner-border-sm text-primary" style="border-radius: 50%;" role="status">
<span class="visually-hidden">{{t('loading-book')}}</span>
</div>
</ng-container>
<ng-template #showTitle>
<span *ngIf="incognitoMode" (click)="turnOffIncognito()" role="button" [attr.aria-label]="t('incognito-mode-alt')">
} @else {
<span *ngIf="incognitoMode" (click)="turnOffIncognito()" role="button" [attr.aria-label]="t('incognito-mode-alt')">
(<i class="fa fa-glasses" aria-hidden="true"></i><span class="visually-hidden">{{t('incognito-mode-label')}}</span>)</span>
<span class="book-title-text ms-1" [ngbTooltip]="bookTitle">{{bookTitle}}</span>
</ng-template>
<span class="book-title-text ms-1" [ngbTooltip]="bookTitle">{{bookTitle}}</span>
}
</div>
<button class="btn btn-secondary col-2 col-xs-1" (click)="closeReader()"><i class="fa fa-times-circle" aria-hidden="true"></i></button>
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
[disabled]="readingDirection === ReadingDirection.LeftToRight ? IsNextDisabled : IsPrevDisabled"
(click)="!isTop && movePage(readingDirection === ReadingDirection.LeftToRight ? PAGING_DIRECTION.FORWARD : PAGING_DIRECTION.BACKWARDS)"
title="{{readingDirection === ReadingDirection.LeftToRight ? t('next') : t('previous')}} Page">
<i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsNextChapter : IsPrevChapter) ? 'fa-angle-double-right' : 'fa-angle-right'}} {{readingDirection === ReadingDirection.LeftToRight ? 'next-page-highlight' : ''}}" aria-hidden="true"></i>
</button>
Expand Down
Loading
Loading