From 1a3412d7ac0d72e0bac8e46b1b726fd55e63b2ab Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Tue, 28 Nov 2023 17:59:48 +0100
Subject: [PATCH] [player] Improve concat scrolling

- add padding
- add stopping on every page
- change selected index recognition
---
 .../pages-layout/pages-layout.component.html   |  3 +++
 .../pages-layout/pages-layout.component.scss   |  2 ++
 .../pages-layout/pages-layout.component.ts     |  1 +
 .../page-scroll-button.component.ts            |  7 ++++---
 .../app/components/page/page.component.html    |  2 ++
 .../src/app/components/page/page.component.ts  |  4 +---
 .../directives/in-view-detection.directive.ts  |  3 ++-
 .../directives/scroll-to-index.directive.ts    | 18 +++++++++++-------
 8 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.html b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.html
index 0e6e82e10..0b2b37cab 100644
--- a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.html
+++ b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.html
@@ -46,6 +46,7 @@
     <aspect-page-scroll-button class="page-container"
                                cdkScrollable
                                [isSnapMode]="scrollPageMode === 'concat-scroll-snap'"
+                               [concatScrollPadding]="concatScrollPadding"
                                [class.concat-scroll-snap]="scrollPageMode === 'concat-scroll-snap'"
                                [style.max-height.%]="aspectRatioColumn.scrollPages"
                                [style.max-width.%]="aspectRatioRow.scrollPages"
@@ -100,6 +101,7 @@
          [style.max-width]="page.hasMaxWidth ? page.maxWidth + 'px' : '100%'"
          [style.padding.px]="page.margin"
          aspectScrollToIndex
+         [scrollPagesLength]="scrollPages.length"
          [selectIndex]="selectIndex"
          [index]="i">
       <div *ngIf="!hidePageLabels"
@@ -109,6 +111,7 @@
       <aspect-page [pageIndex]="pages | pageIndex: page"
                    [scrollPageIndex]="i"
                    [pagesContainer]="pagesContainer"
+                   [concatScrollPadding]="scrollPageMode === 'concat-scroll-snap' ? concatScrollPadding : 0"
                    [page]="page"
                    [isLastPage]="last"
                    (selectedIndexChange)="setSelectedIndex($event)">
