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 <joseph.v.milazzo@gmail.com>
This commit is contained in:
Robbie Davis 2022-06-16 09:50:23 -04:00 committed by GitHub
parent 5b829af531
commit c8418d127c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 89 deletions

View File

@ -1,3 +1,4 @@
<div #companionBar>
<app-side-nav-companion-bar *ngIf="series !== undefined" [hasExtras]="true" [extraDrawer]="extrasDrawer"> <app-side-nav-companion-bar *ngIf="series !== undefined" [hasExtras]="true" [extraDrawer]="extrasDrawer">
<ng-container title> <ng-container title>
<h2 style="margin-bottom: 0px"> <h2 style="margin-bottom: 0px">
@ -49,10 +50,11 @@
</div> </div>
</ng-template> </ng-template>
</app-side-nav-companion-bar> </app-side-nav-companion-bar>
</div>
<div [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid pt-2" *ngIf="series !== undefined" #scrollingBlock>
<div (scroll)="onScroll()" [ngStyle]="{'height': ScrollingBlockHeight}" class="main-container container-fluid pt-2" *ngIf="series !== undefined" #scrollingBlock>
<div class="row mb-3 info-container"> <div class="row mb-3 info-container">
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block"> <div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
<app-image maxWidth="300px" [imageUrl]="seriesImage"></app-image> <app-image maxWidth="300px" [imageUrl]="seriesImage"></app-image>

View File

@ -16,20 +16,14 @@
.virtual-scroller, virtual-scroller { .virtual-scroller, virtual-scroller {
width: 100%; width: 100%;
//height: 10000px;
height: calc(100vh - 85px); height: calc(100vh - 85px);
max-height: calc(var(--vh)*100 - 170px); max-height: calc(var(--vh)*100 - 170px);
} }
// This is responsible for ensuring we scroll down and only tabs and companion bar is visible // This is responsible for ensuring we scroll down and only tabs and companion bar is visible
.main-container { .main-container {
// Height set dynamically by series-detail.component.ts getHeight(); // Height set dynamically by getHeight()
overflow-y: auto; overflow-y: auto;
} position: relative;
overscroll-behavior-y: none;
.nav-tabs.fixed {
position: fixed;
z-index: 100;
background-color: var(--bs-body-bg);
width: 100%;
} }

View File

@ -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 { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { NgbModal, NgbNavChangeEvent, NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, NgbNavChangeEvent, NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr'; 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 { finalize, take, takeUntil, takeWhile } from 'rxjs/operators';
import { BulkSelectionService } from '../cards/bulk-selection.service'; import { BulkSelectionService } from '../cards/bulk-selection.service';
import { EditSeriesModalComponent } from '../cards/_modals/edit-series-modal/edit-series-modal.component'; 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 { CardDetailDrawerComponent } from '../cards/card-detail-drawer/card-detail-drawer.component';
import { FormControl, FormGroup } from '@angular/forms'; import { FormControl, FormGroup } from '@angular/forms';
import { PageLayoutMode } from '../_models/page-layout-mode'; import { PageLayoutMode } from '../_models/page-layout-mode';
import { VirtualScrollerComponent } from '@iharbeck/ngx-virtual-scroller'; import { DOCUMENT } from '@angular/common';
interface RelatedSeris { interface RelatedSeris {
series: Series; series: Series;
@ -63,9 +63,10 @@ interface StoryLineItem {
templateUrl: './series-detail.component.html', templateUrl: './series-detail.component.html',
styleUrls: ['./series-detail.component.scss'] styleUrls: ['./series-detail.component.scss']
}) })
export class SeriesDetailComponent implements OnInit, OnDestroy { export class SeriesDetailComponent implements OnInit, OnDestroy, AfterViewInit {
@ViewChild('scrollingBlock') scrollingBlock: ElementRef<HTMLDivElement> | undefined; @ViewChild('scrollingBlock') scrollingBlock: ElementRef<HTMLDivElement> | undefined;
@ViewChild('companionBar') companionBar: ElementRef<HTMLDivElement> | undefined;
/** /**
* Series Id. Set at load before UI renders * Series Id. Set at load before UI renders
@ -220,6 +221,16 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
return PageLayoutMode; 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, constructor(private route: ActivatedRoute, private seriesService: SeriesService,
private router: Router, public bulkSelectionService: BulkSelectionService, private router: Router, public bulkSelectionService: BulkSelectionService,
@ -231,7 +242,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
private downloadService: DownloadService, private actionService: ActionService, private downloadService: DownloadService, private actionService: ActionService,
public imageSerivce: ImageService, private messageHub: MessageHubService, public imageSerivce: ImageService, private messageHub: MessageHubService,
private readingListService: ReadingListService, public navService: NavService, 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.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.accountService.currentUser$.pipe(take(1)).subscribe(user => { 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 { ngOnInit(): void {
const routeId = this.route.snapshot.paramMap.get('seriesId'); const routeId = this.route.snapshot.paramMap.get('seriesId');
@ -307,6 +295,17 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
this.onDestroy.complete(); 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']) @HostListener('document:keydown.shift', ['$event'])
handleKeypress(event: KeyboardEvent) { handleKeypress(event: KeyboardEvent) {
if (event.key === KEY_CODES.SHIFT) { if (event.key === KEY_CODES.SHIFT) {
@ -435,7 +434,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
series: this.seriesService.getSeries(seriesId) series: this.seriesService.getSeries(seriesId)
}).subscribe(results => { }).subscribe(results => {
this.libraryType = results.libType; this.libraryType = results.libType;
console.log('library type: ', this.libraryType);
this.series = results.series; this.series = results.series;
this.createHTML(); this.createHTML();

View File

@ -1,12 +1,10 @@
import { HttpParams } from '@angular/common/http'; import { HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { Chapter } from 'src/app/_models/chapter'; import { Chapter } from 'src/app/_models/chapter';
import { LibraryType } from 'src/app/_models/library'; import { LibraryType } from 'src/app/_models/library';
import { MangaFormat } from 'src/app/_models/manga-format'; import { MangaFormat } from 'src/app/_models/manga-format';
import { PaginatedResult } from 'src/app/_models/pagination'; import { PaginatedResult } from 'src/app/_models/pagination';
import { Series } from 'src/app/_models/series'; import { Series } from 'src/app/_models/series';
import { SeriesFilter, SortField } from 'src/app/_models/series-filter';
import { Volume } from 'src/app/_models/volume'; import { Volume } from 'src/app/_models/volume';
export enum KEY_CODES { export enum KEY_CODES {