Polish Round 2 (#2411)

This commit is contained in:
Joe Milazzo 2023-11-07 17:42:17 -06:00 committed by GitHub
parent ba3e760b31
commit a2fd87c454
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 213 additions and 95 deletions

View file

@ -24,6 +24,7 @@ import { WebtoonImage } from '../../_models/webtoon-image';
import { ManagaReaderService } from '../../_service/managa-reader.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import {TranslocoDirective} from "@ngneat/transloco";
import {MangaReaderComponent} from "../manga-reader/manga-reader.component";
/**
* How much additional space should pass, past the original bottom of the document height before we trigger the next chapter load
@ -62,6 +63,12 @@ const enum DEBUG_MODES {
})
export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
private readonly mangaReaderService = inject(ManagaReaderService);
private readonly readerService = inject(ReaderService);
private readonly renderer = inject(Renderer2);
private readonly scrollService = inject(ScrollService);
private readonly cdRef = inject(ChangeDetectorRef);
/**
* Current page number aka what's recorded on screen
*/
@ -150,7 +157,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
/**
* Debug mode. Will show extra information. Use bitwise (|) operators between different modes to enable different output
*/
debugMode: DEBUG_MODES = DEBUG_MODES.None;
debugMode: DEBUG_MODES = DEBUG_MODES.Outline;
/**
* Debug mode. Will filter out any messages in here so they don't hit the log
*/
@ -169,9 +176,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
return this.webtoonImageWidth > (innerWidth || document.body.clientWidth);
}
constructor(private readerService: ReaderService, private renderer: Renderer2,
@Inject(DOCUMENT) private document: Document, private scrollService: ScrollService,
private readonly cdRef: ChangeDetectorRef, private mangaReaderService: ManagaReaderService) {
constructor(@Inject(DOCUMENT) private readonly document: Document) {
// This will always exist at this point in time since this is used within manga reader
const reader = document.querySelector('.reading-area');
if (reader !== null) {
@ -200,6 +205,10 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
fromEvent(this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body, 'scroll')
.pipe(debounceTime(20), takeUntilDestroyed(this.destroyRef))
.subscribe((event) => this.handleScrollEvent(event));
fromEvent(this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body, 'scrollend')
.pipe(debounceTime(20), takeUntilDestroyed(this.destroyRef))
.subscribe((event) => this.handleScrollEndEvent(event));
}
ngOnInit(): void {
@ -307,6 +316,18 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
this.checkIfShouldTriggerContinuousReader();
}
handleScrollEndEvent(event?: any) {
if (!this.isScrolling) {
const closestImages = Array.from(document.querySelectorAll('img[id^="page-"]')) as HTMLImageElement[];
const img = this.findClosestVisibleImage(closestImages);
if (img != null) {
this.setPageNum(parseInt(img.getAttribute('page') || this.pageNum + '', 10));
}
}
}
getTotalHeight() {
let totalHeight = 0;
document.querySelectorAll('img[id^="page-"]').forEach(img => totalHeight += img.getBoundingClientRect().height);
@ -423,10 +444,8 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
if (elem === null || elem === undefined) { return false; }
const rect = elem.getBoundingClientRect();
const [innerHeight, innerWidth] = this.getInnerDimensions();
if (rect.bottom >= 0 &&
rect.right >= 0 &&
rect.top <= (innerHeight || document.body.clientHeight) &&
@ -438,6 +457,32 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
return false;
}
/**
* Find the closest visible image within the viewport.
* @param images An array of HTML Image Elements
* @returns Closest visible image or null if none are visible
*/
findClosestVisibleImage(images: HTMLImageElement[]): HTMLImageElement | null {
let closestImage: HTMLImageElement | null = null;
let closestDistanceToTop = Number.MAX_VALUE; // Initialize to a high value.
for (const image of images) {
// Get the bounding rectangle of the image.
const rect = image.getBoundingClientRect();
// Calculate the distance of the current image to the top of the viewport.
const distanceToTop = Math.abs(rect.top);
// Check if the image is visible within the viewport.
if (distanceToTop < closestDistanceToTop) {
closestDistanceToTop = distanceToTop;
closestImage = image;
}
}
return closestImage;
}
initWebtoonReader() {
this.initFinished = false;
@ -449,6 +494,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
this.cdRef.markForCheck();
const [startingIndex, endingIndex] = this.calculatePrefetchIndecies();
this.debugLog('[INIT] Prefetching pages ' + startingIndex + ' to ' + endingIndex + '. Current page: ', this.pageNum);
for(let i = startingIndex; i <= endingIndex; i++) {
this.loadWebtoonImage(i);