allow limiting video-comments rss feeds to an account or video channel
[oweals/peertube.git] / client / src / app / +my-account / my-account-video-playlists / my-account-video-playlist-elements.component.ts
1 import { Subject, Subscription } from 'rxjs'
2 import { CdkDragDrop } from '@angular/cdk/drag-drop'
3 import { Component, OnDestroy, OnInit } from '@angular/core'
4 import { ActivatedRoute } from '@angular/router'
5 import { ComponentPagination, Notifier, ScreenService } from '@app/core'
6 import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
7
8 @Component({
9   selector: 'my-account-video-playlist-elements',
10   templateUrl: './my-account-video-playlist-elements.component.html',
11   styleUrls: [ './my-account-video-playlist-elements.component.scss' ]
12 })
13 export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
14   playlistElements: VideoPlaylistElement[] = []
15   playlist: VideoPlaylist
16
17   pagination: ComponentPagination = {
18     currentPage: 1,
19     itemsPerPage: 10,
20     totalItems: null
21   }
22
23   onDataSubject = new Subject<any[]>()
24
25   private videoPlaylistId: string | number
26   private paramsSub: Subscription
27
28   constructor (
29     private notifier: Notifier,
30     private route: ActivatedRoute,
31     private screenService: ScreenService,
32     private videoPlaylistService: VideoPlaylistService
33   ) {}
34
35   ngOnInit () {
36     this.paramsSub = this.route.params.subscribe(routeParams => {
37       this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
38       this.loadElements()
39
40       this.loadPlaylistInfo()
41     })
42   }
43
44   ngOnDestroy () {
45     if (this.paramsSub) this.paramsSub.unsubscribe()
46   }
47
48   drop (event: CdkDragDrop<any>) {
49     const previousIndex = event.previousIndex
50     const newIndex = event.currentIndex
51
52     if (previousIndex === newIndex) return
53
54     const oldPosition = this.playlistElements[previousIndex].position
55     let insertAfter = this.playlistElements[newIndex].position
56
57     if (oldPosition > insertAfter) insertAfter--
58
59     const element = this.playlistElements[previousIndex]
60
61     this.playlistElements.splice(previousIndex, 1)
62     this.playlistElements.splice(newIndex, 0, element)
63
64     this.videoPlaylistService.reorderPlaylist(this.playlist.id, oldPosition, insertAfter)
65       .subscribe(
66         () => {
67           this.reorderClientPositions()
68         },
69
70         err => this.notifier.error(err.message)
71       )
72   }
73
74   onElementRemoved (element: VideoPlaylistElement) {
75     const oldFirst = this.findFirst()
76
77     this.playlistElements = this.playlistElements.filter(v => v.id !== element.id)
78     this.reorderClientPositions(oldFirst)
79   }
80
81   onNearOfBottom () {
82     // Last page
83     if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
84
85     this.pagination.currentPage += 1
86     this.loadElements()
87   }
88
89   trackByFn (index: number, elem: VideoPlaylistElement) {
90     return elem.id
91   }
92
93   /**
94    * Returns null to not have drag and drop delay.
95    * In small views, where elements are about 100% wide,
96    * we add a delay to prevent unwanted drag&drop.
97    *
98    * @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
99    *
100    * @returns {null|number} Null for no delay, or a number in milliseconds.
101    */
102   getDragStartDelay (): null | number {
103     if (this.screenService.isInTouchScreen()) {
104       return 500
105     }
106
107     return null
108   }
109
110   private loadElements () {
111     this.videoPlaylistService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
112         .subscribe(({ total, data }) => {
113           this.playlistElements = this.playlistElements.concat(data)
114           this.pagination.totalItems = total
115
116           this.onDataSubject.next(data)
117         })
118   }
119
120   private loadPlaylistInfo () {
121     this.videoPlaylistService.getVideoPlaylist(this.videoPlaylistId)
122       .subscribe(playlist => {
123         this.playlist = playlist
124       })
125   }
126
127   private reorderClientPositions (first?: VideoPlaylistElement) {
128     if (this.playlistElements.length === 0) return
129
130     const oldFirst = first || this.findFirst()
131     let i = 1
132
133     for (const element of this.playlistElements) {
134       element.position = i
135       i++
136     }
137
138     // Reload playlist thumbnail if the first element changed
139     const newFirst = this.findFirst()
140     if (oldFirst && newFirst && oldFirst.id !== newFirst.id) {
141       this.playlist.refreshThumbnail()
142     }
143   }
144
145   private findFirst () {
146     return this.playlistElements.find(e => e.position === 1)
147   }
148 }