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