Video previews take all the width on mobile
[oweals/peertube.git] / client / src / app / shared / video / abstract-video-list.ts
1 import { OnInit } from '@angular/core'
2 import { ActivatedRoute, Router } from '@angular/router'
3 import { isInMobileView, isInSmallView } from '@app/shared/misc/utils'
4 import { NotificationsService } from 'angular2-notifications'
5 import { Observable } from 'rxjs/Observable'
6 import { AuthService } from '../../core/auth'
7 import { ComponentPagination } from '../rest/component-pagination.model'
8 import { SortField } from './sort-field.type'
9 import { Video } from './video.model'
10
11 export abstract class AbstractVideoList implements OnInit {
12   pagination: ComponentPagination = {
13     currentPage: 1,
14     itemsPerPage: 25,
15     totalItems: null
16   }
17   sort: SortField = '-createdAt'
18   defaultSort: SortField = '-createdAt'
19   videos: Video[] = []
20   loadOnInit = true
21
22   protected abstract notificationsService: NotificationsService
23   protected abstract authService: AuthService
24   protected abstract router: Router
25   protected abstract route: ActivatedRoute
26
27   protected abstract currentRoute: string
28
29   abstract titlePage: string
30
31   protected otherParams = {}
32
33   private loadedPages: { [ id: number ]: boolean } = {}
34
35   abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>
36
37   get user () {
38     return this.authService.getUser()
39   }
40
41   ngOnInit () {
42     // Subscribe to route changes
43     const routeParams = this.route.snapshot.params
44     this.loadRouteParams(routeParams)
45
46     if (isInMobileView()) {
47       this.pagination.itemsPerPage = 5
48     }
49
50     if (this.loadOnInit === true) this.loadMoreVideos('after')
51   }
52
53   onNearOfTop () {
54     if (this.pagination.currentPage > 1) {
55       this.previousPage()
56     }
57   }
58
59   onNearOfBottom () {
60     if (this.hasMoreVideos()) {
61       this.nextPage()
62     }
63   }
64
65   reloadVideos () {
66     this.videos = []
67     this.loadedPages = {}
68     this.loadMoreVideos('before')
69   }
70
71   loadMoreVideos (where: 'before' | 'after') {
72     if (this.loadedPages[this.pagination.currentPage] === true) return
73
74     const observable = this.getVideosObservable()
75
76     observable.subscribe(
77       ({ videos, totalVideos }) => {
78         // Paging is too high, return to the first one
79         if (this.pagination.currentPage > 1 && totalVideos <= ((this.pagination.currentPage - 1) * this.pagination.itemsPerPage)) {
80           this.pagination.currentPage = 1
81           this.setNewRouteParams()
82           return this.reloadVideos()
83         }
84
85         this.loadedPages[this.pagination.currentPage] = true
86         this.pagination.totalItems = totalVideos
87
88         if (where === 'before') {
89           this.videos = videos.concat(this.videos)
90         } else {
91           this.videos = this.videos.concat(videos)
92         }
93       },
94       error => this.notificationsService.error('Error', error.message)
95     )
96   }
97
98   protected hasMoreVideos () {
99     // No results
100     if (this.pagination.totalItems === 0) return false
101
102     // Not loaded yet
103     if (!this.pagination.totalItems) return true
104
105     const maxPage = this.pagination.totalItems / this.pagination.itemsPerPage
106     return maxPage > this.pagination.currentPage
107   }
108
109   protected previousPage () {
110     this.pagination.currentPage--
111
112     this.setNewRouteParams()
113     this.loadMoreVideos('before')
114   }
115
116   protected nextPage () {
117     this.pagination.currentPage++
118
119     this.setNewRouteParams()
120     this.loadMoreVideos('after')
121   }
122
123   protected buildRouteParams () {
124     // There is always a sort and a current page
125     const params = {
126       sort: this.sort,
127       page: this.pagination.currentPage
128     }
129
130     return Object.assign(params, this.otherParams)
131   }
132
133   protected loadRouteParams (routeParams: { [ key: string ]: any }) {
134     this.sort = routeParams['sort'] as SortField || this.defaultSort
135
136     if (routeParams['page'] !== undefined) {
137       this.pagination.currentPage = parseInt(routeParams['page'], 10)
138     } else {
139       this.pagination.currentPage = 1
140     }
141   }
142
143   protected setNewRouteParams () {
144     const routeParams = this.buildRouteParams()
145     this.router.navigate([ this.currentRoute, routeParams ])
146   }
147 }