2020-06-23 14:10:17 +02:00
|
|
|
import { Observable } from 'rxjs'
|
2021-06-07 17:38:31 +02:00
|
|
|
import { getLocaleDirection } from '@angular/common'
|
|
|
|
import {
|
|
|
|
Component,
|
|
|
|
ElementRef,
|
|
|
|
EventEmitter,
|
|
|
|
Inject,
|
|
|
|
Input,
|
|
|
|
LOCALE_ID,
|
|
|
|
OnChanges,
|
|
|
|
OnInit,
|
|
|
|
Output,
|
|
|
|
SimpleChanges,
|
|
|
|
ViewChild
|
|
|
|
} from '@angular/core'
|
2018-09-25 15:42:58 +02:00
|
|
|
import { Router } from '@angular/router'
|
2020-06-23 14:10:17 +02:00
|
|
|
import { Notifier, User } from '@app/core'
|
2020-08-17 11:47:04 +02:00
|
|
|
import { VIDEO_COMMENT_TEXT_VALIDATOR } from '@app/shared/form-validators/video-comment-validators'
|
|
|
|
import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
2021-04-15 11:38:24 +02:00
|
|
|
import { Video } from '@app/shared/shared-main'
|
2020-07-09 15:54:24 +02:00
|
|
|
import { VideoComment, VideoCommentService } from '@app/shared/shared-video-comment'
|
2020-06-23 14:10:17 +02:00
|
|
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
|
|
|
import { VideoCommentCreate } from '@shared/models'
|
2017-12-27 16:11:53 +01:00
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'my-video-comment-add',
|
|
|
|
templateUrl: './video-comment-add.component.html',
|
|
|
|
styleUrls: ['./video-comment-add.component.scss']
|
|
|
|
})
|
2020-08-07 14:03:28 +02:00
|
|
|
export class VideoCommentAddComponent extends FormReactive implements OnChanges, OnInit {
|
2018-01-03 17:25:47 +01:00
|
|
|
@Input() user: User
|
2017-12-27 16:11:53 +01:00
|
|
|
@Input() video: Video
|
2020-08-12 12:43:26 +02:00
|
|
|
@Input() parentComment?: VideoComment
|
|
|
|
@Input() parentComments?: VideoComment[]
|
2017-12-29 09:18:00 +01:00
|
|
|
@Input() focusOnInit = false
|
2020-08-07 14:03:28 +02:00
|
|
|
@Input() textValue?: string
|
2017-12-27 16:11:53 +01:00
|
|
|
|
2020-02-10 14:25:38 +01:00
|
|
|
@Output() commentCreated = new EventEmitter<VideoComment>()
|
2019-12-15 22:44:31 +01:00
|
|
|
@Output() cancel = new EventEmitter()
|
2017-12-27 16:11:53 +01:00
|
|
|
|
2019-07-24 16:05:59 +02:00
|
|
|
@ViewChild('visitorModal', { static: true }) visitorModal: NgbModal
|
2020-08-09 16:20:31 +02:00
|
|
|
@ViewChild('emojiModal', { static: true }) emojiModal: NgbModal
|
2019-07-24 16:05:59 +02:00
|
|
|
@ViewChild('textarea', { static: true }) textareaElement: ElementRef
|
2017-12-29 09:18:00 +01:00
|
|
|
|
2018-11-15 09:24:56 +01:00
|
|
|
addingComment = false
|
2020-08-07 18:41:05 +02:00
|
|
|
addingCommentButtonValue: string
|
2018-06-18 10:29:17 +02:00
|
|
|
|
2017-12-27 16:11:53 +01:00
|
|
|
constructor (
|
2018-06-05 10:58:45 +02:00
|
|
|
protected formValidatorService: FormValidatorService,
|
2018-12-19 16:04:34 +01:00
|
|
|
private notifier: Notifier,
|
2018-06-04 16:21:17 +02:00
|
|
|
private videoCommentService: VideoCommentService,
|
2018-09-25 15:42:58 +02:00
|
|
|
private modalService: NgbModal,
|
2021-06-07 17:38:31 +02:00
|
|
|
private router: Router,
|
|
|
|
@Inject(LOCALE_ID) private localeId: string
|
2017-12-27 16:11:53 +01:00
|
|
|
) {
|
|
|
|
super()
|
|
|
|
}
|
|
|
|
|
2020-08-09 16:20:31 +02:00
|
|
|
get emojiMarkupList () {
|
2020-11-08 11:35:09 +01:00
|
|
|
const emojiMarkupObjectList = require('markdown-it-emoji/lib/data/light.json')
|
|
|
|
|
|
|
|
// Populate emoji-markup-list from object to array to avoid keys alphabetical order
|
|
|
|
const emojiMarkupArrayList = []
|
|
|
|
for (const emojiMarkupName in emojiMarkupObjectList) {
|
|
|
|
if (emojiMarkupName) {
|
|
|
|
const emoji = emojiMarkupObjectList[emojiMarkupName]
|
|
|
|
emojiMarkupArrayList.push([emoji, emojiMarkupName])
|
|
|
|
}
|
|
|
|
}
|
2020-08-09 16:20:31 +02:00
|
|
|
|
2020-11-08 11:35:09 +01:00
|
|
|
return emojiMarkupArrayList
|
2020-08-09 16:20:31 +02:00
|
|
|
}
|
|
|
|
|
2017-12-27 16:11:53 +01:00
|
|
|
ngOnInit () {
|
2018-06-05 10:58:45 +02:00
|
|
|
this.buildForm({
|
2020-08-17 11:47:04 +02:00
|
|
|
text: VIDEO_COMMENT_TEXT_VALIDATOR
|
2018-06-05 10:58:45 +02:00
|
|
|
})
|
2017-12-29 09:18:00 +01:00
|
|
|
|
2018-09-25 15:42:58 +02:00
|
|
|
if (this.user) {
|
2020-08-12 12:43:26 +02:00
|
|
|
if (!this.parentComment) {
|
2020-08-14 14:34:47 +02:00
|
|
|
this.addingCommentButtonValue = $localize`Comment`
|
2020-08-07 18:41:05 +02:00
|
|
|
} else {
|
2020-08-14 14:34:47 +02:00
|
|
|
this.addingCommentButtonValue = $localize`Reply`
|
2020-08-07 18:41:05 +02:00
|
|
|
}
|
|
|
|
|
2020-08-12 12:43:26 +02:00
|
|
|
this.initTextValue()
|
2018-01-05 11:19:25 +01:00
|
|
|
}
|
2017-12-27 16:11:53 +01:00
|
|
|
}
|
|
|
|
|
2020-08-07 14:03:28 +02:00
|
|
|
ngOnChanges (changes: SimpleChanges) {
|
2021-06-08 10:40:38 +02:00
|
|
|
// Not initialized yet
|
|
|
|
if (!this.form) return
|
|
|
|
|
2020-08-07 14:03:28 +02:00
|
|
|
if (changes.textValue && changes.textValue.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
|
|
|
|
this.patchTextValue(changes.textValue.currentValue, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-19 10:38:24 +01:00
|
|
|
onValidKey () {
|
2019-01-10 09:58:08 +01:00
|
|
|
this.check()
|
2018-02-19 10:38:24 +01:00
|
|
|
if (!this.form.valid) return
|
|
|
|
|
|
|
|
this.formValidated()
|
|
|
|
}
|
|
|
|
|
2018-10-18 09:08:59 +02:00
|
|
|
openVisitorModal (event: any) {
|
2018-09-25 15:42:58 +02:00
|
|
|
if (this.user === null) { // we only open it for visitors
|
|
|
|
// fixing ng-bootstrap ModalService and the "Expression Changed After It Has Been Checked" Error
|
|
|
|
event.srcElement.blur()
|
|
|
|
event.preventDefault()
|
|
|
|
|
|
|
|
this.modalService.open(this.visitorModal)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-09 16:20:31 +02:00
|
|
|
openEmojiModal (event: any) {
|
|
|
|
event.preventDefault()
|
2020-11-08 11:35:09 +01:00
|
|
|
this.modalService.open(this.emojiModal, { backdrop: true, size: 'lg' })
|
2020-08-09 16:20:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
hideModals () {
|
2018-09-25 15:42:58 +02:00
|
|
|
this.modalService.dismissAll()
|
|
|
|
}
|
|
|
|
|
2017-12-27 16:11:53 +01:00
|
|
|
formValidated () {
|
2018-06-18 10:29:17 +02:00
|
|
|
// If we validate very quickly the comment form, we might comment twice
|
|
|
|
if (this.addingComment) return
|
|
|
|
|
|
|
|
this.addingComment = true
|
|
|
|
|
2017-12-27 16:11:53 +01:00
|
|
|
const commentCreate: VideoCommentCreate = this.form.value
|
2020-02-10 14:25:38 +01:00
|
|
|
let obs: Observable<VideoComment>
|
2017-12-27 16:11:53 +01:00
|
|
|
|
|
|
|
if (this.parentComment) {
|
|
|
|
obs = this.addCommentReply(commentCreate)
|
|
|
|
} else {
|
|
|
|
obs = this.addCommentThread(commentCreate)
|
|
|
|
}
|
|
|
|
|
2021-08-17 11:27:47 +02:00
|
|
|
obs.subscribe({
|
|
|
|
next: comment => {
|
2018-06-18 10:29:17 +02:00
|
|
|
this.addingComment = false
|
2017-12-27 16:11:53 +01:00
|
|
|
this.commentCreated.emit(comment)
|
|
|
|
this.form.reset()
|
|
|
|
},
|
|
|
|
|
2021-08-17 11:27:47 +02:00
|
|
|
error: err => {
|
2018-06-18 10:29:17 +02:00
|
|
|
this.addingComment = false
|
|
|
|
|
2018-12-19 16:04:34 +01:00
|
|
|
this.notifier.error(err.text)
|
2018-06-18 10:29:17 +02:00
|
|
|
}
|
2021-08-17 11:27:47 +02:00
|
|
|
})
|
2017-12-27 20:03:37 +01:00
|
|
|
}
|
2017-12-27 16:11:53 +01:00
|
|
|
|
|
|
|
isAddButtonDisplayed () {
|
|
|
|
return this.form.value['text']
|
|
|
|
}
|
|
|
|
|
2019-06-07 10:56:59 +02:00
|
|
|
getUri () {
|
2018-10-04 14:13:08 +02:00
|
|
|
return window.location.href
|
|
|
|
}
|
|
|
|
|
2018-09-25 15:42:58 +02:00
|
|
|
gotoLogin () {
|
2020-08-09 16:20:31 +02:00
|
|
|
this.hideModals()
|
2018-09-25 15:42:58 +02:00
|
|
|
this.router.navigate([ '/login' ])
|
|
|
|
}
|
|
|
|
|
2019-12-17 11:20:24 +01:00
|
|
|
cancelCommentReply () {
|
|
|
|
this.cancel.emit(null)
|
2020-03-15 16:05:37 +01:00
|
|
|
this.form.value['text'] = this.textareaElement.nativeElement.value = ''
|
2019-12-17 11:20:24 +01:00
|
|
|
}
|
|
|
|
|
2021-06-07 17:38:31 +02:00
|
|
|
isRTL () {
|
|
|
|
return getLocaleDirection(this.localeId) === 'rtl'
|
|
|
|
}
|
|
|
|
|
2017-12-27 16:11:53 +01:00
|
|
|
private addCommentReply (commentCreate: VideoCommentCreate) {
|
|
|
|
return this.videoCommentService
|
|
|
|
.addCommentReply(this.video.id, this.parentComment.id, commentCreate)
|
|
|
|
}
|
|
|
|
|
|
|
|
private addCommentThread (commentCreate: VideoCommentCreate) {
|
|
|
|
return this.videoCommentService
|
|
|
|
.addCommentThread(this.video.id, commentCreate)
|
|
|
|
}
|
2020-08-07 14:03:28 +02:00
|
|
|
|
2020-08-12 12:43:26 +02:00
|
|
|
private initTextValue () {
|
|
|
|
if (this.textValue) {
|
|
|
|
this.patchTextValue(this.textValue, this.focusOnInit)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.parentComment) {
|
|
|
|
const mentions = this.parentComments
|
|
|
|
.filter(c => c.account && c.account.id !== this.user.account.id) // Don't add mention of ourselves
|
|
|
|
.map(c => '@' + c.by)
|
|
|
|
|
|
|
|
const mentionsSet = new Set(mentions)
|
|
|
|
const mentionsText = Array.from(mentionsSet).join(' ') + ' '
|
|
|
|
|
|
|
|
this.patchTextValue(mentionsText, this.focusOnInit)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 14:03:28 +02:00
|
|
|
private patchTextValue (text: string, focus: boolean) {
|
|
|
|
setTimeout(() => {
|
|
|
|
if (focus) {
|
|
|
|
this.textareaElement.nativeElement.focus()
|
|
|
|
}
|
|
|
|
|
2020-11-06 17:40:40 +01:00
|
|
|
// Scroll to textarea
|
2020-08-07 14:03:28 +02:00
|
|
|
this.textareaElement.nativeElement.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })
|
2020-11-06 17:40:40 +01:00
|
|
|
|
|
|
|
// Use the native textarea autosize according to the text's break lines
|
|
|
|
this.textareaElement.nativeElement.dispatchEvent(new Event('input'))
|
2020-08-07 14:03:28 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
this.form.patchValue({ text })
|
|
|
|
}
|
2017-12-27 16:11:53 +01:00
|
|
|
}
|