aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared/video/infinite-scroller.directive.ts
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared/video/infinite-scroller.directive.ts')
-rw-r--r--client/src/app/shared/video/infinite-scroller.directive.ts65
1 files changed, 45 insertions, 20 deletions
diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts
index b1e88882c..9f613c5fa 100644
--- a/client/src/app/shared/video/infinite-scroller.directive.ts
+++ b/client/src/app/shared/video/infinite-scroller.directive.ts
@@ -1,14 +1,15 @@
1import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators' 1import { distinctUntilChanged, filter, map, share, startWith, tap, throttleTime } from 'rxjs/operators'
2import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' 2import { AfterContentChecked, Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
3import { fromEvent, Subscription } from 'rxjs' 3import { fromEvent, Observable, Subscription } from 'rxjs'
4 4
5@Directive({ 5@Directive({
6 selector: '[myInfiniteScroller]' 6 selector: '[myInfiniteScroller]'
7}) 7})
8export class InfiniteScrollerDirective implements OnInit, OnDestroy { 8export class InfiniteScrollerDirective implements OnInit, OnDestroy, AfterContentChecked {
9 @Input() percentLimit = 70 9 @Input() percentLimit = 70
10 @Input() autoInit = false 10 @Input() autoInit = false
11 @Input() onItself = false 11 @Input() onItself = false
12 @Input() dataObservable: Observable<any[]>
12 13
13 @Output() nearOfBottom = new EventEmitter<void>() 14 @Output() nearOfBottom = new EventEmitter<void>()
14 15
@@ -17,10 +18,22 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
17 private scrollDownSub: Subscription 18 private scrollDownSub: Subscription
18 private container: HTMLElement 19 private container: HTMLElement
19 20
21 private checkScroll = false
22
20 constructor (private el: ElementRef) { 23 constructor (private el: ElementRef) {
21 this.decimalLimit = this.percentLimit / 100 24 this.decimalLimit = this.percentLimit / 100
22 } 25 }
23 26
27 ngAfterContentChecked () {
28 if (this.checkScroll) {
29 this.checkScroll = false
30
31 console.log('Checking if the initial state has a scroll.')
32
33 if (this.hasScroll() === false) this.nearOfBottom.emit()
34 }
35 }
36
24 ngOnInit () { 37 ngOnInit () {
25 if (this.autoInit === true) return this.initialize() 38 if (this.autoInit === true) return this.initialize()
26 } 39 }
@@ -30,14 +43,15 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
30 } 43 }
31 44
32 initialize () { 45 initialize () {
33 if (this.onItself) { 46 this.container = this.onItself
34 this.container = this.el.nativeElement 47 ? this.el.nativeElement
35 } 48 : document.documentElement
36 49
37 // Emit the last value 50 // Emit the last value
38 const throttleOptions = { leading: true, trailing: true } 51 const throttleOptions = { leading: true, trailing: true }
39 52
40 const scrollObservable = fromEvent(this.container || window, 'scroll') 53 const scrollableElement = this.onItself ? this.container : window
54 const scrollObservable = fromEvent(scrollableElement, 'scroll')
41 .pipe( 55 .pipe(
42 startWith(null as string), // FIXME: typings 56 startWith(null as string), // FIXME: typings
43 throttleTime(200, undefined, throttleOptions), 57 throttleTime(200, undefined, throttleOptions),
@@ -49,23 +63,34 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
49 // Scroll Down 63 // Scroll Down
50 this.scrollDownSub = scrollObservable 64 this.scrollDownSub = scrollObservable
51 .pipe( 65 .pipe(
52 // Check we scroll down 66 filter(({ current }) => this.isScrollingDown(current)),
53 filter(({ current }) => { 67 filter(({ current, maximumScroll }) => (current / maximumScroll) > this.decimalLimit)
54 const res = this.lastCurrentBottom < current
55
56 this.lastCurrentBottom = current
57 return res
58 }),
59 filter(({ current, maximumScroll }) => maximumScroll <= 0 || (current / maximumScroll) > this.decimalLimit)
60 ) 68 )
61 .subscribe(() => this.nearOfBottom.emit()) 69 .subscribe(() => this.nearOfBottom.emit())
70
71 if (this.dataObservable) {
72 this.dataObservable
73 .pipe(filter(d => d.length !== 0))
74 .subscribe(() => this.checkScroll = true)
75 }
62 } 76 }
63 77
64 private getScrollInfo () { 78 private getScrollInfo () {
65 if (this.container) { 79 return { current: this.container.scrollTop, maximumScroll: this.getMaximumScroll() }
66 return { current: this.container.scrollTop, maximumScroll: this.container.scrollHeight } 80 }
67 } 81
82 private getMaximumScroll () {
83 return this.container.scrollHeight - window.innerHeight
84 }
85
86 private hasScroll () {
87 return this.getMaximumScroll() > 0
88 }
89
90 private isScrollingDown (current: number) {
91 const result = this.lastCurrentBottom < current
68 92
69 return { current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight } 93 this.lastCurrentBottom = current
94 return result
70 } 95 }
71} 96}