aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRigel Kent <par@rigelk.eu>2018-09-25 15:42:58 +0200
committerGitHub <noreply@github.com>2018-09-25 15:42:58 +0200
commit660d11e91e1643927028d2d6870a911f569b34d8 (patch)
tree455a39a397667eaa175a87d4b62b46406e75711a
parentba6a98b8fad8214338e0d0919eac3439e90569fe (diff)
downloadPeerTube-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
-rw-r--r--client/src/app/+video-channels/video-channels.component.html2
-rw-r--r--client/src/app/search/search.component.html2
-rw-r--r--client/src/app/shared/shared.module.ts4
-rw-r--r--client/src/app/shared/user-subscription/index.ts1
-rw-r--r--client/src/app/shared/user-subscription/remote-subscribe.component.html25
-rw-r--r--client/src/app/shared/user-subscription/remote-subscribe.component.scss5
-rw-r--r--client/src/app/shared/user-subscription/remote-subscribe.component.ts43
-rw-r--r--client/src/app/shared/user-subscription/subscribe-button.component.html60
-rw-r--r--client/src/app/shared/user-subscription/subscribe-button.component.scss67
-rw-r--r--client/src/app/shared/user-subscription/subscribe-button.component.ts46
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comment-add.component.html26
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comment-add.component.scss14
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comment-add.component.ts57
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comments.component.html1
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html4
-rw-r--r--client/src/sass/application.scss9
-rw-r--r--client/src/sass/include/_bootstrap.scss2
17 files changed, 292 insertions, 76 deletions
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
index 8d6f81e1b..c65b5713d 100644
--- a/client/src/app/+video-channels/video-channels.component.html
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -9,7 +9,7 @@
9 <div class="actor-display-name">{{ videoChannel.displayName }}</div> 9 <div class="actor-display-name">{{ videoChannel.displayName }}</div>
10 <div class="actor-name">{{ videoChannel.nameWithHost }}</div> 10 <div class="actor-name">{{ videoChannel.nameWithHost }}</div>
11 11
12 <my-subscribe-button #subscribeButton *ngIf="isUserLoggedIn()" [videoChannel]="videoChannel"></my-subscribe-button> 12 <my-subscribe-button #subscribeButton [videoChannel]="videoChannel"></my-subscribe-button>
13 </div> 13 </div>
14 <div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div> 14 <div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div>
15 15
diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html
index c4072b291..216905cf0 100644
--- a/client/src/app/search/search.component.html
+++ b/client/src/app/search/search.component.html
@@ -41,7 +41,7 @@
41 <div i18n class="video-channel-followers">{{ result.followersCount }} subscribers</div> 41 <div i18n class="video-channel-followers">{{ result.followersCount }} subscribers</div>
42 </div> 42 </div>
43 43
44 <my-subscribe-button *ngIf="isUserLoggedIn()" [videoChannel]="result"></my-subscribe-button> 44 <my-subscribe-button [videoChannel]="result"></my-subscribe-button>
45 </div> 45 </div>
46 46
47 <div *ngIf="isVideo(result)" class="entry video"> 47 <div *ngIf="isVideo(result)" class="entry video">
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index 1e71feb86..076f1d275 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -53,7 +53,7 @@ import { PeertubeCheckboxComponent } from '@app/shared/forms/peertube-checkbox.c
53import { VideoImportService } from '@app/shared/video-import/video-import.service' 53import { VideoImportService } from '@app/shared/video-import/video-import.service'
54import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' 54import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component'
55import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' 55import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
56import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription' 56import { SubscribeButtonComponent, RemoteSubscribeComponent, UserSubscriptionService } from '@app/shared/user-subscription'
57import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component' 57import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component'
58import { OverviewService } from '@app/shared/overview' 58import { OverviewService } from '@app/shared/overview'
59 59
@@ -93,6 +93,7 @@ import { OverviewService } from '@app/shared/overview'
93 ReactiveFileComponent, 93 ReactiveFileComponent,
94 PeertubeCheckboxComponent, 94 PeertubeCheckboxComponent,
95 SubscribeButtonComponent, 95 SubscribeButtonComponent,
96 RemoteSubscribeComponent,
96 InstanceFeaturesTableComponent 97 InstanceFeaturesTableComponent
97 ], 98 ],
98 99
@@ -127,6 +128,7 @@ import { OverviewService } from '@app/shared/overview'
127 ReactiveFileComponent, 128 ReactiveFileComponent,
128 PeertubeCheckboxComponent, 129 PeertubeCheckboxComponent,
129 SubscribeButtonComponent, 130 SubscribeButtonComponent,
131 RemoteSubscribeComponent,
130 InstanceFeaturesTableComponent, 132 InstanceFeaturesTableComponent,
131 133
132 NumberFormatterPipe, 134 NumberFormatterPipe,
diff --git a/client/src/app/shared/user-subscription/index.ts b/client/src/app/shared/user-subscription/index.ts
index faddae66a..e76940f7b 100644
--- a/client/src/app/shared/user-subscription/index.ts
+++ b/client/src/app/shared/user-subscription/index.ts
@@ -1,2 +1,3 @@
1export * from './user-subscription.service' 1export * from './user-subscription.service'
2export * from './subscribe-button.component' 2export * from './subscribe-button.component'
3export * from './remote-subscribe.component'
diff --git a/client/src/app/shared/user-subscription/remote-subscribe.component.html b/client/src/app/shared/user-subscription/remote-subscribe.component.html
new file mode 100644
index 000000000..3762142f2
--- /dev/null
+++ b/client/src/app/shared/user-subscription/remote-subscribe.component.html
@@ -0,0 +1,25 @@
1<form novalidate [formGroup]="form"
2 (ngSubmit)="formValidated()">
3 <div class="form-group">
4 <input type="email"
5 formControlName="text"
6 class="form-control"
7 (keyup.control.enter)="onValidKey()" (keyup.meta.enter)="onValidKey()"
8 placeholder="jane_doe@example.com">
9 </div>
10 <button type="submit"
11 [disabled]="!form.valid"
12 class="btn btn-sm btn-remote-follow"
13 i18n>
14 <span *ngIf="!interact">Remote subscribe</span>
15 <span *ngIf="interact">Remote interact</span>
16 </button>
17 <my-help *ngIf="!interact && showHelp"
18 helpType="custom"
19 i18n-customHtml customHtml="You can subscribe to the channel via any ActivityPub-capable fediverse instance. For instance with Mastodon or Pleroma you can type the channel URL in the search box and subscribe there.">
20 </my-help>
21 <my-help *ngIf="showHelp && interact"
22 helpType="custom"
23 i18n-customHtml customHtml="You can interact with this via any ActivityPub-capable fediverse instance. For instance with Mastodon or Pleroma you can type the current URL in the search box and interact with it there.">
24 </my-help>
25</form> \ No newline at end of file
diff --git a/client/src/app/shared/user-subscription/remote-subscribe.component.scss b/client/src/app/shared/user-subscription/remote-subscribe.component.scss
new file mode 100644
index 000000000..e49271079
--- /dev/null
+++ b/client/src/app/shared/user-subscription/remote-subscribe.component.scss
@@ -0,0 +1,5 @@
1@import '_mixins';
2
3.btn-remote-follow {
4 @include orange-button;
5} \ No newline at end of file
diff --git a/client/src/app/shared/user-subscription/remote-subscribe.component.ts b/client/src/app/shared/user-subscription/remote-subscribe.component.ts
new file mode 100644
index 000000000..7a81108cd
--- /dev/null
+++ b/client/src/app/shared/user-subscription/remote-subscribe.component.ts
@@ -0,0 +1,43 @@
1import { Component, Input, OnInit } from '@angular/core'
2import { FormReactive } from '@app/shared/forms/form-reactive'
3import {
4 FormValidatorService,
5 UserValidatorsService
6} from '@app/shared/forms/form-validators'
7
8@Component({
9 selector: 'my-remote-subscribe',
10 templateUrl: './remote-subscribe.component.html',
11 styleUrls: ['./remote-subscribe.component.scss']
12})
13export class RemoteSubscribeComponent extends FormReactive implements OnInit {
14 @Input() account: string
15 @Input() interact = false
16 @Input() showHelp = false
17
18 constructor (
19 protected formValidatorService: FormValidatorService,
20 private userValidatorsService: UserValidatorsService
21 ) {
22 super()
23 }
24
25 ngOnInit () {
26 this.buildForm({
27 text: this.userValidatorsService.USER_EMAIL
28 })
29 }
30
31 onValidKey () {
32 this.onValueChanged()
33 if (!this.form.valid) return
34
35 this.formValidated()
36 }
37
38 formValidated () {
39 const address = this.form.value['text']
40 const [ , hostname ] = address.split('@')
41 window.open(`https://${hostname}/authorize_interaction?acct=${this.account}`)
42 }
43}
diff --git a/client/src/app/shared/user-subscription/subscribe-button.component.html b/client/src/app/shared/user-subscription/subscribe-button.component.html
index 34c024c17..b62fb7dfa 100644
--- a/client/src/app/shared/user-subscription/subscribe-button.component.html
+++ b/client/src/app/shared/user-subscription/subscribe-button.component.html
@@ -1,15 +1,45 @@
1<span i18n *ngIf="subscribed === false" class="subscribe-button" [ngClass]="size" role="button" (click)="subscribe()"> 1<div class="btn-group-subscribe btn-group"
2 <span>Subscribe</span> 2 [ngClass]="{'subscribe-button': subscribed !== true, 'unsubscribe-button': subscribed === true}">
3 <span *ngIf="displayFollowers && videoChannel.followersCount !== 0" class="followers-count"> 3 <button *ngIf="subscribed === false && isUserLoggedIn()" type="button"
4 {{ videoChannel.followersCount | myNumberFormatter }} 4 class="btn btn-sm" role="button"
5 </span> 5 (click)="subscribe()" i18n>
6</span> 6 <span>
7 7 Subscribe
8<span *ngIf="subscribed === true" class="unsubscribe-button" [ngClass]="size" role="button" (click)="unsubscribe()"> 8 </span>
9 <span class="subscribed" i18n>Subscribed</span> 9 <span *ngIf="displayFollowers && videoChannel.followersCount !== 0" class="followers-count">
10 <span class="unsubscribe" i18n>Unsubscribe</span> 10 {{ videoChannel.followersCount | myNumberFormatter }}
11 11 </span>
12 <span *ngIf="displayFollowers && videoChannel.followersCount !== 0" class="followers-count"> 12 </button>
13 {{ videoChannel.followersCount | myNumberFormatter }} 13 <button *ngIf="subscribed === true" type="button"
14 </span> 14 class="btn btn-sm" role="button"
15</span> 15 (click)="unsubscribe()" i18n>Unsubscribe</button>
16
17 <div class="btn-group" ngbDropdown autoClose="outside"
18 placement="bottom-right" role="group"
19 aria-label="Multiple ways to subscribe to the current channel">
20 <button class="btn btn-sm dropdown-toggle-split" ngbDropdownToggle>
21 <span *ngIf="!isUserLoggedIn()">
22 Subscribe
23 </span>
24 <span *ngIf="displayFollowers && videoChannel.followersCount !== 0" class="followers-count">
25 {{ videoChannel.followersCount | myNumberFormatter }}
26 </span>
27 </button>
28 <div class="dropdown-menu" ngbDropdownMenu>
29
30 <h6 class="dropdown-header" i18n>Using an ActivityPub-compatible account</h6>
31 <button class="dropdown-item" (click)="subscribe()"
32 *ngIf="subscribed === false">
33 <span *ngIf="!isUserLoggedIn()" i18n>Subscribe with an account on {{ videoChannel.host }}</span>
34 <span *ngIf="isUserLoggedIn()" i18n>Subscribe with your local account</span>
35 </button>
36 <button class="dropdown-item" i18n>Subscribe with a remote account:</button>
37 <my-remote-subscribe showHelp="true" account="{{ uriAccount }}"></my-remote-subscribe>
38 <div class="dropdown-divider"></div>
39
40 <h6 class="dropdown-header" i18n>Using a syndication feed</h6>
41 <button (click)="rssOpen()" class="dropdown-item" i18n>Subscribe via RSS</button>
42
43 </div>
44 </div>
45</div> \ No newline at end of file
diff --git a/client/src/app/shared/user-subscription/subscribe-button.component.scss b/client/src/app/shared/user-subscription/subscribe-button.component.scss
index b78d2f59c..7a8a8ee08 100644
--- a/client/src/app/shared/user-subscription/subscribe-button.component.scss
+++ b/client/src/app/shared/user-subscription/subscribe-button.component.scss
@@ -1,51 +1,46 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3 3
4.subscribe-button { 4.btn-group-subscribe {
5 @include peertube-button; 5 @include peertube-button;
6 @include orange-button; 6 @include disable-default-a-behaviour;
7} 7 float: right;
8 padding: 0;
8 9
9.unsubscribe-button { 10 &.btn-group > .btn:not(.dropdown-toggle) {
10 @include peertube-button; 11 padding-right: 5px;
11 @include grey-button 12 font-size: 15px;
12} 13 }
14 &.btn-group > .btn-group:not(:first-child) > .btn {
15 padding-left: 2px;
16 }
13 17
14.subscribe-button, 18 &.subscribe-button {
15.unsubscribe-button { 19 .btn {
16 display: inline-block; 20 @include orange-button;
21 font-weight: 600;
22 }
17 23
18 &.small { 24 span.followers-count {
19 min-width: 75px; 25 padding-left:5px;
20 height: 20px; 26 }
21 line-height: 20px;
22 font-size: 13px;
23 } 27 }
24 28 &.unsubscribe-button {
25 &.normal { 29 .btn {
26 min-width: 120px; 30 @include grey-button;
27 height: 30px; 31 font-weight: 600;
28 line-height: 30px; 32 }
29 font-size: 16px;
30 } 33 }
31}
32 34
33.unsubscribe-button { 35 .dropdown-header {
34 .subscribed { 36 padding-left: 1rem;
35 display: inline;
36 } 37 }
37 38
38 .unsubscribe { 39 /deep/ form {
39 display: none; 40 padding: 0.25rem 1rem;
40 } 41 }
41 42
42 &:hover { 43 input {
43 .subscribed { 44 @include peertube-input-text(100%);
44 display: none;
45 }
46
47 .unsubscribe {
48 display: inline;
49 }
50 } 45 }
51} \ No newline at end of file 46}
diff --git a/client/src/app/shared/user-subscription/subscribe-button.component.ts b/client/src/app/shared/user-subscription/subscribe-button.component.ts
index b5873a2ee..e3c758942 100644
--- a/client/src/app/shared/user-subscription/subscribe-button.component.ts
+++ b/client/src/app/shared/user-subscription/subscribe-button.component.ts
@@ -1,4 +1,6 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, Input, OnInit } from '@angular/core'
2import { Router } from '@angular/router'
3import { AuthService } from '@app/core'
2import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' 4import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service'
3import { VideoChannel } from '@app/shared/video-channel/video-channel.model' 5import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
4import { NotificationsService } from 'angular2-notifications' 6import { NotificationsService } from 'angular2-notifications'
@@ -17,6 +19,8 @@ export class SubscribeButtonComponent implements OnInit {
17 subscribed: boolean 19 subscribed: boolean
18 20
19 constructor ( 21 constructor (
22 private authService: AuthService,
23 private router: Router,
20 private notificationsService: NotificationsService, 24 private notificationsService: NotificationsService,
21 private userSubscriptionService: UserSubscriptionService, 25 private userSubscriptionService: UserSubscriptionService,
22 private i18n: I18n 26 private i18n: I18n
@@ -26,16 +30,30 @@ export class SubscribeButtonComponent implements OnInit {
26 return this.videoChannel.name + '@' + this.videoChannel.host 30 return this.videoChannel.name + '@' + this.videoChannel.host
27 } 31 }
28 32
33 get uriAccount () {
34 return this.videoChannel.ownerAccount.name + '@' + this.videoChannel.host
35 }
36
29 ngOnInit () { 37 ngOnInit () {
30 this.userSubscriptionService.isSubscriptionExists(this.uri) 38 if (this.isUserLoggedIn()) {
31 .subscribe( 39 this.userSubscriptionService.isSubscriptionExists(this.uri)
32 res => this.subscribed = res[this.uri], 40 .subscribe(
41 res => this.subscribed = res[this.uri],
33 42
34 err => this.notificationsService.error(this.i18n('Error'), err.message) 43 err => this.notificationsService.error(this.i18n('Error'), err.message)
35 ) 44 )
45 }
36 } 46 }
37 47
38 subscribe () { 48 subscribe () {
49 if (this.isUserLoggedIn()) {
50 this.localSubscribe()
51 } else {
52 this.gotoLogin()
53 }
54 }
55
56 localSubscribe () {
39 this.userSubscriptionService.addSubscription(this.uri) 57 this.userSubscriptionService.addSubscription(this.uri)
40 .subscribe( 58 .subscribe(
41 () => { 59 () => {
@@ -52,6 +70,12 @@ export class SubscribeButtonComponent implements OnInit {
52 } 70 }
53 71
54 unsubscribe () { 72 unsubscribe () {
73 if (this.isUserLoggedIn()) {
74 this.localUnsubscribe()
75 }
76 }
77
78 localUnsubscribe () {
55 this.userSubscriptionService.deleteSubscription(this.uri) 79 this.userSubscriptionService.deleteSubscription(this.uri)
56 .subscribe( 80 .subscribe(
57 () => { 81 () => {
@@ -66,4 +90,16 @@ export class SubscribeButtonComponent implements OnInit {
66 err => this.notificationsService.error(this.i18n('Error'), err.message) 90 err => this.notificationsService.error(this.i18n('Error'), err.message)
67 ) 91 )
68 } 92 }
93
94 isUserLoggedIn () {
95 return this.authService.isLoggedIn()
96 }
97
98 gotoLogin () {
99 this.router.navigate([ '/login' ])
100 }
101
102 rssOpen () {
103 window.open('')
104 }
69} 105}
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 @@
1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
2import { Router } from '@angular/router'
2import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
3import { Observable } from 'rxjs' 4import { Observable } from 'rxjs'
4import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model' 5import { VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model'
@@ -10,6 +11,8 @@ import { VideoCommentService } from './video-comment.service'
10import { I18n } from '@ngx-translate/i18n-polyfill' 11import { I18n } from '@ngx-translate/i18n-polyfill'
11import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 12import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
12import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service' 13import { VideoCommentValidatorsService } from '@app/shared/forms/form-validators/video-comment-validators.service'
14import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
15import { 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
diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss
index 760be3822..0029c22ef 100644
--- a/client/src/sass/application.scss
+++ b/client/src/sass/application.scss
@@ -199,9 +199,18 @@ label {
199 199
200 .dropdown-item { 200 .dropdown-item {
201 padding: 3px 15px; 201 padding: 3px 15px;
202
203 &:active {
204 color: #000 !important;
205 }
206 }
207
208 button {
209 @include disable-default-a-behaviour;
202 } 210 }
203 211
204 a { 212 a {
213 @include disable-default-a-behaviour;
205 color: #000 !important; 214 color: #000 !important;
206 } 215 }
207} 216}
diff --git a/client/src/sass/include/_bootstrap.scss b/client/src/sass/include/_bootstrap.scss
index 4abc887ad..7bce85c37 100644
--- a/client/src/sass/include/_bootstrap.scss
+++ b/client/src/sass/include/_bootstrap.scss
@@ -46,7 +46,7 @@ $nav-pills-link-active-color: #000;
46@import '~bootstrap/scss/buttons'; 46@import '~bootstrap/scss/buttons';
47//@import '~bootstrap/scss/transitions'; 47//@import '~bootstrap/scss/transitions';
48@import '~bootstrap/scss/dropdown'; 48@import '~bootstrap/scss/dropdown';
49//@import '~bootstrap/scss/button-group'; 49@import '~bootstrap/scss/button-group';
50@import '~bootstrap/scss/input-group'; 50@import '~bootstrap/scss/input-group';
51//@import '~bootstrap/scss/custom-forms'; 51//@import '~bootstrap/scss/custom-forms';
52@import '~bootstrap/scss/nav'; 52@import '~bootstrap/scss/nav';