]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/videos/+video-watch/comment/video-comments.component.ts
Fix other videos not displayed in video watch
[github/Chocobozzz/PeerTube.git] / client / src / app / videos / +video-watch / comment / video-comments.component.ts
1 import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'
2 import { ConfirmService } from '@app/core'
3 import { NotificationsService } from 'angular2-notifications'
4 import { VideoComment as VideoCommentInterface, VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model'
5 import { AuthService } from '../../../core/auth'
6 import { ComponentPagination } from '../../../shared/rest/component-pagination.model'
7 import { User } from '../../../shared/users'
8 import { SortField } from '../../../shared/video/sort-field.type'
9 import { VideoDetails } from '../../../shared/video/video-details.model'
10 import { VideoComment } from './video-comment.model'
11 import { VideoCommentService } from './video-comment.service'
12
13 @Component({
14 selector: 'my-video-comments',
15 templateUrl: './video-comments.component.html',
16 styleUrls: ['./video-comments.component.scss']
17 })
18 export class VideoCommentsComponent implements OnChanges {
19 @Input() video: VideoDetails
20 @Input() user: User
21
22 comments: VideoComment[] = []
23 sort: SortField = '-createdAt'
24 componentPagination: ComponentPagination = {
25 currentPage: 1,
26 itemsPerPage: 10,
27 totalItems: null
28 }
29 inReplyToCommentId: number
30 threadComments: { [ id: number ]: VideoCommentThreadTree } = {}
31 threadLoading: { [ id: number ]: boolean } = {}
32
33 constructor (
34 private authService: AuthService,
35 private notificationsService: NotificationsService,
36 private confirmService: ConfirmService,
37 private videoCommentService: VideoCommentService
38 ) {}
39
40 ngOnChanges (changes: SimpleChanges) {
41 if (changes['video']) {
42 this.loadVideoComments()
43 }
44 }
45
46 viewReplies (comment: VideoCommentInterface) {
47 this.threadLoading[comment.id] = true
48
49 this.videoCommentService.getVideoThreadComments(this.video.id, comment.id)
50 .subscribe(
51 res => {
52 this.threadComments[comment.id] = res
53 this.threadLoading[comment.id] = false
54 },
55
56 err => this.notificationsService.error('Error', err.message)
57 )
58 }
59
60 loadMoreComments () {
61 this.videoCommentService.getVideoCommentThreads(this.video.id, this.componentPagination, this.sort)
62 .subscribe(
63 res => {
64 this.comments = this.comments.concat(res.comments)
65 this.componentPagination.totalItems = res.totalComments
66 },
67
68 err => this.notificationsService.error('Error', err.message)
69 )
70 }
71
72 onCommentThreadCreated (comment: VideoComment) {
73 this.comments.unshift(comment)
74 }
75
76 onWantedToReply (comment: VideoComment) {
77 this.inReplyToCommentId = comment.id
78 }
79
80 onResetReply () {
81 this.inReplyToCommentId = undefined
82 }
83
84 onThreadCreated (commentTree: VideoCommentThreadTree) {
85 this.viewReplies(commentTree.comment)
86 }
87
88 onWantedToDelete (commentToDelete: VideoComment) {
89 let message = 'Do you really want to delete this comment?'
90 if (commentToDelete.totalReplies !== 0) message += `${commentToDelete.totalReplies} would be deleted too.`
91
92 this.confirmService.confirm(message, 'Delete').subscribe(
93 res => {
94 if (res === false) return
95
96 this.videoCommentService.deleteVideoComment(commentToDelete.videoId, commentToDelete.id)
97 .subscribe(
98 () => {
99 // Delete the comment in the tree
100 if (commentToDelete.inReplyToCommentId) {
101 const thread = this.threadComments[commentToDelete.threadId]
102 if (!thread) {
103 console.error(`Cannot find thread ${commentToDelete.threadId} of the comment to delete ${commentToDelete.id}`)
104 return
105 }
106
107 this.deleteLocalCommentThread(thread, commentToDelete)
108 return
109 }
110
111 // Delete the thread
112 this.comments = this.comments.filter(c => c.id !== commentToDelete.id)
113 this.componentPagination.totalItems--
114 },
115
116 err => this.notificationsService.error('Error', err.message)
117 )
118 }
119 )
120 }
121
122 isUserLoggedIn () {
123 return this.authService.isLoggedIn()
124 }
125
126 onNearOfBottom () {
127 this.componentPagination.currentPage++
128
129 if (this.hasMoreComments()) {
130 this.loadMoreComments()
131 }
132 }
133
134 private hasMoreComments () {
135 // No results
136 if (this.componentPagination.totalItems === 0) return false
137
138 // Not loaded yet
139 if (!this.componentPagination.totalItems) return true
140
141 const maxPage = this.componentPagination.totalItems / this.componentPagination.itemsPerPage
142 return maxPage > this.componentPagination.currentPage
143 }
144
145 private deleteLocalCommentThread (parentComment: VideoCommentThreadTree, commentToDelete: VideoComment) {
146 for (const commentChild of parentComment.children) {
147 if (commentChild.comment.id === commentToDelete.id) {
148 parentComment.children = parentComment.children.filter(c => c.comment.id !== commentToDelete.id)
149 return
150 }
151
152 this.deleteLocalCommentThread(commentChild, commentToDelete)
153 }
154 }
155
156 private loadVideoComments () {
157 if (this.video.commentsEnabled === true) {
158 // Reset all our fields
159 this.comments = []
160 this.threadComments = {}
161 this.threadLoading = {}
162 this.inReplyToCommentId = undefined
163 this.componentPagination = {
164 currentPage: 1,
165 itemsPerPage: 10,
166 totalItems: null
167 }
168
169 this.loadMoreComments()
170 }
171 }
172 }