Fix video play promise error on non supported browsers
[oweals/peertube.git] / client / src / app / shared / video / infinite-scroller.directive.ts
1 import { Directive, EventEmitter, Input, OnInit, Output } from '@angular/core'
2 import 'rxjs/add/operator/debounceTime'
3 import 'rxjs/add/operator/distinct'
4 import 'rxjs/add/operator/distinctUntilChanged'
5 import 'rxjs/add/operator/filter'
6 import 'rxjs/add/operator/map'
7 import 'rxjs/add/operator/startWith'
8 import { fromEvent } from 'rxjs/observable/fromEvent'
9
10 @Directive({
11   selector: '[myInfiniteScroller]'
12 })
13 export class InfiniteScrollerDirective implements OnInit {
14   private static PAGE_VIEW_TOP_MARGIN = 500
15
16   @Input() containerHeight: number
17   @Input() pageHeight: number
18   @Input() percentLimit = 70
19   @Input() autoLoading = false
20
21   @Output() nearOfBottom = new EventEmitter<void>()
22   @Output() nearOfTop = new EventEmitter<void>()
23   @Output() pageChanged = new EventEmitter<number>()
24
25   private decimalLimit = 0
26   private lastCurrentBottom = -1
27   private lastCurrentTop = 0
28
29   constructor () {
30     this.decimalLimit = this.percentLimit / 100
31   }
32
33   ngOnInit () {
34     if (this.autoLoading === true) return this.initialize()
35   }
36
37   initialize () {
38     const scrollObservable = fromEvent(window, 'scroll')
39       .startWith(true)
40       .map(() => ({ current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight }))
41
42     // Scroll Down
43     scrollObservable
44       // Check we scroll down
45       .filter(({ current }) => {
46         const res = this.lastCurrentBottom < current
47
48         this.lastCurrentBottom = current
49         return res
50       })
51       .filter(({ current, maximumScroll }) => maximumScroll <= 0 || (current / maximumScroll) > this.decimalLimit)
52       .debounceTime(200)
53       .distinct()
54       .subscribe(() => this.nearOfBottom.emit())
55
56     // Scroll up
57     scrollObservable
58       // Check we scroll up
59       .filter(({ current }) => {
60         const res = this.lastCurrentTop > current
61
62         this.lastCurrentTop = current
63         return res
64       })
65       .filter(({ current, maximumScroll }) => {
66         return current !== 0 && (1 - (current / maximumScroll)) > this.decimalLimit
67       })
68       .debounceTime(200)
69       .distinct()
70       .subscribe(() => this.nearOfTop.emit())
71
72     // Page change
73     scrollObservable
74       .debounceTime(500)
75       .distinct()
76       .map(({ current }) => Math.max(1, Math.round((current + InfiniteScrollerDirective.PAGE_VIEW_TOP_MARGIN) / this.pageHeight)))
77       .distinctUntilChanged()
78       .subscribe(res => this.pageChanged.emit(res))
79   }
80
81 }