Fix infinite scroll on big screens
[oweals/peertube.git] / client / src / app / +my-account / my-account-video-playlists / my-account-video-playlist-elements.component.ts
1 import { Component, OnDestroy, OnInit } from '@angular/core'
2 import { Notifier, ServerService } from '@app/core'
3 import { AuthService } from '../../core/auth'
4 import { ConfirmService } from '../../core/confirm'
5 import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
6 import { Subject, Subscription } from 'rxjs'
7 import { ActivatedRoute } from '@angular/router'
8 import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
9 import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
10 import { I18n } from '@ngx-translate/i18n-polyfill'
11 import { CdkDragDrop } from '@angular/cdk/drag-drop'
12 import { VideoPlaylistElement } from '@app/shared/video-playlist/video-playlist-element.model'
13
14 @Component({
15   selector: 'my-account-video-playlist-elements',
16   templateUrl: './my-account-video-playlist-elements.component.html',
17   styleUrls: [ './my-account-video-playlist-elements.component.scss' ]
18 })
19 export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
20   playlistElements: VideoPlaylistElement[] = []
21   playlist: VideoPlaylist
22
23   pagination: ComponentPagination = {
24     currentPage: 1,
25     itemsPerPage: 10,
26     totalItems: null
27   }
28
29   onDataSubject = new Subject<any[]>()
30
31   private videoPlaylistId: string | number
32   private paramsSub: Subscription
33
34   constructor (
35     private authService: AuthService,
36     private serverService: ServerService,
37     private notifier: Notifier,
38     private confirmService: ConfirmService,
39     private route: ActivatedRoute,
40     private i18n: I18n,
41     private videoPlaylistService: VideoPlaylistService
42   ) {}
43
44   ngOnInit () {
45     this.paramsSub = this.route.params.subscribe(routeParams => {
46       this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
47       this.loadElements()
48
49       this.loadPlaylistInfo()
50     })
51   }
52
53   ngOnDestroy () {
54     if (this.paramsSub) this.paramsSub.unsubscribe()
55   }
56
57   drop (event: CdkDragDrop<any>) {
58     const previousIndex = event.previousIndex
59     const newIndex = event.currentIndex
60
61     if (previousIndex === newIndex) return
62
63     const oldPosition = this.playlistElements[previousIndex].position
64     let insertAfter = this.playlistElements[newIndex].position
65
66     if (oldPosition > insertAfter) insertAfter--
67
68     const element = this.playlistElements[previousIndex]
69
70     this.playlistElements.splice(previousIndex, 1)
71     this.playlistElements.splice(newIndex, 0, element)
72
73     this.videoPlaylistService.reorderPlaylist(this.playlist.id, oldPosition, insertAfter)
74       .subscribe(
75         () => {
76           this.reorderClientPositions()
77         },
78
79         err => this.notifier.error(err.message)
80       )
81   }
82
83   onElementRemoved (element: VideoPlaylistElement) {
84     const oldFirst = this.findFirst()
85
86     this.playlistElements = this.playlistElements.filter(v => v.id !== element.id)
87     this.reorderClientPositions(oldFirst)
88   }
89
90   onNearOfBottom () {
91     // Last page
92     if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
93
94     this.pagination.currentPage += 1
95     this.loadElements()
96   }
97
98   trackByFn (index: number, elem: VideoPlaylistElement) {
99     return elem.id
100   }
101
102   private loadElements () {
103     this.videoPlaylistService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
104         .subscribe(({ total, data }) => {
105           this.playlistElements = this.playlistElements.concat(data)
106           this.pagination.totalItems = total
107
108           this.onDataSubject.next(data)
109         })
110   }
111
112   private loadPlaylistInfo () {
113     this.videoPlaylistService.getVideoPlaylist(this.videoPlaylistId)
114       .subscribe(playlist => {
115         this.playlist = playlist
116       })
117   }
118
119   private reorderClientPositions (first?: VideoPlaylistElement) {
120     if (this.playlistElements.length === 0) return
121
122     const oldFirst = first || this.findFirst()
123     let i = 1
124
125     for (const element of this.playlistElements) {
126       element.position = i
127       i++
128     }
129
130     // Reload playlist thumbnail if the first element changed
131     const newFirst = this.findFirst()
132     if (oldFirst && newFirst && oldFirst.id !== newFirst.id) {
133       this.playlist.refreshThumbnail()
134     }
135   }
136
137   private findFirst () {
138     return this.playlistElements.find(e => e.position === 1)
139   }
140 }