More Reader Fixes (#1696)

* Fixed resizing or layout changes causing page change on double reader

* Implemented the debug log pattern on double renderers. Fixed a case when navigation backwards and showing only one page. Updated so go to page or slider update will handle selecting the right page number for pair display.

* All Spread cases for double working

* Cleanup dead code

* Ensure we can jump to last page
This commit is contained in:
Joe Milazzo 2022-12-13 15:57:51 -06:00 committed by GitHub
parent 90d5834ffa
commit c640ae3637
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 146 additions and 104 deletions

View File

@ -310,6 +310,16 @@ public class StatisticService : IStatisticService
.ToListAsync();
}
public void ReadCountByDay()
{
// _context.AppUserProgresses
// .GroupBy(p => p.LastModified.Day)
// .Select(g =>
// {
// Day = g.Key,
// })
}
public Task<IEnumerable<ReadHistoryEvent>> GetHistory()
{
// _context.AppUserProgresses

View File

@ -162,6 +162,7 @@ export class CanvasRendererComponent implements OnInit, AfterViewInit, OnDestroy
return needsSplitting;
}
isValid() {
return this.renderWithCanvas;
}

View File

@ -7,7 +7,7 @@ import { ReaderService } from 'src/app/_services/reader.service';
import { LayoutMode } from '../../_models/layout-mode';
import { FITTING_OPTION, PAGING_DIRECTION } from '../../_models/reader-enums';
import { ReaderSetting } from '../../_models/reader-setting';
import { ImageRenderer } from '../../_models/renderer';
import { DEBUG_MODES, ImageRenderer } from '../../_models/renderer';
import { ManagaReaderService } from '../../_series/managa-reader.service';
/**
@ -26,11 +26,10 @@ export class DoubleRendererComponent implements OnInit, OnDestroy, ImageRenderer
@Input() bookmark$!: Observable<number>;
@Input() showClickOverlay$!: Observable<boolean>;
@Input() pageNum$!: Observable<{pageNum: number, maxPages: number}>;
@Input() getPage!: (pageNum: number) => HTMLImageElement;
@Output() imageHeight: EventEmitter<number> = new EventEmitter<number>();
debugMode: DEBUG_MODES = DEBUG_MODES.None;
imageFitClass$!: Observable<string>;
showClickOverlayClass$!: Observable<string>;
readerModeClass$!: Observable<string>;
@ -61,6 +60,7 @@ export class DoubleRendererComponent implements OnInit, OnDestroy, ImageRenderer
*/
shouldRenderDouble$!: Observable<boolean>;
private readonly onDestroy = new Subject<void>();
get ReaderMode() {return ReaderMode;}
@ -172,22 +172,27 @@ export class DoubleRendererComponent implements OnInit, OnDestroy, ImageRenderer
if (!this.isValid()) return false;
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Not rendering double as current page is cover image');
this.debugLog('Not rendering double as current page is cover image');
return false;
}
if (this.mangaReaderService.isWidePage(this.pageNum) ) {
console.log('Not rendering double as current page is wide image');
this.debugLog('Not rendering double as current page is wide image');
return false;
}
if (this.mangaReaderService.isSecondLastImage(this.pageNum, this.maxPages)) {
this.debugLog('Not rendering double as current page is last');
return false;
}
if (this.mangaReaderService.isLastImage(this.pageNum, this.maxPages)) {
console.log('Not rendering double as current page is last and there are an odd number of pages');
this.debugLog('Not rendering double as current page is last');
return false;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1) ) {
console.log('Not rendering double as next page is wide image');
this.debugLog('Not rendering double as next page is wide image');
return false;
}
@ -225,49 +230,66 @@ export class DoubleRendererComponent implements OnInit, OnDestroy, ImageRenderer
switch (direction) {
case PAGING_DIRECTION.FORWARD:
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Moving forward 1 page as on cover image');
this.debugLog('Moving forward 1 page as on cover image');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
console.log('Moving forward 1 page as current page is wide');
this.debugLog('Moving forward 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1)) {
console.log('Moving forward 1 page as next page is wide');
this.debugLog('Moving forward 1 page as next page is wide');
return 1;
}
if (this.mangaReaderService.isSecondLastImage(this.pageNum, this.maxPages)) {
console.log('Moving forward 1 page as 2 pages left');
this.debugLog('Moving forward 1 page as 2 pages left');
return 1;
}
if (this.mangaReaderService.isLastImage(this.pageNum, this.maxPages)) {
console.log('Moving forward 1 page as 1 page left');
this.debugLog('Moving forward 1 page as 1 page left');
return 1;
}
console.log('Moving forward 2 pages');
this.debugLog('Moving forward 2 pages');
return 2;
case PAGING_DIRECTION.BACKWARDS:
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Moving back 1 page as on cover image');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
console.log('Moving back 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 1)) {
console.log('Moving back 1 page as prev page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 2)) {
console.log('Moving back 1 page as 2 pages back is wide');
this.debugLog('Moving back 1 page as on cover image');
return 1;
}
console.log('Moving back 2 pages');
if (this.mangaReaderService.adjustForDoubleReader(this.pageNum - 1) != this.pageNum - 1 && !this.mangaReaderService.isWidePage(this.pageNum - 2)) {
this.debugLog('Moving back 2 pages as previous pair should be in a pair');
return 2;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
this.debugLog('Moving back 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 1)) {
this.debugLog('Moving back 1 page as prev page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 2)) {
this.debugLog('Moving back 1 page as 2 pages back is wide');
return 1;
}
this.debugLog('Moving back 2 pages');
return 2;
}
}
reset(): void {}
debugLog(message: string, extraData?: any) {
if (!(this.debugMode & DEBUG_MODES.Logs)) return;
if (extraData !== undefined) {
console.log(message, extraData);
} else {
console.log(message);
}
}
}

View File

@ -7,7 +7,7 @@ import { ReaderService } from 'src/app/_services/reader.service';
import { LayoutMode } from '../../_models/layout-mode';
import { FITTING_OPTION, PAGING_DIRECTION } from '../../_models/reader-enums';
import { ReaderSetting } from '../../_models/reader-setting';
import { ImageRenderer } from '../../_models/renderer';
import { DEBUG_MODES, ImageRenderer } from '../../_models/renderer';
import { ManagaReaderService } from '../../_series/managa-reader.service';
/**
@ -28,11 +28,11 @@ export class DoubleReverseRendererComponent implements OnInit, OnDestroy, ImageR
@Input() bookmark$!: Observable<number>;
@Input() showClickOverlay$!: Observable<boolean>;
@Input() pageNum$!: Observable<{pageNum: number, maxPages: number}>;
@Input() getPage!: (pageNum: number) => HTMLImageElement;
@Output() imageHeight: EventEmitter<number> = new EventEmitter<number>();
debugMode: DEBUG_MODES = DEBUG_MODES.None;
imageFitClass$!: Observable<string>;
showClickOverlayClass$!: Observable<string>;
readerModeClass$!: Observable<string>;
@ -115,8 +115,8 @@ export class DoubleReverseRendererComponent implements OnInit, OnDestroy, ImageR
this.shouldRenderDouble$ = this.pageNum$.pipe(
takeUntil(this.onDestroy),
map((_) => this.shouldRenderDouble()),
filter(_ => this.isValid()),
map(() => this.shouldRenderDouble()),
filter(() => this.isValid()),
shareReplay()
);
@ -173,22 +173,27 @@ export class DoubleReverseRendererComponent implements OnInit, OnDestroy, ImageR
if (!this.isValid()) return false;
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Not rendering double as current page is cover image');
this.debugLog('Not rendering double as current page is cover image');
return false;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
console.log('Not rendering double as current page is wide image');
this.debugLog('Not rendering double as current page is wide image');
return false;
}
if (this.mangaReaderService.isSecondLastImage(this.pageNum, this.maxPages)) {
this.debugLog('Not rendering double as current page is last');
return false;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1) ) {
console.log('Not rendering double as next page is wide image');
this.debugLog('Not rendering double as next page is wide image');
return false;
}
if (this.mangaReaderService.isLastImage(this.pageNum, this.maxPages)) {
console.log('Not rendering double as current page is last and there are an odd number of pages');
this.debugLog('Not rendering double as current page is last and there are an odd number of pages');
return false;
}
@ -219,92 +224,85 @@ export class DoubleReverseRendererComponent implements OnInit, OnDestroy, ImageR
switch (direction) {
case PAGING_DIRECTION.FORWARD:
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Moving forward 1 page as on cover image');
this.debugLog('Moving forward 1 page as on cover image');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
this.debugLog('Moving forward 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1)) {
this.debugLog('Moving forward 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isSecondLastImage(this.pageNum, this.maxPages)) {
console.log('Moving forward 1 page as 2 pages left');
this.debugLog('Moving forward 1 page as 2 pages left');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
console.log('Moving forward 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1)) {
console.log('Moving forward 1 page as current page is wide');
return 1;
}
if (this.mangaReaderService.isLastImage(this.pageNum + 1, this.maxPages)) {
console.log('Moving forward 2 pages as right image is the last page and we just rendered double page');
return 2;
}
if (this.pageNum === this.maxPages - 1) {
console.log('Moving forward 0 page as on last page');
return 0;
}
if (this.mangaReaderService.isLastImage(this.pageNum, this.maxPages)) {
console.log('Moving forward 1 page as 1 page left');
return 1;
this.debugLog('Moving forward 2 pages as right image is the last page and we just rendered double page');
return 2;
}
console.log('Moving forward 2 pages');
this.debugLog('Moving forward 2 pages');
return 2;
case PAGING_DIRECTION.BACKWARDS:
if (this.mangaReaderService.isCoverImage(this.pageNum)) {
console.log('Moving back 1 page as on cover image');
this.debugLog('Moving back 1 page as on cover image');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 1)) {
console.log('Moving back 2 page as right page is wide');
if (this.mangaReaderService.adjustForDoubleReader(this.pageNum - 1) != this.pageNum - 1 && !this.mangaReaderService.isWidePage(this.pageNum - 2)) {
this.debugLog('Moving back 2 pages as previous pair should be in a pair');
return 2;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 2)) {
console.log('Moving back 1 page as coming from wide page');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum)) {
console.log('Moving back 1 page as left page is wide');
this.debugLog('Moving back 1 page as left page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum) && (!this.mangaReaderService.isWidePage(this.pageNum - 4))) {
console.log('Moving back 1 page as left page is wide');
this.debugLog('Moving back 1 page as left page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 1)) {
console.log('Moving back 1 page as prev page is wide');
this.debugLog('Moving back 1 page as prev page is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum - 2)) {
console.log('Moving back 1 page as 2 pages back is wide');
this.debugLog('Moving back 1 page as 2 pages back is wide');
return 1;
}
if (this.mangaReaderService.isWidePage(this.pageNum + 2)) {
console.log('Moving back 2 page as 2 pages back is wide');
this.debugLog('Moving back 2 page as 2 pages back is wide');
return 1;
}
// Not sure about this condition on moving backwards
if (this.mangaReaderService.isSecondLastImage(this.pageNum, this.maxPages)) {
console.log('Moving back 1 page as 2 pages left');
this.debugLog('Moving back 1 page as 2 pages left');
return 1;
}
console.log('Moving back 2 pages');
this.debugLog('Moving back 2 pages');
return 2;
}
}
reset(): void {}
debugLog(message: string, extraData?: any) {
if (!(this.debugMode & DEBUG_MODES.Logs)) return;
if (extraData !== undefined) {
console.log(message, extraData);
} else {
console.log(message);
}
}
}

View File

@ -32,8 +32,6 @@ const enum DEBUG_MODES {
* Turn on Page outline
*/
Outline = 8
}
@Component({

View File

@ -473,16 +473,12 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
this.generalSettingsForm.get('pageSplitOption')?.disable();
this.generalSettingsForm.get('fittingOption')?.setValue(this.mangaReaderService.translateScalingOption(ScalingOption.FitToHeight));
this.generalSettingsForm.get('fittingOption')?.disable();
// If we are in double mode, we need to check if our current page is on a right edge or not, if so adjust by decrementing by 1
if (this.readerMode !== ReaderMode.Webtoon) {
this.setPageNum(this.mangaReaderService.adjustForDoubleReader(this.pageNum));
}
}
this.cdRef.markForCheck();
// Re-render the current page when we switch layouts
if (changeOccurred) {
this.setPageNum(this.adjustPagesForDoubleRenderer(this.pageNum));
this.loadPage();
}
});
@ -604,6 +600,15 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
};
}
// If we are in double mode, we need to check if our current page is on a right edge or not, if so adjust by decrementing by 1
adjustPagesForDoubleRenderer(pageNum: number) {
if (pageNum === this.maxPages - 1) return pageNum;
if (this.readerMode !== ReaderMode.Webtoon && this.layoutMode !== LayoutMode.Single) {
return this.mangaReaderService.adjustForDoubleReader(pageNum);
}
return pageNum;
}
disableDoubleRendererIfScreenTooSmall() {
if (window.innerWidth > window.innerHeight) {
this.generalSettingsForm.get('layoutMode')?.enable();
@ -736,10 +741,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
page = this.maxPages - 1;
}
// If we are in double mode, we need to check if our current page is on a right edge or not, if so adjust by decrementing by 1
if (this.layoutMode !== LayoutMode.Single && this.readerMode !== ReaderMode.Webtoon) {
page = this.mangaReaderService.adjustForDoubleReader(page);
}
page = this.adjustPagesForDoubleRenderer(page);
this.setPageNum(page); // first call
this.goToPageEvent = new BehaviorSubject<number>(this.pageNum);
@ -1121,9 +1123,9 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
this.pagingDirectionSubject.next(PAGING_DIRECTION.BACKWARDS);
}
this.setPageNum(page);
this.setPageNum(this.adjustPagesForDoubleRenderer(page));
this.refreshSlider.emit();
this.goToPageEvent.next(page);
this.goToPageEvent.next(this.pageNum);
this.render();
}
@ -1179,7 +1181,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
this.pagingDirectionSubject.next(PAGING_DIRECTION.BACKWARDS);
}
this.setPageNum(page);
this.setPageNum(this.adjustPagesForDoubleRenderer(page));
this.goToPageEvent.next(page);
this.render();
}

