diff options
author | Rigel Kent <par@rigelk.eu> | 2018-09-25 15:42:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-25 15:42:58 +0200 |
commit | 660d11e91e1643927028d2d6870a911f569b34d8 (patch) | |
tree | 455a39a397667eaa175a87d4b62b46406e75711a /client/src/app/videos | |
parent | ba6a98b8fad8214338e0d0919eac3439e90569fe (diff) | |
download | PeerTube-660d11e91e1643927028d2d6870a911f569b34d8.tar.gz PeerTube-660d11e91e1643927028d2d6870a911f569b34d8.tar.zst PeerTube-660d11e91e1643927028d2d6870a911f569b34d8.zip |
refactor subscribe button and comment-add for visitor-interact UX (#1100)
* refactor subscribe button for visitor-subscribe UX
* refactor comment-add for visitor-interact UX
Diffstat (limited to 'client/src/app/videos')
5 files changed, 86 insertions, 16 deletions
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 index f65a88d20..9441edfb1 100644 --- 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 | |||
@@ -1,9 +1,11 @@ | |||
1 | <form novalidate [formGroup]="form" (ngSubmit)="formValidated()"> | 1 | <form novalidate [formGroup]="form" (ngSubmit)="formValidated()"> |
2 | <div class="avatar-and-textarea"> | 2 | <div class="avatar-and-textarea"> |
3 | <img [src]="user.accountAvatarUrl" alt="Avatar" /> | 3 | <img [src]="getAvatarUrl()" alt="Avatar" /> |
4 | 4 | ||
5 | <div class="form-group"> | 5 | <div class="form-group"> |
6 | <textarea i18n-placeholder placeholder="Add comment..." autosize | 6 | <textarea i18n-placeholder placeholder="Add comment..." autosize |
7 | [readonly]="(user === null) ? true : false" | ||
8 | (click)="openVisitorModal($event)" | ||
7 | formControlName="text" [ngClass]="{ 'input-error': formErrors['text'] }" | 9 | formControlName="text" [ngClass]="{ 'input-error': formErrors['text'] }" |
8 | (keyup.control.enter)="onValidKey()" (keyup.meta.enter)="onValidKey()" #textarea> | 10 | (keyup.control.enter)="onValidKey()" (keyup.meta.enter)="onValidKey()" #textarea> |
9 | 11 | ||
@@ -20,3 +22,25 @@ | |||
20 | </button> | 22 | </button> |
21 | </div> | 23 | </div> |
22 | </form> | 24 | </form> |
25 | |||
26 | <ng-template #visitorModal let-modal> | ||
27 | <div class="modal-header"> | ||
28 | <h4 class="modal-title" id="modal-basic-title" i18n>You are one step away from commenting</h4> | ||
29 | <button type="button" class="close" aria-label="Close" (click)="hideVisitorModal()"></button> | ||
30 | </div> | ||
31 | <div class="modal-body" i18n> | ||
32 | <span i18n> | ||
33 | If you have an account on this instance, you can login: | ||
34 | </span> | ||
35 | <span class="btn btn-sm mx-3" role="button" (click)="gotoLogin()" i18n>login to comment</span> | ||
36 | <span i18n> | ||
37 | Otherwise you can comment using an account on an ActivityPub-compatible instance: | ||
38 | </span> | ||
39 | <my-remote-subscribe [interact]="true" account="{{ uri }}"></my-remote-subscribe> | ||
40 | </div> | ||
41 | <div class="modal-footer inputs"> | ||
42 | <span i18n class="action-button action-button-cancel" role="button" (click)="hideVisitorModal()"> | ||
43 | Cancel | ||
44 | </span> | ||
45 | </div> | ||
46 | </ng-template> | ||
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 index bb809296a..e998cba5e 100644 --- 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 | |||
@@ -36,7 +36,7 @@ form { | |||
36 | 36 | ||
37 | button { | 37 | button { |
38 | @include peertube-button; | 38 | @include peertube-button; |
39 | @include orange-button | 39 | @include orange-button; |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
@@ -44,4 +44,16 @@ form { | |||
44 | textarea, .submit-comment button { | 44 | textarea, .submit-comment button { |
45 | font-size: 14px !important; | 45 | font-size: 14px !important; |
46 | } | 46 | } |
47 | } | ||
48 | |||
49 | .modal-body { | ||
50 | .btn { | ||
51 | @include peertube-button; | ||
52 | @include orange-button; | ||
53 | } | ||
54 | |||
55 | span { | ||
56 | float: left; | ||
57 | margin-bottom: 20px; | ||
58 | } | ||
47 | } \ No newline at end of file | 59 | } \ No newline at end of file |
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 index 9998685e8..91af113d2 100644 --- 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 | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { Router } from '@angular/router' | ||
2 | import { NotificationsService } from 'angular2-notifications' | 3 | import { NotificationsService } from 'angular2-notifications' |
3 | import { Observable } from 'rxjs' | 4 | import { Observable } from 'rxjs' |
4 | import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model' | 5 | import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model' |
@@ -10,6 +11,8 @@ import { VideoCommentService } from './video-comment.service' | |||
10 | import { I18n } from '@ngx-translate/i18n-polyfill' | 11 | import { I18n } from '@ngx-translate/i18n-polyfill' |
11 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' | 12 | import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' |
12 | import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service' | 13 | import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service' |
14 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | ||
15 | import { AuthService } from '@app/core/auth' | ||
13 | 16 | ||
14 | @Component({ | 17 | @Component({ |
15 | selector: 'my-video-comment-add', | 18 | selector: 'my-video-comment-add', |
@@ -25,15 +28,20 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { | |||
25 | 28 | ||
26 | @Output() commentCreated = new EventEmitter<VideoCommentCreate>() | 29 | @Output() commentCreated = new EventEmitter<VideoCommentCreate>() |
27 | 30 | ||
31 | @ViewChild('visitorModal') visitorModal: NgbModal | ||
28 | @ViewChild('textarea') private textareaElement: ElementRef | 32 | @ViewChild('textarea') private textareaElement: ElementRef |
29 | 33 | ||
30 | private addingComment = false | 34 | private addingComment = false |
35 | private uri: string | ||
31 | 36 | ||
32 | constructor ( | 37 | constructor ( |
33 | protected formValidatorService: FormValidatorService, | 38 | protected formValidatorService: FormValidatorService, |
34 | private videoCommentValidatorsService: VideoCommentValidatorsService, | 39 | private videoCommentValidatorsService: VideoCommentValidatorsService, |
35 | private notificationsService: NotificationsService, | 40 | private notificationsService: NotificationsService, |
36 | private videoCommentService: VideoCommentService, | 41 | private videoCommentService: VideoCommentService, |
42 | private authService: AuthService, | ||
43 | private modalService: NgbModal, | ||
44 | private router: Router, | ||
37 | private i18n: I18n | 45 | private i18n: I18n |
38 | ) { | 46 | ) { |
39 | super() | 47 | super() |
@@ -44,19 +52,23 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { | |||
44 | text: this.videoCommentValidatorsService.VIDEO_COMMENT_TEXT | 52 | text: this.videoCommentValidatorsService.VIDEO_COMMENT_TEXT |
45 | }) | 53 | }) |
46 | 54 | ||
47 | if (this.focusOnInit === true) { | 55 | this.uri = this.router.url |
48 | this.textareaElement.nativeElement.focus() | ||
49 | } | ||
50 | 56 | ||
51 | if (this.parentComment) { | 57 | if (this.user) { |
52 | const mentions = this.parentComments | 58 | if (this.focusOnInit === true) { |
53 | .filter(c => c.account.id !== this.user.account.id) // Don't add mention of ourselves | 59 | this.textareaElement.nativeElement.focus() |
54 | .map(c => '@' + c.by) | 60 | } |
61 | |||
62 | if (this.parentComment) { | ||
63 | const mentions = this.parentComments | ||
64 | .filter(c => c.account.id !== this.user.account.id) // Don't add mention of ourselves | ||
65 | .map(c => '@' + c.by) | ||
55 | 66 | ||
56 | const mentionsSet = new Set(mentions) | 67 | const mentionsSet = new Set(mentions) |
57 | const mentionsText = Array.from(mentionsSet).join(' ') + ' ' | 68 | const mentionsText = Array.from(mentionsSet).join(' ') + ' ' |
58 | 69 | ||
59 | this.form.patchValue({ text: mentionsText }) | 70 | this.form.patchValue({ text: mentionsText }) |
71 | } | ||
60 | } | 72 | } |
61 | } | 73 | } |
62 | 74 | ||
@@ -67,6 +79,20 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { | |||
67 | this.formValidated() | 79 | this.formValidated() |
68 | } | 80 | } |
69 | 81 | ||
82 | openVisitorModal (event) { | ||
83 | if (this.user === null) { // we only open it for visitors | ||
84 | // fixing ng-bootstrap ModalService and the "Expression Changed After It Has Been Checked" Error | ||
85 | event.srcElement.blur() | ||
86 | event.preventDefault() | ||
87 | |||
88 | this.modalService.open(this.visitorModal) | ||
89 | } | ||
90 | } | ||
91 | |||
92 | hideVisitorModal () { | ||
93 | this.modalService.dismissAll() | ||
94 | } | ||
95 | |||
70 | formValidated () { | 96 | formValidated () { |
71 | // If we validate very quickly the comment form, we might comment twice | 97 | // If we validate very quickly the comment form, we might comment twice |
72 | if (this.addingComment) return | 98 | if (this.addingComment) return |
@@ -101,6 +127,17 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { | |||
101 | return this.form.value['text'] | 127 | return this.form.value['text'] |
102 | } | 128 | } |
103 | 129 | ||
130 | getAvatarUrl () { | ||
131 | if (this.user) return this.user.accountAvatarUrl | ||
132 | return window.location.origin + '/client/assets/images/default-avatar.png' | ||
133 | } | ||
134 | |||
135 | gotoLogin () { | ||
136 | this.hideVisitorModal() | ||
137 | this.authService.redirectUrl = this.router.url | ||
138 | this.router.navigate([ '/login' ]) | ||
139 | } | ||
140 | |||
104 | private addCommentReply (commentCreate: VideoCommentCreate) { | 141 | private addCommentReply (commentCreate: VideoCommentCreate) { |
105 | return this.videoCommentService | 142 | return this.videoCommentService |
106 | .addCommentReply(this.video.id, this.parentComment.id, commentCreate) | 143 | .addCommentReply(this.video.id, this.parentComment.id, commentCreate) |
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 index bf6706ed3..9919ac615 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.html +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.html | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | <ng-template [ngIf]="video.commentsEnabled === true"> | 11 | <ng-template [ngIf]="video.commentsEnabled === true"> |
12 | <my-video-comment-add | 12 | <my-video-comment-add |
13 | *ngIf="isUserLoggedIn()" | ||
14 | [video]="video" | 13 | [video]="video" |
15 | [user]="user" | 14 | [user]="user" |
16 | (commentCreated)="onCommentThreadCreated($event)" | 15 | (commentCreated)="onCommentThreadCreated($event)" |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 630345a35..770785d02 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -126,7 +126,7 @@ | |||
126 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> | 126 | <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" /> |
127 | </a> | 127 | </a> |
128 | 128 | ||
129 | <my-subscribe-button #subscribeButton *ngIf="isUserLoggedIn()" [videoChannel]="video.channel" size="small"></my-subscribe-button> | 129 | <my-subscribe-button #subscribeButton [videoChannel]="video.channel" size="small"></my-subscribe-button> |
130 | </div> | 130 | </div> |
131 | 131 | ||
132 | <div class="video-info-by"> | 132 | <div class="video-info-by"> |
@@ -134,8 +134,6 @@ | |||
134 | <span i18n>By {{ video.byAccount }}</span> | 134 | <span i18n>By {{ video.byAccount }}</span> |
135 | <img [src]="video.accountAvatarUrl" alt="Account avatar" /> | 135 | <img [src]="video.accountAvatarUrl" alt="Account avatar" /> |
136 | </a> | 136 | </a> |
137 | |||
138 | <my-help helpType="custom" i18n-customHtml customHtml="You can subscribe to this account via any ActivityPub-capable fediverse instance. For instance with Mastodon or Pleroma you can type in the search box <strong>@{{video.account.name}}@{{video.account.host}}</strong> and subscribe there."></my-help> | ||
139 | </div> | 137 | </div> |
140 | </div> | 138 | </div> |
141 | 139 | ||