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/shared | |
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/shared')
8 files changed, 194 insertions, 57 deletions
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 | |||
53 | import { VideoImportService } from '@app/shared/video-import/video-import.service' | 53 | import { VideoImportService } from '@app/shared/video-import/video-import.service' |
54 | import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' | 54 | import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' |
55 | import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' | 55 | import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' |
56 | import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription' | 56 | import { SubscribeButtonComponent, RemoteSubscribeComponent, UserSubscriptionService } from '@app/shared/user-subscription' |
57 | import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component' | 57 | import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component' |
58 | import { OverviewService } from '@app/shared/overview' | 58 | import { 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 @@ | |||
1 | export * from './user-subscription.service' | 1 | export * from './user-subscription.service' |
2 | export * from './subscribe-button.component' | 2 | export * from './subscribe-button.component' |
3 | export * 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 @@ | |||
1 | import { Component, Input, OnInit } from '@angular/core' | ||
2 | import { FormReactive } from '@app/shared/forms/form-reactive' | ||
3 | import { | ||
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 | }) | ||
13 | export 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 @@ | |||
1 | import { Component, Input, OnInit } from '@angular/core' | 1 | import { Component, Input, OnInit } from '@angular/core' |
2 | import { Router } from '@angular/router' | ||
3 | import { AuthService } from '@app/core' | ||
2 | import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' | 4 | import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' |
3 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' | 5 | import { VideoChannel } from '@app/shared/video-channel/video-channel.model' |
4 | import { NotificationsService } from 'angular2-notifications' | 6 | import { 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 | } |