diff --git a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.scss b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.scss
index 5366e753f..a8a5d3b07 100644
--- a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.scss
+++ b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.scss
@@ -21,6 +21,8 @@
 .concat-scroll-snap {
   scroll-snap-type: y mandatory;
   scroll-padding: 0;
+  scroll-padding-bottom: 50px; // same value in component
+  scroll-snap-stop: always;
 }
 
 .page-container{
diff --git a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.ts b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.ts
index 300a34094..c2bb99542 100644
--- a/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.ts
+++ b/projects/player/src/app/components/layouts/pages-layout/pages-layout.component.ts
@@ -31,6 +31,7 @@ export class PagesLayoutComponent implements OnInit, AfterViewInit, OnDestroy {
   layoutAlignment: 'row' | 'column' = 'row';
   hidePageLabels: boolean = true;
   tabHeaderHeight: number = 0;
+  concatScrollPadding: number = 50; // Use the same value in Css
 
   maxWidth: { alwaysVisiblePage: number, scrollPages: number, allPages: number } =
     { alwaysVisiblePage: 0, scrollPages: 0, allPages: 0 };
diff --git a/projects/player/src/app/components/page-scroll-button/page-scroll-button.component.ts b/projects/player/src/app/components/page-scroll-button/page-scroll-button.component.ts
index cc902ca80..2550d9cbf 100644
--- a/projects/player/src/app/components/page-scroll-button/page-scroll-button.component.ts
+++ b/projects/player/src/app/components/page-scroll-button/page-scroll-button.component.ts
@@ -17,7 +17,7 @@ export class PageScrollButtonComponent implements AfterViewInit, OnDestroy {
   }
 
   @Input() isSnapMode!: boolean;
-
+  @Input() concatScrollPadding!: number;
   @Output() scrollToNextPage: EventEmitter<void> = new EventEmitter<void>();
 
   isVisible: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
@@ -60,7 +60,8 @@ export class PageScrollButtonComponent implements AfterViewInit, OnDestroy {
 
   scrollDown(): void {
     const nextScrollTop = this.elementRef.nativeElement.scrollTop + 2;
-    if (this.isSnapMode && this.getBottomsOfPages()
+    const pageBottoms: number[] = this.getBottomsOfPages();
+    if (this.isSnapMode && pageBottoms.length > 1 && pageBottoms
       .filter((page: number) => Math
         .abs(page - (nextScrollTop + this.elementRef.nativeElement.offsetHeight)) <= 2).length === 1) {
       this.clearScrollIng();
@@ -74,7 +75,7 @@ export class PageScrollButtonComponent implements AfterViewInit, OnDestroy {
     return [...this.elementRef.nativeElement.querySelectorAll('aspect-page')]
       .map(page => page.parentElement?.offsetHeight)
       .reduce((acc, v, i) => {
-        i === 0 ? acc.push(v) : acc.push(v + acc[i - 1]);
+        i === 0 ? acc.push(v + this.concatScrollPadding) : acc.push(v + acc[i - 1]);
         return acc;
       }, []);
   }
diff --git a/projects/player/src/app/components/page/page.component.html b/projects/player/src/app/components/page/page.component.html
index 231600c01..2f0ba8ab3 100644
--- a/projects/player/src/app/components/page/page.component.html
+++ b/projects/player/src/app/components/page/page.component.html
@@ -1,5 +1,6 @@
 <div aspectInViewDetection
      detectionType="top"
+     [topPadding]="concatScrollPadding || 0"
      [intersectionContainer]="pagesContainer"
      (intersecting)="selectedIndexChange.emit(scrollPageIndex)">
   <aspect-section
@@ -17,6 +18,7 @@
 </div>
 <div aspectInViewDetection
      detectionType="bottom"
+     [topPadding]="concatScrollPadding || 0"
      [intersectionContainer]="pagesContainer"
      (intersecting)="selectedIndexChange.emit(scrollPageIndex)">
 </div>
diff --git a/projects/player/src/app/components/page/page.component.ts b/projects/player/src/app/components/page/page.component.ts
index eb08b2757..2acf2026e 100644
--- a/projects/player/src/app/components/page/page.component.ts
+++ b/projects/player/src/app/components/page/page.component.ts
@@ -2,7 +2,6 @@ import {
   Component, Input, Output, EventEmitter
 } from '@angular/core';
 import { Page } from 'common/models/page';
-import { MediaPlayerService } from '../../services/media-player.service';
 
 @Component({
   selector: 'aspect-page',
@@ -16,7 +15,6 @@ export class PageComponent {
   @Input() pageIndex!: number;
   @Input() scrollPageIndex!: number;
   @Input() pagesContainer!: HTMLElement;
+  @Input() concatScrollPadding!: number;
   @Output() selectedIndexChange = new EventEmitter<number>();
-
-  constructor(public mediaPlayerService: MediaPlayerService) {}
 }
diff --git a/projects/player/src/app/directives/in-view-detection.directive.ts b/projects/player/src/app/directives/in-view-detection.directive.ts
index 476e78466..86812016d 100644
--- a/projects/player/src/app/directives/in-view-detection.directive.ts
+++ b/projects/player/src/app/directives/in-view-detection.directive.ts
@@ -12,6 +12,7 @@ export class InViewDetectionDirective implements OnInit, OnDestroy {
   @Input() detectionType!: 'top' | 'bottom';
   @Output() intersecting = new EventEmitter();
   @Input() intersectionContainer!: HTMLElement;
+  @Input() topPadding!: number;
 
   intersectionDetector!: IntersectionDetector;
 
@@ -20,7 +21,7 @@ export class InViewDetectionDirective implements OnInit, OnDestroy {
   constructor(private elementRef: ElementRef) {}
 
   ngOnInit(): void {
-    const constraint = this.detectionType === 'top' ? '0px 0px -99% 0px' : '99% 0px 0px 0px';
+    const constraint = this.detectionType === 'top' ? `${this.topPadding}px 0% -90% 0%` : '-90% 0% 0% 0%';
     this.intersectionDetector = new IntersectionDetector(this.intersectionContainer, constraint);
     this.intersectionDetector.observe(this.elementRef.nativeElement);
     this.intersectionDetector.intersecting
diff --git a/projects/player/src/app/directives/scroll-to-index.directive.ts b/projects/player/src/app/directives/scroll-to-index.directive.ts
index ac5133c9d..d0993825b 100644
--- a/projects/player/src/app/directives/scroll-to-index.directive.ts
+++ b/projects/player/src/app/directives/scroll-to-index.directive.ts
@@ -10,19 +10,23 @@ import { takeUntil } from 'rxjs/operators';
 export class ScrollToIndexDirective implements OnInit, OnDestroy {
   @Input() selectIndex!: Subject<number>;
   @Input() index!: number;
+  @Input() scrollPagesLength!: number;
 
   private ngUnsubscribe = new Subject<void>();
 
   constructor(private elementRef: ElementRef) {}
 
   ngOnInit(): void {
-    this.selectIndex
-      .pipe(takeUntil(this.ngUnsubscribe))
-      .subscribe((selectedIndex: number): void => {
-        if (selectedIndex === this.index) {
-          this.elementRef.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
-        }
-      });
+    if (this.scrollPagesLength > 1) {
+      this.selectIndex
+        .pipe(takeUntil(this.ngUnsubscribe))
+        .subscribe((selectedIndex: number): void => {
+          if (selectedIndex === this.index) {
+            setTimeout(() => this.elementRef.nativeElement
+              .scrollIntoView({ behavior: 'smooth', block: 'start' }));
+          }
+        });
+    }
   }
 
   ngOnDestroy(): void {
-- 
GitLab