From c8418d127c3a36cee16393ee70748f9fb0216efc Mon Sep 17 00:00:00 2001 From: Robbie Davis Date: Thu, 16 Jun 2022 09:50:23 -0400 Subject: [PATCH] Bugfix for sticky tabs on firefox (#1322) * Updating calcs for firefox * Removing unused code * Fixed up browser discrepencies * Review updates * Review updates * Added debouncing to scroll * Fixed a janky scroll issue with overscrolling * Cleaned up the code to use renderer and injectable document for SSR. * Removing sticky tabs Co-authored-by: Joseph Milazzo --- .../series-detail.component.html | 96 ++++++++++--------- .../series-detail.component.scss | 12 +-- .../series-detail/series-detail.component.ts | 60 ++++++------ .../app/shared/_services/utility.service.ts | 2 - 4 files changed, 81 insertions(+), 89 deletions(-) diff --git a/UI/Web/src/app/series-detail/series-detail.component.html b/UI/Web/src/app/series-detail/series-detail.component.html index fd3fe1248..8e9fa59b0 100644 --- a/UI/Web/src/app/series-detail/series-detail.component.html +++ b/UI/Web/src/app/series-detail/series-detail.component.html @@ -1,58 +1,60 @@ +
- -

- - {{series?.name}} -

-
- -
{{series?.localizedName}}
-
+ +

+ + {{series?.name}} +

+
+ +
{{series?.localizedName}}
+
- -
-

Page Settings

- -
-
-
- -
-
- -
-
- - - - - - + +
+
--> +
+
+ +
+
+ + + + + + +
-
-
-
-
+ +
+ + + - -
+
diff --git a/UI/Web/src/app/series-detail/series-detail.component.scss b/UI/Web/src/app/series-detail/series-detail.component.scss index f2777c510..7c90e746b 100644 --- a/UI/Web/src/app/series-detail/series-detail.component.scss +++ b/UI/Web/src/app/series-detail/series-detail.component.scss @@ -16,20 +16,14 @@ .virtual-scroller, virtual-scroller { width: 100%; - //height: 10000px; height: calc(100vh - 85px); max-height: calc(var(--vh)*100 - 170px); } // This is responsible for ensuring we scroll down and only tabs and companion bar is visible .main-container { - // Height set dynamically by series-detail.component.ts getHeight(); + // Height set dynamically by getHeight() overflow-y: auto; -} - -.nav-tabs.fixed { - position: fixed; - z-index: 100; - background-color: var(--bs-body-bg); - width: 100%; + position: relative; + overscroll-behavior-y: none; } diff --git a/UI/Web/src/app/series-detail/series-detail.component.ts b/UI/Web/src/app/series-detail/series-detail.component.ts index 0b55c8b86..4e22c765f 100644 --- a/UI/Web/src/app/series-detail/series-detail.component.ts +++ b/UI/Web/src/app/series-detail/series-detail.component.ts @@ -1,9 +1,9 @@ -import { Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, ElementRef, HostListener, OnDestroy, OnInit, ViewChild, Renderer2, AfterViewInit, Inject } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; import { NgbModal, NgbNavChangeEvent, NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap'; import { ToastrService } from 'ngx-toastr'; -import { forkJoin, Subject } from 'rxjs'; +import { forkJoin, fromEvent, Subject, debounceTime } from 'rxjs'; import { finalize, take, takeUntil, takeWhile } from 'rxjs/operators'; import { BulkSelectionService } from '../cards/bulk-selection.service'; import { EditSeriesModalComponent } from '../cards/_modals/edit-series-modal/edit-series-modal.component'; @@ -37,7 +37,7 @@ import { RelationKind } from '../_models/series-detail/relation-kind'; import { CardDetailDrawerComponent } from '../cards/card-detail-drawer/card-detail-drawer.component'; import { FormControl, FormGroup } from '@angular/forms'; import { PageLayoutMode } from '../_models/page-layout-mode'; -import { VirtualScrollerComponent } from '@iharbeck/ngx-virtual-scroller'; +import { DOCUMENT } from '@angular/common'; interface RelatedSeris { series: Series; @@ -63,9 +63,10 @@ interface StoryLineItem { templateUrl: './series-detail.component.html', styleUrls: ['./series-detail.component.scss'] }) -export class SeriesDetailComponent implements OnInit, OnDestroy { +export class SeriesDetailComponent implements OnInit, OnDestroy, AfterViewInit { - @ViewChild('scrollingBlock') scrollingBlock: ElementRef | undefined; + @ViewChild('scrollingBlock') scrollingBlock: ElementRef | undefined; + @ViewChild('companionBar') companionBar: ElementRef | undefined; /** * Series Id. Set at load before UI renders @@ -220,6 +221,16 @@ export class SeriesDetailComponent implements OnInit, OnDestroy { return PageLayoutMode; } + get ScrollingBlockHeight() { + if (this.scrollingBlock === undefined) return 'calc(var(--vh)*100)'; + const navbar = this.document.querySelector('.navbar') as HTMLElement; + if (navbar === null) return 'calc(var(--vh)*100)'; + + const companionHeight = this.companionBar!.nativeElement.offsetHeight; + const navbarHeight = navbar.offsetHeight; + const totalHeight = companionHeight + navbarHeight + 21; //21px to account for padding + return 'calc(var(--vh)*100 - ' + totalHeight + 'px)'; + } constructor(private route: ActivatedRoute, private seriesService: SeriesService, private router: Router, public bulkSelectionService: BulkSelectionService, @@ -231,7 +242,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy { private downloadService: DownloadService, private actionService: ActionService, public imageSerivce: ImageService, private messageHub: MessageHubService, private readingListService: ReadingListService, public navService: NavService, - private offcanvasService: NgbOffcanvas + private offcanvasService: NgbOffcanvas, private renderer: Renderer2, + @Inject(DOCUMENT) private document: Document ) { this.router.routeReuseStrategy.shouldReuseRoute = () => false; this.accountService.currentUser$.pipe(take(1)).subscribe(user => { @@ -244,30 +256,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy { }); } - onScroll(): void { - const tabs = document.querySelector('.nav-tabs') as HTMLElement | null; - const main = document.querySelector('.main-container') as HTMLElement | null; - const content = document.querySelector('.tab-content') as HTMLElement | null; - let mainOffset = main!.offsetTop; - let tabOffset = tabs!.offsetTop; - let contentOffset = content!.offsetTop; - let mainScrollPos = main!.scrollTop; - - if (!document.querySelector('.nav-tabs.fixed') && (tabOffset - mainOffset) <= mainScrollPos) { - tabs!.classList.add("fixed"); - tabs!.style.top = mainOffset+'px'; - } else if (document.querySelector('.nav-tabs.fixed') && mainScrollPos <= (contentOffset - mainOffset)) { - tabs!.classList.remove("fixed"); - } - } - - - - get ScrollingBlockHeight() { - if (this.scrollingBlock === undefined) return 'calc(var(--vh)*100)'; - const mainOffset = this.scrollingBlock.nativeElement.offsetTop; - return 'calc(var(--vh)*100 - ' + mainOffset + 'px)'; - } ngOnInit(): void { const routeId = this.route.snapshot.paramMap.get('seriesId'); @@ -307,6 +295,17 @@ export class SeriesDetailComponent implements OnInit, OnDestroy { this.onDestroy.complete(); } + ngAfterViewInit(): void { + this.initScroll(); + } + + initScroll() { + if (this.scrollingBlock === undefined || this.scrollingBlock.nativeElement === undefined) { + setTimeout(() => {this.initScroll()}, 10); + return; + } + } + @HostListener('document:keydown.shift', ['$event']) handleKeypress(event: KeyboardEvent) { if (event.key === KEY_CODES.SHIFT) { @@ -435,7 +434,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy { series: this.seriesService.getSeries(seriesId) }).subscribe(results => { this.libraryType = results.libType; - console.log('library type: ', this.libraryType); this.series = results.series; this.createHTML(); diff --git a/UI/Web/src/app/shared/_services/utility.service.ts b/UI/Web/src/app/shared/_services/utility.service.ts index 20d096b0b..8f49d3335 100644 --- a/UI/Web/src/app/shared/_services/utility.service.ts +++ b/UI/Web/src/app/shared/_services/utility.service.ts @@ -1,12 +1,10 @@ import { HttpParams } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ActivatedRouteSnapshot } from '@angular/router'; import { Chapter } from 'src/app/_models/chapter'; import { LibraryType } from 'src/app/_models/library'; import { MangaFormat } from 'src/app/_models/manga-format'; import { PaginatedResult } from 'src/app/_models/pagination'; import { Series } from 'src/app/_models/series'; -import { SeriesFilter, SortField } from 'src/app/_models/series-filter'; import { Volume } from 'src/app/_models/volume'; export enum KEY_CODES {