From e040edb5bddfd7a1dab4fe61dde2c8cece7e7f5e Mon Sep 17 00:00:00 2001 From: Sergey Elpashev Date: Wed, 17 Jul 2024 16:58:22 +0300 Subject: [PATCH] feat: manhwa scroll --- .../app/components/reader/reader.component.ts | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/apps/NwaifuAnime/src/app/components/reader/reader.component.ts b/apps/NwaifuAnime/src/app/components/reader/reader.component.ts index 03ea771..126acf7 100644 --- a/apps/NwaifuAnime/src/app/components/reader/reader.component.ts +++ b/apps/NwaifuAnime/src/app/components/reader/reader.component.ts @@ -1,5 +1,14 @@ -import { CommonModule } from "@angular/common"; -import { AfterViewInit, Component, OnDestroy } from "@angular/core"; +import { CommonModule, isPlatformBrowser } from "@angular/common"; +import { + AfterViewInit, + Component, + ElementRef, + Inject, + OnDestroy, + PLATFORM_ID, + QueryList, + ViewChildren, +} from "@angular/core"; import { ActivatedRoute, Router, RouterLink } from "@angular/router"; import { Observable, Subject, Subscription, fromEvent, map, takeUntil, throttleTime } from "rxjs"; import { Chapter, Page } from "../../services/parsers/rulib/rulib.chapter.dto"; @@ -31,15 +40,20 @@ export class ReaderComponent implements AfterViewInit, OnDestroy { private fromTowards = false; private destroy$ = new Subject(); private scrollSubscription = new Subscription(); + @ViewChildren("anchor") anchor: QueryList> = new QueryList(); + private observer!: IntersectionObserver; constructor( private route: ActivatedRoute, private router: Router, private searchService: SearchService, + private host: ElementRef, + @Inject(PLATFORM_ID) private platformId: object, ) {} ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); + if (this.observer) this.observer.disconnect(); } get manhwaPages() { @@ -70,6 +84,19 @@ export class ReaderComponent implements AfterViewInit, OnDestroy { .pipe(takeUntil(this.destroy$)) .subscribe((data) => { this.isManhwa = data; + if (this.isManhwa) { + this.observer = new IntersectionObserver( + ([entry]) => entry.isIntersecting && this.testScrollEmitter(), + { + root: this.isHostScrollable() ? this.host.nativeElement : null, + }, + ); + this.anchor.changes + .pipe(takeUntil(this.destroy$)) + .subscribe((list: QueryList>) => { + if (this.observer && list.first) this.observer.observe(list.first.nativeElement); + }); + } }); } else { this.router.navigate(["/"]); @@ -77,6 +104,23 @@ export class ReaderComponent implements AfterViewInit, OnDestroy { }); } + private isHostScrollable(): boolean { + if (isPlatformBrowser(this.platformId)) { + const style = window.getComputedStyle(this.host.nativeElement); + + return ( + style.getPropertyValue("overflow") === "auto" || + style.getPropertyValue("overflow-y") === "scroll" + ); + } + + return false; + } + + private testScrollEmitter() { + this.nextPage(); + } + private handleScrollManhwa(event: Event) { if (event.currentTarget) { if (