All files / app/directives/page-animation page-animation.directive.ts

100% Statements 32/32
80% Branches 4/5
100% Functions 12/12
100% Lines 31/31

Kamil Chmielowski

Web / Angular

Jasmine code coverage report for cv app.

You can contact with me by email: kamilchmielowski94@gmail.com or my page.

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                        1x 11x   11x 11x 11x 11x         11x 11x 11x       9x       9x       11x       2x 1x   1x 1x         9x   12x 1x   1x 1x           1x 1x 1x 1x       1x 1x 1x   1x 1x 1x      
import { AfterViewInit, Directive, ElementRef, HostListener, OnDestroy, OnInit } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
 
import { filter, map, Subscription } from 'rxjs';
 
import { DomService } from '../../services/dom/dom.service';
import { fadeAnimationTimeout } from './page-animation';
 
@Directive({
  selector: '[pageAnimation]',
  standalone: true,
})
export class PageAnimationDirective implements OnInit, AfterViewInit, OnDestroy {
  private readonly subscription = new Subscription();
 
  private isScrollable = true;
  private maxClientHeight: number = 0;
  private prevScrollX = 0;
  private prevScrollY = 0;
  private prevUrl!: string;
  private timeoutHandle!: NodeJS.Timeout;
 
  constructor(
    private domService: DomService,
    private elementRef: ElementRef<HTMLElement>,
    private router: Router,
  ) {}
 
  ngOnInit(): void {
    this.observeNavigationEnd();
  }
 
  ngAfterViewInit(): void {
    this.maxClientHeight = this.elementRef.nativeElement.clientHeight;
  }
 
  ngOnDestroy(): void {
    this.subscription.unsubscribe();
  }
 
  @HostListener('window:scroll', ['$event']) private onScroll(): void {
    if (!this.isScrollable) {
      this.domService.getWindow().scrollTo(this.prevScrollX, this.prevScrollY);
    } else {
      this.prevScrollX = this.domService.getWindow().scrollX;
      this.prevScrollY = this.domService.getWindow().scrollY;
    }
  }
 
  private observeNavigationEnd(): void {
    this.subscription.add(
      this.router.events.pipe(
        filter(e => e instanceof NavigationEnd),
        map(e => e as NavigationEnd),
      ).subscribe(result => {
        this.setPageHeightToMaxClient();
        this.timeoutHandle = setTimeout(() => this.setDefaultPageHeight(result.url), fadeAnimationTimeout * 2);
      })
    );
  }
 
  private setPageHeightToMaxClient(): void {
    this.isScrollable = false;
    clearTimeout(this.timeoutHandle);
    this.elementRef.nativeElement.style.setProperty('min-height', `${this.maxClientHeight}px`);
    this.elementRef.nativeElement.classList.toggle('no-scroll');
  }
 
  private setDefaultPageHeight(url: string): void {
    this.isScrollable = true;
    if ((this.elementRef.nativeElement.clientHeight || 0) > this.maxClientHeight) {
      this.maxClientHeight = this.elementRef.nativeElement.clientHeight;
    }
    this.elementRef.nativeElement.style.setProperty('min-height', `100vh`);
    this.elementRef.nativeElement.classList.toggle('no-scroll');
    this.prevUrl = url;
  }
}