From 1942f11d5ee6926ad93dc1b79fae18325ba5de18 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 23 Jun 2020 14:49:20 +0200 Subject: Lazy load all routes --- .../comment/video-comment-add.component.html | 56 ----- .../comment/video-comment-add.component.scss | 82 -------- .../comment/video-comment-add.component.ts | 149 ------------- .../comment/video-comment-thread-tree.model.ts | 7 - .../comment/video-comment.component.html | 95 --------- .../comment/video-comment.component.scss | 189 ----------------- .../comment/video-comment.component.ts | 131 ------------ .../+video-watch/comment/video-comment.model.ts | 48 ----- .../+video-watch/comment/video-comment.service.ts | 149 ------------- .../comment/video-comments.component.html | 98 --------- .../comment/video-comments.component.scss | 53 ----- .../comment/video-comments.component.ts | 232 --------------------- 12 files changed, 1289 deletions(-) delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment-add.component.html delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment-add.component.scss delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment-add.component.ts delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment.component.html delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment.component.scss delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment.component.ts delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment.model.ts delete mode 100644 client/src/app/videos/+video-watch/comment/video-comment.service.ts delete mode 100644 client/src/app/videos/+video-watch/comment/video-comments.component.html delete mode 100644 client/src/app/videos/+video-watch/comment/video-comments.component.scss delete mode 100644 client/src/app/videos/+video-watch/comment/video-comments.component.ts (limited to 'client/src/app/videos/+video-watch/comment') diff --git a/client/src/app/videos/+video-watch/comment/video-comment-add.component.html b/client/src/app/videos/+video-watch/comment/video-comment-add.component.html deleted file mode 100644 index 9b43d91da..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment-add.component.html +++ /dev/null @@ -1,56 +0,0 @@ -
-
- Avatar - -
- -
- {{ formErrors.text }} -
-
-
- -
- - -
-
- - - - - - diff --git a/client/src/app/videos/+video-watch/comment/video-comment-add.component.scss b/client/src/app/videos/+video-watch/comment/video-comment-add.component.scss deleted file mode 100644 index b3725ab94..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment-add.component.scss +++ /dev/null @@ -1,82 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -form { - margin-bottom: 30px; -} - -.avatar-and-textarea { - display: flex; - margin-bottom: 10px; - - img { - @include avatar(25px); - - vertical-align: top; - margin-right: 10px; - } - - .form-group { - flex-grow: 1; - margin: 0; - - textarea { - @include peertube-textarea(100%, 60px); - - &:focus::placeholder { - opacity: 0; - } - } - } -} - -.comment-buttons { - display: flex; - justify-content: flex-end; - - button { - @include peertube-button; - @include disable-outline; - @include disable-default-a-behaviour; - - &:not(:last-child) { - margin-right: .5rem; - } - - &:last-child { - @include orange-button; - } - } - - .cancel-button { - @include tertiary-button; - - font-weight: $font-semibold; - display: inline-block; - padding: 0 10px 0 10px; - white-space: nowrap; - background: transparent; - } -} - -@media screen and (max-width: 600px) { - textarea, .comment-buttons button { - font-size: 14px !important; - } - - textarea { - padding: 5px !important; - } -} - -.modal-body { - .btn { - @include peertube-button; - @include orange-button; - } - - span { - float: left; - margin-bottom: 20px; - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts b/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts deleted file mode 100644 index 79505c779..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Observable } from 'rxjs' -import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' -import { Router } from '@angular/router' -import { Notifier, User } from '@app/core' -import { FormReactive, FormValidatorService, VideoCommentValidatorsService } from '@app/shared/shared-forms' -import { Video } from '@app/shared/shared-main' -import { NgbModal } from '@ng-bootstrap/ng-bootstrap' -import { VideoCommentCreate } from '@shared/models' -import { VideoComment } from './video-comment.model' -import { VideoCommentService } from './video-comment.service' - -@Component({ - selector: 'my-video-comment-add', - templateUrl: './video-comment-add.component.html', - styleUrls: ['./video-comment-add.component.scss'] -}) -export class VideoCommentAddComponent extends FormReactive implements OnInit { - @Input() user: User - @Input() video: Video - @Input() parentComment: VideoComment - @Input() parentComments: VideoComment[] - @Input() focusOnInit = false - - @Output() commentCreated = new EventEmitter() - @Output() cancel = new EventEmitter() - - @ViewChild('visitorModal', { static: true }) visitorModal: NgbModal - @ViewChild('textarea', { static: true }) textareaElement: ElementRef - - addingComment = false - - constructor ( - protected formValidatorService: FormValidatorService, - private videoCommentValidatorsService: VideoCommentValidatorsService, - private notifier: Notifier, - private videoCommentService: VideoCommentService, - private modalService: NgbModal, - private router: Router - ) { - super() - } - - ngOnInit () { - this.buildForm({ - text: this.videoCommentValidatorsService.VIDEO_COMMENT_TEXT - }) - - if (this.user) { - if (this.focusOnInit === true) { - this.textareaElement.nativeElement.focus() - } - - 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.form.patchValue({ text: mentionsText }) - } - } - } - - onValidKey () { - this.check() - if (!this.form.valid) return - - this.formValidated() - } - - openVisitorModal (event: any) { - 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) - } - } - - hideVisitorModal () { - this.modalService.dismissAll() - } - - formValidated () { - // If we validate very quickly the comment form, we might comment twice - if (this.addingComment) return - - this.addingComment = true - - const commentCreate: VideoCommentCreate = this.form.value - let obs: Observable - - if (this.parentComment) { - obs = this.addCommentReply(commentCreate) - } else { - obs = this.addCommentThread(commentCreate) - } - - obs.subscribe( - comment => { - this.addingComment = false - this.commentCreated.emit(comment) - this.form.reset() - }, - - err => { - this.addingComment = false - - this.notifier.error(err.text) - } - ) - } - - isAddButtonDisplayed () { - return this.form.value['text'] - } - - getUri () { - return window.location.href - } - - getAvatarUrl () { - if (this.user) return this.user.accountAvatarUrl - return window.location.origin + '/client/assets/images/default-avatar.png' - } - - gotoLogin () { - this.hideVisitorModal() - this.router.navigate([ '/login' ]) - } - - cancelCommentReply () { - this.cancel.emit(null) - this.form.value['text'] = this.textareaElement.nativeElement.value = '' - } - - 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) - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts b/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts deleted file mode 100644 index 7c2aaeadd..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { VideoCommentThreadTree as VideoCommentThreadTreeServerModel } from '@shared/models' -import { VideoComment } from './video-comment.model' - -export class VideoCommentThreadTree implements VideoCommentThreadTreeServerModel { - comment: VideoComment - children: VideoCommentThreadTree[] -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.html b/client/src/app/videos/+video-watch/comment/video-comment.component.html deleted file mode 100644 index 002de57e4..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.html +++ /dev/null @@ -1,95 +0,0 @@ -
-
- - Avatar - - -
-
- -
- - -
- -
Highlighted comment
- - -
- -
-
Reply
-
Delete
- - -
-
- - - - -
- This comment has been deleted -
-
- - - -
-
- -
-
- - -
-
-
diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.scss b/client/src/app/videos/+video-watch/comment/video-comment.component.scss deleted file mode 100644 index e7ef79561..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.scss +++ /dev/null @@ -1,189 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -.root-comment { - font-size: 15px; - display: flex; - - .left { - display: flex; - flex-direction: column; - align-items: center; - margin-right: 10px; - - .vertical-border { - width: 2px; - height: 100%; - background-color: rgba(0, 0, 0, 0.05); - margin: 10px calc(1rem + 1px); - } - } - - .right { - width: 100%; - } - - .comment-avatar { - @include avatar(36px); - } - - .comment { - flex-grow: 1; - // Fix word-wrap with flex - min-width: 1px; - - .highlighted-comment { - display: inline-block; - background-color: #F5F5F5; - color: #3d3d3d; - padding: 0 5px; - font-size: 13px; - margin-bottom: 5px; - font-weight: $font-semibold; - border-radius: 3px; - } - - .comment-account-date { - display: flex; - margin-bottom: 4px; - - .video-author { - height: 20px; - background-color: #888888; - border-radius: 12px; - margin-bottom: 2px; - max-width: 100%; - box-sizing: border-box; - flex-direction: row; - align-items: center; - display: inline-flex; - padding-right: 6px; - padding-left: 6px; - color: white !important; - } - - .comment-account { - word-break: break-all; - font-weight: 600; - font-size: 90%; - - a { - @include disable-default-a-behaviour; - - color: pvar(--mainForegroundColor); - } - - .comment-account-fid { - opacity: .6; - } - } - - .comment-date { - font-size: 90%; - color: pvar(--greyForegroundColor); - margin-left: 5px; - text-decoration: none; - } - } - - .comment-html { - @include peertube-word-wrap; - - // Mentions - ::ng-deep a { - - &:not(.linkified-url) { - @include disable-default-a-behaviour; - - color: pvar(--mainForegroundColor); - - font-weight: $font-semibold; - } - - } - - // Paragraphs - ::ng-deep p { - margin-bottom: .3rem; - } - - &.comment-html-deleted { - color: pvar(--greyForegroundColor); - margin-bottom: 1rem; - } - } - - .comment-actions { - margin-bottom: 10px; - display: flex; - - ::ng-deep .dropdown-toggle, - .comment-action-reply, - .comment-action-delete { - color: pvar(--greyForegroundColor); - cursor: pointer; - margin-right: 10px; - - &:hover { - color: pvar(--mainForegroundColor); - } - } - - ::ng-deep .action-button { - background-color: transparent; - padding: 0; - font-weight: unset; - } - } - - my-video-comment-add { - ::ng-deep form { - margin-top: 1rem; - margin-bottom: 0; - } - } - } - - .children { - // Reduce avatars size for replies - .comment-avatar { - @include avatar(25px); - } - - .left { - margin-right: 6px; - } - } -} - -@media screen and (max-width: 1200px) { - .children { - margin-left: -10px; - } -} - -@media screen and (max-width: 600px) { - .root-comment { - .children { - margin-left: -20px; - - .left { - align-items: flex-start; - - .vertical-border { - margin-left: 2px; - } - } - } - - .comment { - .comment-account-date { - flex-direction: column; - - .comment-date { - margin-left: 0; - } - } - } - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.ts b/client/src/app/videos/+video-watch/comment/video-comment.component.ts deleted file mode 100644 index 27846c1ad..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core' -import { MarkdownService, Notifier, UserService } from '@app/core' -import { AuthService } from '@app/core/auth' -import { Account, Actor, Video } from '@app/shared/shared-main' -import { User, UserRight } from '@shared/models' -import { VideoCommentThreadTree } from './video-comment-thread-tree.model' -import { VideoComment } from './video-comment.model' - -@Component({ - selector: 'my-video-comment', - templateUrl: './video-comment.component.html', - styleUrls: ['./video-comment.component.scss'] -}) -export class VideoCommentComponent implements OnInit, OnChanges { - @Input() video: Video - @Input() comment: VideoComment - @Input() parentComments: VideoComment[] = [] - @Input() commentTree: VideoCommentThreadTree - @Input() inReplyToCommentId: number - @Input() highlightedComment = false - @Input() firstInThread = false - - @Output() wantedToDelete = new EventEmitter() - @Output() wantedToReply = new EventEmitter() - @Output() threadCreated = new EventEmitter() - @Output() resetReply = new EventEmitter() - @Output() timestampClicked = new EventEmitter() - - sanitizedCommentHTML = '' - newParentComments: VideoComment[] = [] - - commentAccount: Account - commentUser: User - - constructor ( - private markdownService: MarkdownService, - private authService: AuthService, - private userService: UserService, - private notifier: Notifier - ) {} - - get user () { - return this.authService.getUser() - } - - ngOnInit () { - this.init() - } - - ngOnChanges () { - this.init() - } - - onCommentReplyCreated (createdComment: VideoComment) { - if (!this.commentTree) { - this.commentTree = { - comment: this.comment, - children: [] - } - - this.threadCreated.emit(this.commentTree) - } - - this.commentTree.children.unshift({ - comment: createdComment, - children: [] - }) - this.resetReply.emit() - } - - onWantToReply (comment?: VideoComment) { - this.wantedToReply.emit(comment || this.comment) - } - - onWantToDelete (comment?: VideoComment) { - this.wantedToDelete.emit(comment || this.comment) - } - - isUserLoggedIn () { - return this.authService.isLoggedIn() - } - - onResetReply () { - this.resetReply.emit() - } - - handleTimestampClicked (timestamp: number) { - this.timestampClicked.emit(timestamp) - } - - isRemovableByUser () { - return this.comment.account && this.isUserLoggedIn() && - ( - this.user.account.id === this.comment.account.id || - this.user.account.id === this.video.account.id || - this.user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) - ) - } - - switchToDefaultAvatar ($event: Event) { - ($event.target as HTMLImageElement).src = Actor.GET_DEFAULT_AVATAR_URL() - } - - private getUserIfNeeded (account: Account) { - if (!account.userId) return - if (!this.authService.isLoggedIn()) return - - const user = this.authService.getUser() - if (user.hasRight(UserRight.MANAGE_USERS)) { - this.userService.getUserWithCache(account.userId) - .subscribe( - user => this.commentUser = user, - - err => this.notifier.error(err.message) - ) - } - } - - private async init () { - const html = await this.markdownService.textMarkdownToHTML(this.comment.text, true) - this.sanitizedCommentHTML = await this.markdownService.processVideoTimestamps(html) - this.newParentComments = this.parentComments.concat([ this.comment ]) - - if (this.comment.account) { - this.commentAccount = new Account(this.comment.account) - this.getUserIfNeeded(this.commentAccount) - } else { - this.comment.account = null - } - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.model.ts b/client/src/app/videos/+video-watch/comment/video-comment.model.ts deleted file mode 100644 index e85443196..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment.model.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { getAbsoluteAPIUrl } from '@app/helpers' -import { Actor } from '@app/shared/shared-main' -import { Account as AccountInterface, VideoComment as VideoCommentServerModel } from '@shared/models' - -export class VideoComment implements VideoCommentServerModel { - id: number - url: string - text: string - threadId: number - inReplyToCommentId: number - videoId: number - createdAt: Date | string - updatedAt: Date | string - deletedAt: Date | string - isDeleted: boolean - account: AccountInterface - totalRepliesFromVideoAuthor: number - totalReplies: number - by: string - accountAvatarUrl: string - - isLocal: boolean - - constructor (hash: VideoCommentServerModel) { - this.id = hash.id - this.url = hash.url - this.text = hash.text - this.threadId = hash.threadId - this.inReplyToCommentId = hash.inReplyToCommentId - this.videoId = hash.videoId - this.createdAt = new Date(hash.createdAt.toString()) - this.updatedAt = new Date(hash.updatedAt.toString()) - this.deletedAt = hash.deletedAt ? new Date(hash.deletedAt.toString()) : null - this.isDeleted = hash.isDeleted - this.account = hash.account - this.totalRepliesFromVideoAuthor = hash.totalRepliesFromVideoAuthor - this.totalReplies = hash.totalReplies - - if (this.account) { - this.by = Actor.CREATE_BY_STRING(this.account.name, this.account.host) - this.accountAvatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.account) - - const absoluteAPIUrl = getAbsoluteAPIUrl() - const thisHost = new URL(absoluteAPIUrl).host - this.isLocal = this.account.host.trim() === thisHost - } - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.service.ts b/client/src/app/videos/+video-watch/comment/video-comment.service.ts deleted file mode 100644 index a73fb9ca8..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comment.service.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Observable } from 'rxjs' -import { catchError, map } from 'rxjs/operators' -import { HttpClient, HttpParams } from '@angular/common/http' -import { Injectable } from '@angular/core' -import { ComponentPaginationLight, RestExtractor, RestService } from '@app/core' -import { objectLineFeedToHtml } from '@app/helpers' -import { - FeedFormat, - ResultList, - VideoComment as VideoCommentServerModel, - VideoCommentCreate, - VideoCommentThreadTree as VideoCommentThreadTreeServerModel -} from '@shared/models' -import { environment } from '../../../../environments/environment' -import { VideoCommentThreadTree } from './video-comment-thread-tree.model' -import { VideoComment } from './video-comment.model' - -@Injectable() -export class VideoCommentService { - private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' - private static BASE_FEEDS_URL = environment.apiUrl + '/feeds/video-comments.' - - constructor ( - private authHttp: HttpClient, - private restExtractor: RestExtractor, - private restService: RestService - ) {} - - addCommentThread (videoId: number | string, comment: VideoCommentCreate) { - const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads' - const normalizedComment = objectLineFeedToHtml(comment, 'text') - - return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment) - .pipe( - map(data => this.extractVideoComment(data.comment)), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - addCommentReply (videoId: number | string, inReplyToCommentId: number, comment: VideoCommentCreate) { - const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comments/' + inReplyToCommentId - const normalizedComment = objectLineFeedToHtml(comment, 'text') - - return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment) - .pipe( - map(data => this.extractVideoComment(data.comment)), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - getVideoCommentThreads (parameters: { - videoId: number | string, - componentPagination: ComponentPaginationLight, - sort: string - }): Observable> { - const { videoId, componentPagination, sort } = parameters - - const pagination = this.restService.componentPaginationToRestPagination(componentPagination) - - let params = new HttpParams() - params = this.restService.addRestGetParams(params, pagination, sort) - - const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads' - return this.authHttp.get>(url, { params }) - .pipe( - map(result => this.extractVideoComments(result)), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - getVideoThreadComments (parameters: { - videoId: number | string, - threadId: number - }): Observable { - const { videoId, threadId } = parameters - const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comment-threads/${threadId}` - - return this.authHttp - .get(url) - .pipe( - map(tree => this.extractVideoCommentTree(tree)), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - deleteVideoComment (videoId: number | string, commentId: number) { - const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comments/${commentId}` - - return this.authHttp - .delete(url) - .pipe( - map(this.restExtractor.extractDataBool), - catchError(err => this.restExtractor.handleError(err)) - ) - } - - getVideoCommentsFeeds (videoUUID?: string) { - const feeds = [ - { - format: FeedFormat.RSS, - label: 'rss 2.0', - url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.RSS.toLowerCase() - }, - { - format: FeedFormat.ATOM, - label: 'atom 1.0', - url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.ATOM.toLowerCase() - }, - { - format: FeedFormat.JSON, - label: 'json 1.0', - url: VideoCommentService.BASE_FEEDS_URL + FeedFormat.JSON.toLowerCase() - } - ] - - if (videoUUID !== undefined) { - for (const feed of feeds) { - feed.url += '?videoId=' + videoUUID - } - } - - return feeds - } - - private extractVideoComment (videoComment: VideoCommentServerModel) { - return new VideoComment(videoComment) - } - - private extractVideoComments (result: ResultList) { - const videoCommentsJson = result.data - const totalComments = result.total - const comments: VideoComment[] = [] - - for (const videoCommentJson of videoCommentsJson) { - comments.push(new VideoComment(videoCommentJson)) - } - - return { data: comments, total: totalComments } - } - - private extractVideoCommentTree (tree: VideoCommentThreadTreeServerModel) { - if (!tree) return tree as VideoCommentThreadTree - - tree.comment = new VideoComment(tree.comment) - tree.children.forEach(c => this.extractVideoCommentTree(c)) - - return tree as VideoCommentThreadTree - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.html b/client/src/app/videos/+video-watch/comment/video-comments.component.html deleted file mode 100644 index dd1d43560..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.html +++ /dev/null @@ -1,98 +0,0 @@ -
-
-

- - - 1 Comment - {{ componentPagination.totalItems }} Comments - - Comments -

- - - -
- -
- - -
-
-
- - - - -
No comments.
- -
-
-
- -
- -
- -
- - - - - - View {{ comment.totalReplies }} replies from {{ video?.account?.displayName || 'the author' }} and others - - - View {{ comment.totalReplies }} replies from {{ video?.account?.displayName || 'the author' }} - - - View {{ comment.totalReplies }} replies - - -
-
- -
-
-
- -
- Comments are disabled. -
-
diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.scss b/client/src/app/videos/+video-watch/comment/video-comments.component.scss deleted file mode 100644 index df42fae73..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.scss +++ /dev/null @@ -1,53 +0,0 @@ -@import '_variables'; -@import '_mixins'; - -#highlighted-comment { - margin-bottom: 25px; -} - -.view-replies { - font-weight: $font-semibold; - font-size: 15px; - cursor: pointer; -} - -.glyphicon, .comment-thread-loading { - margin-right: 5px; - display: inline-block; - font-size: 13px; -} - -.title-block { - .title-page { - margin-right: 0; - } - - my-feed { - display: inline-block; - margin-left: 5px; - opacity: 0; - transition: ease-in .2s opacity; - } - &:hover my-feed { - opacity: 1; - } -} - -#dropdown-sort-comments { - font-weight: 600; - text-transform: uppercase; - border: none; - transform: translateY(-7%); -} - -@media screen and (max-width: 600px) { - .view-replies { - margin-left: 46px; - } -} - -@media screen and (max-width: 450px) { - .view-replies { - font-size: 14px; - } -} diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.ts b/client/src/app/videos/+video-watch/comment/video-comments.component.ts deleted file mode 100644 index df0018ec6..000000000 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Subject, Subscription } from 'rxjs' -import { Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core' -import { ActivatedRoute } from '@angular/router' -import { AuthService, ComponentPagination, ConfirmService, hasMoreItems, Notifier, User } from '@app/core' -import { HooksService } from '@app/core/plugins/hooks.service' -import { Syndication, VideoDetails } from '@app/shared/shared-main' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { VideoCommentThreadTree } from './video-comment-thread-tree.model' -import { VideoComment } from './video-comment.model' -import { VideoCommentService } from './video-comment.service' - -@Component({ - selector: 'my-video-comments', - templateUrl: './video-comments.component.html', - styleUrls: ['./video-comments.component.scss'] -}) -export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy { - @ViewChild('commentHighlightBlock') commentHighlightBlock: ElementRef - @Input() video: VideoDetails - @Input() user: User - - @Output() timestampClicked = new EventEmitter() - - comments: VideoComment[] = [] - highlightedThread: VideoComment - sort = '-createdAt' - componentPagination: ComponentPagination = { - currentPage: 1, - itemsPerPage: 10, - totalItems: null - } - inReplyToCommentId: number - threadComments: { [ id: number ]: VideoCommentThreadTree } = {} - threadLoading: { [ id: number ]: boolean } = {} - - syndicationItems: Syndication[] = [] - - onDataSubject = new Subject() - - private sub: Subscription - - constructor ( - private authService: AuthService, - private notifier: Notifier, - private confirmService: ConfirmService, - private videoCommentService: VideoCommentService, - private activatedRoute: ActivatedRoute, - private i18n: I18n, - private hooks: HooksService - ) {} - - ngOnInit () { - // Find highlighted comment in params - this.sub = this.activatedRoute.params.subscribe( - params => { - if (params['threadId']) { - const highlightedThreadId = +params['threadId'] - this.processHighlightedThread(highlightedThreadId) - } - } - ) - } - - ngOnChanges (changes: SimpleChanges) { - if (changes['video']) { - this.resetVideo() - } - } - - ngOnDestroy () { - if (this.sub) this.sub.unsubscribe() - } - - viewReplies (commentId: number, highlightThread = false) { - this.threadLoading[commentId] = true - - const params = { - videoId: this.video.id, - threadId: commentId - } - - const obs = this.hooks.wrapObsFun( - this.videoCommentService.getVideoThreadComments.bind(this.videoCommentService), - params, - 'video-watch', - 'filter:api.video-watch.video-thread-replies.list.params', - 'filter:api.video-watch.video-thread-replies.list.result' - ) - - obs.subscribe( - res => { - this.threadComments[commentId] = res - this.threadLoading[commentId] = false - this.hooks.runAction('action:video-watch.video-thread-replies.loaded', 'video-watch', { data: res }) - - if (highlightThread) { - this.highlightedThread = new VideoComment(res.comment) - - // Scroll to the highlighted thread - setTimeout(() => this.commentHighlightBlock.nativeElement.scrollIntoView(), 0) - } - }, - - err => this.notifier.error(err.message) - ) - } - - loadMoreThreads () { - const params = { - videoId: this.video.id, - componentPagination: this.componentPagination, - sort: this.sort - } - - const obs = this.hooks.wrapObsFun( - this.videoCommentService.getVideoCommentThreads.bind(this.videoCommentService), - params, - 'video-watch', - 'filter:api.video-watch.video-threads.list.params', - 'filter:api.video-watch.video-threads.list.result' - ) - - obs.subscribe( - res => { - this.comments = this.comments.concat(res.data) - this.componentPagination.totalItems = res.total - - this.onDataSubject.next(res.data) - this.hooks.runAction('action:video-watch.video-threads.loaded', 'video-watch', { data: this.componentPagination }) - }, - - err => this.notifier.error(err.message) - ) - } - - onCommentThreadCreated (comment: VideoComment) { - this.comments.unshift(comment) - } - - onWantedToReply (comment: VideoComment) { - this.inReplyToCommentId = comment.id - } - - onResetReply () { - this.inReplyToCommentId = undefined - } - - onThreadCreated (commentTree: VideoCommentThreadTree) { - this.viewReplies(commentTree.comment.id) - } - - handleSortChange (sort: string) { - if (this.sort === sort) return - - this.sort = sort - this.resetVideo() - } - - handleTimestampClicked (timestamp: number) { - this.timestampClicked.emit(timestamp) - } - - async onWantedToDelete (commentToDelete: VideoComment) { - let message = 'Do you really want to delete this comment?' - - if (commentToDelete.isLocal || this.video.isLocal) { - message += this.i18n(' The deletion will be sent to remote instances so they can reflect the change.') - } else { - message += this.i18n(' It is a remote comment, so the deletion will only be effective on your instance.') - } - - const res = await this.confirmService.confirm(message, this.i18n('Delete')) - if (res === false) return - - this.videoCommentService.deleteVideoComment(commentToDelete.videoId, commentToDelete.id) - .subscribe( - () => { - if (this.highlightedThread?.id === commentToDelete.id) { - commentToDelete = this.comments.find(c => c.id === commentToDelete.id) - - this.highlightedThread = undefined - } - - // Mark the comment as deleted - this.softDeleteComment(commentToDelete) - }, - - err => this.notifier.error(err.message) - ) - } - - isUserLoggedIn () { - return this.authService.isLoggedIn() - } - - onNearOfBottom () { - if (hasMoreItems(this.componentPagination)) { - this.componentPagination.currentPage++ - this.loadMoreThreads() - } - } - - private softDeleteComment (comment: VideoComment) { - comment.isDeleted = true - comment.deletedAt = new Date() - comment.text = '' - comment.account = null - } - - private resetVideo () { - if (this.video.commentsEnabled === true) { - // Reset all our fields - this.highlightedThread = null - this.comments = [] - this.threadComments = {} - this.threadLoading = {} - this.inReplyToCommentId = undefined - this.componentPagination.currentPage = 1 - this.componentPagination.totalItems = null - - this.syndicationItems = this.videoCommentService.getVideoCommentsFeeds(this.video.uuid) - this.loadMoreThreads() - } - } - - private processHighlightedThread (highlightedThreadId: number) { - this.highlightedThread = this.comments.find(c => c.id === highlightedThreadId) - - const highlightThread = true - this.viewReplies(highlightedThreadId, highlightThread) - } -} -- cgit v1.2.3