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