]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/+videos/+video-watch/comment/video-comment.component.ts
Move delete, delete & redraft actions to options
[github/Chocobozzz/PeerTube.git] / client / src / app / +videos / +video-watch / comment / video-comment.component.ts
1
2 import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core'
3 import { MarkdownService, Notifier, UserService } from '@app/core'
4 import { AuthService } from '@app/core/auth'
5 import { Account, Actor, DropdownAction, Video } from '@app/shared/shared-main'
6 import { CommentReportComponent } from '@app/shared/shared-moderation/report-modals/comment-report.component'
7 import { VideoComment, VideoCommentThreadTree } from '@app/shared/shared-video-comment'
8 import { User, UserRight } from '@shared/models'
9
10 @Component({
11 selector: 'my-video-comment',
12 templateUrl: './video-comment.component.html',
13 styleUrls: ['./video-comment.component.scss']
14 })
15 export class VideoCommentComponent implements OnInit, OnChanges {
16 @ViewChild('commentReportModal') commentReportModal: CommentReportComponent
17
18 @Input() video: Video
19 @Input() comment: VideoComment
20 @Input() parentComments: VideoComment[] = []
21 @Input() commentTree: VideoCommentThreadTree
22 @Input() inReplyToCommentId: number
23 @Input() highlightedComment = false
24 @Input() firstInThread = false
25 @Input() redraftValue?: string
26
27 @Output() wantedToReply = new EventEmitter<VideoComment>()
28 @Output() wantedToDelete = new EventEmitter<VideoComment>()
29 @Output() wantedToRedraft = new EventEmitter<VideoComment>()
30 @Output() threadCreated = new EventEmitter<VideoCommentThreadTree>()
31 @Output() resetReply = new EventEmitter()
32 @Output() timestampClicked = new EventEmitter<number>()
33
34 prependModerationActions: DropdownAction<any>[]
35
36 sanitizedCommentHTML = ''
37 newParentComments: VideoComment[] = []
38
39 commentAccount: Account
40 commentUser: User
41
42 constructor (
43 private markdownService: MarkdownService,
44 private authService: AuthService,
45 private userService: UserService,
46 private notifier: Notifier
47 ) {}
48
49 get user () {
50 return this.authService.getUser()
51 }
52
53 ngOnInit () {
54 this.init()
55 }
56
57 ngOnChanges () {
58 this.init()
59 }
60
61 onCommentReplyCreated (createdComment: VideoComment) {
62 if (!this.commentTree) {
63 this.commentTree = {
64 comment: this.comment,
65 children: []
66 }
67
68 this.threadCreated.emit(this.commentTree)
69 }
70
71 this.commentTree.children.unshift({
72 comment: createdComment,
73 children: []
74 })
75
76 this.resetReply.emit()
77
78 delete this.redraftValue
79 }
80
81 onWantToReply (comment?: VideoComment) {
82 this.wantedToReply.emit(comment || this.comment)
83 }
84
85 onWantToDelete (comment?: VideoComment) {
86 this.wantedToDelete.emit(comment || this.comment)
87 }
88
89 onWantToRedraft (comment?: VideoComment) {
90 this.wantedToRedraft.emit(comment || this.comment)
91 }
92
93 isUserLoggedIn () {
94 return this.authService.isLoggedIn()
95 }
96
97 onResetReply () {
98 this.resetReply.emit()
99 }
100
101 handleTimestampClicked (timestamp: number) {
102 this.timestampClicked.emit(timestamp)
103 }
104
105 isRemovableByUser () {
106 return this.comment.account && this.isUserLoggedIn() &&
107 (
108 this.user.account.id === this.comment.account.id ||
109 this.user.account.id === this.video.account.id ||
110 this.user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT)
111 )
112 }
113
114 isRedraftableByUser () {
115 return this.comment.account && this.isUserLoggedIn() && this.user.account.id === this.comment.account.id && this.comment.totalReplies === 0
116 }
117
118 isReportableByUser() {
119 return this.comment.account && this.isUserLoggedIn() && this.comment.isDeleted === false && this.authService.getUser().account.id !== this.comment.account.id
120 }
121
122 switchToDefaultAvatar ($event: Event) {
123 ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL()
124 }
125
126 private getUserIfNeeded (account: Account) {
127 if (!account.userId) return
128 if (!this.authService.isLoggedIn()) return
129
130 const user = this.authService.getUser()
131 if (user.hasRight(UserRight.MANAGE_USERS)) {
132 this.userService.getUserWithCache(account.userId)
133 .subscribe(
134 user => this.commentUser = user,
135
136 err => this.notifier.error(err.message)
137 )
138 }
139 }
140
141 private async init () {
142 const html = await this.markdownService.textMarkdownToHTML(this.comment.text, true)
143 this.sanitizedCommentHTML = await this.markdownService.processVideoTimestamps(html)
144 this.newParentComments = this.parentComments.concat([ this.comment ])
145
146 if (this.comment.account) {
147 this.commentAccount = new Account(this.comment.account)
148 this.getUserIfNeeded(this.commentAccount)
149 } else {
150 this.comment.account = null
151 }
152
153 this.prependModerationActions = []
154
155 if (this.isReportableByUser()) {
156 this.prependModerationActions.push({
157 label: $localize`Report comment`,
158 handler: () => this.showReportModal()
159 })
160 }
161
162 if (this.isRemovableByUser()) {
163 this.prependModerationActions.push({
164 label: $localize`Remove comment`,
165 handler: () => this.onWantToDelete()
166 })
167 }
168
169 if (this.isRedraftableByUser()) {
170 this.prependModerationActions.push({
171 label: $localize`Remove & re-draft comment`,
172 handler: () => this.onWantToRedraft()
173 })
174 }
175
176 if (this.prependModerationActions.length === 0) {
177 this.prependModerationActions = undefined
178 }
179 }
180
181 private showReportModal () {
182 this.commentReportModal.show()
183 }
184 }