View File

@ -58,6 +58,8 @@ export class SingleRendererComponent implements OnInit, OnDestroy, ImageRenderer
tap(pageInfo => {
this.pageNum = pageInfo.pageNum;
this.maxPages = pageInfo.maxPages;
// TODO: Put this here this.currentImage = this.getPagez
}),
).subscribe(() => {});
@ -125,11 +127,6 @@ export class SingleRendererComponent implements OnInit, OnDestroy, ImageRenderer
if (img === null || img.length === 0 || img[0] === null) return;
if (!this.isValid()) return;
// This seems to cause a problem after rendering a split
//if (this.mangaReaderService.shouldSplit(this.currentImage, this.pageSplit)) return;
this.currentImage = img[0];
this.cdRef.markForCheck();
this.imageHeight.emit(this.currentImage.height);

View File

@ -2,6 +2,21 @@ import { Observable } from "rxjs";
import { PAGING_DIRECTION } from "./reader-enums";
import { ReaderSetting } from "./reader-setting";
/**
* Bitwise enums for configuring how much debug information we want
*/
export const enum DEBUG_MODES {
/**
* No Debug information
*/
None = 0,
/**
* Turn on debug logging
*/
Logs = 2,
}
/**
* A generic interface for an image renderer
*/
@ -40,6 +55,4 @@ export interface ImageRenderer {
* This should reset any needed state, but not unset the image.
*/
reset(): void;
}

View File

@ -39,6 +39,7 @@ export class ManagaReaderService {
i++;
});
console.log('pairs: ', this.pairs);
}
adjustForDoubleReader(page: number) {
@ -94,7 +95,7 @@ export class ManagaReaderService {
* If the current page is second to last image
*/
isSecondLastImage(pageNum: number, maxPages: number) {
return maxPages - 2 === pageNum;
return (maxPages - 2) === pageNum;
}
/**

View File

@ -7,7 +7,7 @@
"name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
},
"version": "0.6.1.14"
"version": "0.6.1.15"
},
"servers": [
{