Angular 16 (#2007)
* Removed adv, which isn't needed. * Updated zone * Updated to angular 16 * Updated to angular 16 (partially) * Updated to angular 16 * Package update for Angular 16 (and other dependencies) is complete. * Replaced all takeUntil(this.onDestroy) with new takeUntilDestroyed() * Updated all inputs that have ! to be required and deleted all unit tests. * Corrected how takeUntilDestroyed() is supposed to be implemented.
This commit is contained in:
parent
9bc8361381
commit
9c06cccd35
87 changed files with 3964 additions and 20426 deletions
|
|
@ -1,5 +1,20 @@
|
|||
import { DOCUMENT } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component, DestroyRef,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
Renderer2,
|
||||
SimpleChanges
|
||||
} from '@angular/core';
|
||||
import { BehaviorSubject, fromEvent, ReplaySubject, Subject } from 'rxjs';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { ScrollService } from 'src/app/_services/scroll.service';
|
||||
|
|
@ -7,6 +22,7 @@ import { ReaderService } from '../../../_services/reader.service';
|
|||
import { PAGING_DIRECTION } from '../../_models/reader-enums';
|
||||
import { WebtoonImage } from '../../_models/webtoon-image';
|
||||
import { ManagaReaderService } from '../../_series/managa-reader.service';
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
/**
|
||||
* How much additional space should pass, past the original bottom of the document height before we trigger the next chapter load
|
||||
|
|
@ -58,7 +74,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
/**
|
||||
* Method to generate the src for Image loading
|
||||
*/
|
||||
@Input() urlProvider!: (page: number) => string;
|
||||
@Input({required: true}) urlProvider!: (page: number) => string;
|
||||
@Output() pageNumberChange: EventEmitter<number> = new EventEmitter<number>();
|
||||
@Output() loadNextChapter: EventEmitter<void> = new EventEmitter<void>();
|
||||
@Output() loadPrevChapter: EventEmitter<void> = new EventEmitter<void>();
|
||||
|
|
@ -66,6 +82,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
@Input() goToPage: BehaviorSubject<number> | undefined;
|
||||
@Input() bookmarkPage: ReplaySubject<number> = new ReplaySubject<number>();
|
||||
@Input() fullscreenToggled: ReplaySubject<boolean> = new ReplaySubject<boolean>();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
readerElemRef!: ElementRef<HTMLDivElement>;
|
||||
|
||||
|
|
@ -110,7 +127,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
/**
|
||||
* If the user has scrolled all the way to the bottom. This is used solely for continuous reading
|
||||
*/
|
||||
atBottom: boolean = false;
|
||||
atBottom: boolean = false;
|
||||
/**
|
||||
* If the user has scrolled all the way to the top. This is used solely for continuous reading
|
||||
*/
|
||||
|
|
@ -149,10 +166,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
return this.webtoonImageWidth > (innerWidth || document.body.clientWidth);
|
||||
}
|
||||
|
||||
|
||||
private readonly onDestroy = new Subject<void>();
|
||||
|
||||
constructor(private readerService: ReaderService, private renderer: Renderer2,
|
||||
constructor(private readerService: ReaderService, private renderer: Renderer2,
|
||||
@Inject(DOCUMENT) private document: Document, private scrollService: ScrollService,
|
||||
private readonly cdRef: ChangeDetectorRef, private mangaReaderService: ManagaReaderService) {
|
||||
// This will always exist at this point in time since this is used within manga reader
|
||||
|
|
@ -172,18 +186,16 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
ngOnDestroy(): void {
|
||||
this.intersectionObserver.disconnect();
|
||||
this.onDestroy.next();
|
||||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for binding the scroll handler to the correct event. On non-fullscreen, body is correct. However, on fullscreen, we must use the reader as that is what
|
||||
* Responsible for binding the scroll handler to the correct event. On non-fullscreen, body is correct. However, on fullscreen, we must use the reader as that is what
|
||||
* gets promoted to fullscreen.
|
||||
*/
|
||||
initScrollHandler() {
|
||||
console.log('Setting up Scroll handler on ', this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body);
|
||||
fromEvent(this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body, 'scroll')
|
||||
.pipe(debounceTime(20), takeUntil(this.onDestroy))
|
||||
.pipe(debounceTime(20), takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe((event) => this.handleScrollEvent(event));
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +205,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.recalculateImageWidth();
|
||||
|
||||
if (this.goToPage) {
|
||||
this.goToPage.pipe(takeUntil(this.onDestroy)).subscribe(page => {
|
||||
this.goToPage.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(page => {
|
||||
const isSamePage = this.pageNum === page;
|
||||
if (isSamePage) { return; }
|
||||
this.debugLog('[GoToPage] jump has occured from ' + this.pageNum + ' to ' + page);
|
||||
|
|
@ -209,11 +221,11 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
if (this.bookmarkPage) {
|
||||
this.bookmarkPage.pipe(takeUntil(this.onDestroy)).subscribe(page => {
|
||||
this.bookmarkPage.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(page => {
|
||||
const image = document.querySelector('img[id^="page-' + page + '"]');
|
||||
if (image) {
|
||||
this.renderer.addClass(image, 'bookmark-effect');
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
this.renderer.removeClass(image, 'bookmark-effect');
|
||||
}, 1000);
|
||||
|
|
@ -222,7 +234,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
if (this.fullscreenToggled) {
|
||||
this.fullscreenToggled.pipe(takeUntil(this.onDestroy)).subscribe(isFullscreen => {
|
||||
this.fullscreenToggled.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(isFullscreen => {
|
||||
this.debugLog('[FullScreen] Fullscreen mode: ', isFullscreen);
|
||||
this.isFullscreenMode = isFullscreen;
|
||||
this.cdRef.markForCheck();
|
||||
|
|
@ -251,13 +263,13 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
return (offset
|
||||
|| document.body.scrollTop
|
||||
|| document.documentElement.scrollTop
|
||||
|| document.body.scrollTop
|
||||
|| document.documentElement.scrollTop
|
||||
|| 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* On scroll in document, calculate if the user/javascript has scrolled to the current image element (and it's visible), update that scrolling has ended completely,
|
||||
* On scroll in document, calculate if the user/javascript has scrolled to the current image element (and it's visible), update that scrolling has ended completely,
|
||||
* and calculate the direction the scrolling is occuring. This is not used for prefetching.
|
||||
* @param event Scroll Event
|
||||
*/
|
||||
|
|
@ -279,7 +291,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
if (!this.isScrolling) {
|
||||
// Use offset of the image against the scroll container to test if the most of the image is visible on the screen. We can use this
|
||||
// to mark the current page and separate the prefetching code.
|
||||
// to mark the current page and separate the prefetching code.
|
||||
const midlineImages = Array.from(document.querySelectorAll('img[id^="page-"]'))
|
||||
.filter(entry => this.shouldElementCountAsCurrentPage(entry));
|
||||
|
||||
|
|
@ -336,7 +348,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
document.body.scrollTop = this.previousScrollHeightMinusTop + (SPACER_SCROLL_INTO_PX / 2);
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
} else if (totalScroll >= totalHeight + SPACER_SCROLL_INTO_PX && this.atBottom) {
|
||||
} else if (totalScroll >= totalHeight + SPACER_SCROLL_INTO_PX && this.atBottom) {
|
||||
// This if statement will fire once we scroll into the spacer at all
|
||||
this.loadNextChapter.emit();
|
||||
this.cdRef.markForCheck();
|
||||
|
|
@ -345,12 +357,12 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
// < 5 because debug mode and FF (mobile) can report non 0, despite being at 0
|
||||
if (this.getScrollTop() < 5 && this.pageNum === 0 && !this.atTop) {
|
||||
this.atBottom = false;
|
||||
this.atTop = true;
|
||||
this.atTop = true;
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
// Scroll user back to original location
|
||||
this.previousScrollHeightMinusTop = document.body.scrollHeight - document.body.scrollTop;
|
||||
|
||||
|
||||
const reader = this.isFullscreenMode ? this.readerElemRef.nativeElement : this.document.body;
|
||||
requestAnimationFrame(() => this.scrollService.scrollTo((SPACER_SCROLL_INTO_PX / 2), reader));
|
||||
} else if (this.getScrollTop() < 5 && this.pageNum === 0 && this.atTop) {
|
||||
|
|
@ -362,7 +374,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @returns Height, Width
|
||||
*/
|
||||
getInnerDimensions() {
|
||||
|
|
@ -377,10 +389,10 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Is any part of the element visible in the scrollport. Does not take into account
|
||||
* style properites, just scroll port visibility.
|
||||
* @param elem
|
||||
* @returns
|
||||
* Is any part of the element visible in the scrollport. Does not take into account
|
||||
* style properites, just scroll port visibility.
|
||||
* @param elem
|
||||
* @returns
|
||||
*/
|
||||
isElementVisible(elem: Element) {
|
||||
if (elem === null || elem === undefined) { return false; }
|
||||
|
|
@ -391,8 +403,8 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
const [innerHeight, innerWidth] = this.getInnerDimensions();
|
||||
|
||||
return (rect.bottom >= 0 &&
|
||||
rect.right >= 0 &&
|
||||
return (rect.bottom >= 0 &&
|
||||
rect.right >= 0 &&
|
||||
rect.top <= (innerHeight || document.body.clientHeight) &&
|
||||
rect.left <= (innerWidth || document.body.clientWidth)
|
||||
);
|
||||
|
|
@ -400,7 +412,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
/**
|
||||
* Is any part of the element visible in the scrollport and is it above the midline trigger.
|
||||
* The midline trigger does not mean it is half of the screen. It may be top 25%.
|
||||
* The midline trigger does not mean it is half of the screen. It may be top 25%.
|
||||
* @param elem HTML Element
|
||||
* @returns If above midline
|
||||
*/
|
||||
|
|
@ -412,8 +424,8 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
const [innerHeight, innerWidth] = this.getInnerDimensions();
|
||||
|
||||
|
||||
if (rect.bottom >= 0 &&
|
||||
rect.right >= 0 &&
|
||||
if (rect.bottom >= 0 &&
|
||||
rect.right >= 0 &&
|
||||
rect.top <= (innerHeight || document.body.clientHeight) &&
|
||||
rect.left <= (innerWidth || document.body.clientWidth)
|
||||
) {
|
||||
|
|
@ -444,7 +456,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
/**
|
||||
* Callback for an image onLoad. At this point the image is already rendered in DOM (may not be visible)
|
||||
* This will be used to scroll to current page for intial load
|
||||
* @param event
|
||||
* @param event
|
||||
*/
|
||||
onImageLoad(event: any) {
|
||||
const imagePage = this.readerService.imageUrlToPageNum(event.target.src);
|
||||
|
|
@ -468,13 +480,13 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.debugLog('[Image Load] ! Loaded current page !', this.pageNum);
|
||||
this.currentPageElem = this.document.querySelector('img#page-' + this.pageNum);
|
||||
// There needs to be a bit of time before we scroll
|
||||
if (this.currentPageElem && !this.isElementVisible(this.currentPageElem)) {
|
||||
if (this.currentPageElem && !this.isElementVisible(this.currentPageElem)) {
|
||||
this.scrollToCurrentPage();
|
||||
} else {
|
||||
this.initFinished = true;
|
||||
this.cdRef.markForCheck();
|
||||
}
|
||||
|
||||
|
||||
this.allImagesLoaded = true;
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
|
|
@ -530,7 +542,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.currentPageElem = document.querySelector('img#page-' + this.pageNum);
|
||||
if (!this.currentPageElem) { return; }
|
||||
this.debugLog('[GoToPage] Scrolling to page', this.pageNum);
|
||||
|
||||
|
||||
// Update prevScrollPosition, so the next scroll event properly calculates direction
|
||||
this.prevScrollPosition = this.currentPageElem.getBoundingClientRect().top;
|
||||
this.isScrolling = true;
|
||||
|
|
@ -553,7 +565,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
}
|
||||
|
||||
this.debugLog('\t[PREFETCH] Prefetching ', page);
|
||||
|
||||
|
||||
const data = this.webtoonImages.value.concat({src: this.urlProvider(page), page});
|
||||
|
||||
data.sort((a: WebtoonImage, b: WebtoonImage) => {
|
||||
|
|
@ -582,9 +594,9 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
/**
|
||||
* Finds the ranges of indecies to load from backend. totalPages - 1 is due to backend will automatically return last page for any page number
|
||||
* above totalPages. Webtoon reader might ask for that which results in duplicate last pages.
|
||||
* @param pageNum
|
||||
* @returns
|
||||
* above totalPages. Webtoon reader might ask for that which results in duplicate last pages.
|
||||
* @param pageNum
|
||||
* @returns
|
||||
*/
|
||||
calculatePrefetchIndecies(pageNum: number = -1) {
|
||||
if (pageNum == -1) {
|
||||
|
|
@ -646,7 +658,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
|
|||
|
||||
if (this.debugLogFilter.filter(str => message.replace('\t', '').startsWith(str)).length > 0) return;
|
||||
if (extraData !== undefined) {
|
||||
console.log(message, extraData);
|
||||
console.log(message, extraData);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue