diff options
author | Chocobozzz <me@florianbigard.com> | 2018-08-28 17:39:29 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-08-28 17:39:29 +0200 |
commit | 41a676db3989fe3eca91301ac5f5aea30d98654a (patch) | |
tree | 00a28c9110cdd351435ec0c066599763748119e7 | |
parent | f0d4e7eb240f256b4f01cde4a1cd6f66f8f4347c (diff) | |
download | PeerTube-41a676db3989fe3eca91301ac5f5aea30d98654a.tar.gz PeerTube-41a676db3989fe3eca91301ac5f5aea30d98654a.tar.zst PeerTube-41a676db3989fe3eca91301ac5f5aea30d98654a.zip |
Add features table on signup
18 files changed, 180 insertions, 82 deletions
diff --git a/client/src/app/+about/about-peertube/about-peertube.component.html b/client/src/app/+about/about-peertube/about-peertube.component.html index 55ac344f9..13ce89f75 100644 --- a/client/src/app/+about/about-peertube/about-peertube.component.html +++ b/client/src/app/+about/about-peertube/about-peertube.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <div i18n class="about-peertube-title"> | 1 | <h1 i18n class="about-peertube-title"> |
2 | About PeerTube | 2 | About PeerTube |
3 | </div> | 3 | </h1> |
4 | 4 | ||
5 | <div class="description"> | 5 | <div class="description"> |
6 | <p i18n>PeerTube is a federated (ActivityPub) video streaming platform using P2P (WebTorrent) directly in the web browser.</p> | 6 | <p i18n>PeerTube is a federated (ActivityPub) video streaming platform using P2P (WebTorrent) directly in the web browser.</p> |
@@ -15,14 +15,14 @@ | |||
15 | </div> | 15 | </div> |
16 | 16 | ||
17 | <div id="p2p-privacy"> | 17 | <div id="p2p-privacy"> |
18 | <div i18n class="section-title">P2P & Privacy</div> | 18 | <h3 i18n class="section-title">P2P & Privacy</h3> |
19 | 19 | ||
20 | <p i18n> | 20 | <p i18n> |
21 | PeerTube uses the BitTorrent protocol to share bandwidth between users. | 21 | PeerTube uses the BitTorrent protocol to share bandwidth between users. |
22 | This implies that your IP address is stored in the instance's BitTorrent tracker as long as you download or watch the video. | 22 | This implies that your IP address is stored in the instance's BitTorrent tracker as long as you download or watch the video. |
23 | </p> | 23 | </p> |
24 | 24 | ||
25 | <h4 i18n class="p2p-privacy-title">What are the consequences?</h4> | 25 | <h6 i18n class="p2p-privacy-title">What are the consequences?</h6> |
26 | 26 | ||
27 | <p i18n> | 27 | <p i18n> |
28 | In theory, someone with enough technical skills could create a script that tracks which IP is downloading which video. | 28 | In theory, someone with enough technical skills could create a script that tracks which IP is downloading which video. |
@@ -64,7 +64,7 @@ | |||
64 | There are much more effective ways to get that kind of information. | 64 | There are much more effective ways to get that kind of information. |
65 | </p> | 65 | </p> |
66 | 66 | ||
67 | <h4 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h4> | 67 | <h6 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h6> |
68 | 68 | ||
69 | <p i18n> | 69 | <p i18n> |
70 | The threats to privacy in YouTube are different from PeerTube's. | 70 | The threats to privacy in YouTube are different from PeerTube's. |
@@ -72,7 +72,7 @@ | |||
72 | Moreover, YouTube is owned by Google/Alphabet, a company that tracks you across many websites (via AdSense or Google Analytics). | 72 | Moreover, YouTube is owned by Google/Alphabet, a company that tracks you across many websites (via AdSense or Google Analytics). |
73 | </p> | 73 | </p> |
74 | 74 | ||
75 | <h4 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h4> | 75 | <h6 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h6> |
76 | 76 | ||
77 | <p i18n> | 77 | <p i18n> |
78 | Your IP address is public so every time you consult a website, there is a number of actors (in addition to the final website) seeing your IP in their connection logs: ISP/routers/trackers/CDN and more. | 78 | Your IP address is public so every time you consult a website, there is a number of actors (in addition to the final website) seeing your IP in their connection logs: ISP/routers/trackers/CDN and more. |
@@ -80,7 +80,7 @@ | |||
80 | Thinking that removing P2P from PeerTube will give you back anonymity doesn't make sense. | 80 | Thinking that removing P2P from PeerTube will give you back anonymity doesn't make sense. |
81 | </p> | 81 | </p> |
82 | 82 | ||
83 | <h4 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h4> | 83 | <h6 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h6> |
84 | 84 | ||
85 | <p i18n> | 85 | <p i18n> |
86 | PeerTube is only in beta, and want to deliver the best countermeasures possible by the time the stable is released. | 86 | PeerTube is only in beta, and want to deliver the best countermeasures possible by the time the stable is released. |
diff --git a/client/src/app/+about/about-peertube/about-peertube.component.scss b/client/src/app/+about/about-peertube/about-peertube.component.scss index 1d8579ec1..0d2e2bb68 100644 --- a/client/src/app/+about/about-peertube/about-peertube.component.scss +++ b/client/src/app/+about/about-peertube/about-peertube.component.scss | |||
@@ -2,7 +2,7 @@ | |||
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | .about-peertube-title { | 4 | .about-peertube-title { |
5 | font-size: 20px; | 5 | font-size: 25px; |
6 | font-weight: bold; | 6 | font-weight: bold; |
7 | margin-bottom: 15px; | 7 | margin-bottom: 15px; |
8 | } | 8 | } |
diff --git a/client/src/app/+about/about.component.scss b/client/src/app/+about/about.component.scss deleted file mode 100644 index e69de29bb..000000000 --- a/client/src/app/+about/about.component.scss +++ /dev/null | |||
diff --git a/client/src/app/+about/about.component.ts b/client/src/app/+about/about.component.ts index 7b65d920f..0c91cd75f 100644 --- a/client/src/app/+about/about.component.ts +++ b/client/src/app/+about/about.component.ts | |||
@@ -2,8 +2,7 @@ import { Component } from '@angular/core' | |||
2 | 2 | ||
3 | @Component({ | 3 | @Component({ |
4 | selector: 'my-about', | 4 | selector: 'my-about', |
5 | templateUrl: './about.component.html', | 5 | templateUrl: './about.component.html' |
6 | styleUrls: [ './about.component.scss' ] | ||
7 | }) | 6 | }) |
8 | 7 | ||
9 | export class AboutComponent { | 8 | export class AboutComponent { |
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts index 3b6dabcb9..248b0df50 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts | |||
@@ -64,6 +64,14 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { | |||
64 | super() | 64 | super() |
65 | } | 65 | } |
66 | 66 | ||
67 | get videoQuotaOptions () { | ||
68 | return EditCustomConfigComponent.videoQuotaOptions | ||
69 | } | ||
70 | |||
71 | get videoQuotaDailyOptions () { | ||
72 | return EditCustomConfigComponent.videoQuotaDailyOptions | ||
73 | } | ||
74 | |||
67 | getResolutionKey (resolution: string) { | 75 | getResolutionKey (resolution: string) { |
68 | return 'transcodingResolution' + resolution | 76 | return 'transcodingResolution' + resolution |
69 | } | 77 | } |
diff --git a/client/src/app/shared/instance/instance-features-table.component.html b/client/src/app/shared/instance/instance-features-table.component.html new file mode 100644 index 000000000..ba170f074 --- /dev/null +++ b/client/src/app/shared/instance/instance-features-table.component.html | |||
@@ -0,0 +1,28 @@ | |||
1 | <div class="feature-table"> | ||
2 | |||
3 | <table class="table"> | ||
4 | <tr> | ||
5 | <td i18n class="label">Video quota</td> | ||
6 | |||
7 | <td class="value"> | ||
8 | <ng-container *ngIf="initialUserVideoQuota !== -1"> | ||
9 | {{ initialUserVideoQuota | bytes: 0 }} | ||
10 | |||
11 | <my-help helpType="custom" [customHtml]="quotaHelpIndication"></my-help> | ||
12 | </ng-container> | ||
13 | |||
14 | <ng-container i18n *ngIf="initialUserVideoQuota === -1"> | ||
15 | Unlimited | ||
16 | </ng-container> | ||
17 | </td> | ||
18 | </tr> | ||
19 | |||
20 | <tr *ngFor="let feature of features"> | ||
21 | <td class="label">{{ feature.label }}</td> | ||
22 | <td> | ||
23 | <span *ngIf="feature.value === true" class="glyphicon glyphicon-ok"></span> | ||
24 | <span *ngIf="feature.value === false" class="glyphicon glyphicon-remove"></span> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </div> \ No newline at end of file | ||
diff --git a/client/src/app/shared/instance/instance-features-table.component.scss b/client/src/app/shared/instance/instance-features-table.component.scss new file mode 100644 index 000000000..d597a03ba --- /dev/null +++ b/client/src/app/shared/instance/instance-features-table.component.scss | |||
@@ -0,0 +1,20 @@ | |||
1 | @import '_variables'; | ||
2 | @import '_mixins'; | ||
3 | |||
4 | table { | ||
5 | font-size: 14px; | ||
6 | max-width: 400px; | ||
7 | |||
8 | .label { | ||
9 | font-weight: $font-semibold; | ||
10 | min-width: 330px; | ||
11 | } | ||
12 | |||
13 | .glyphicon-ok { | ||
14 | color: $green; | ||
15 | } | ||
16 | |||
17 | .glyphicon-remove { | ||
18 | color: $red; | ||
19 | } | ||
20 | } \ No newline at end of file | ||
diff --git a/client/src/app/shared/instance/instance-features-table.component.ts b/client/src/app/shared/instance/instance-features-table.component.ts new file mode 100644 index 000000000..1aad5aa81 --- /dev/null +++ b/client/src/app/shared/instance/instance-features-table.component.ts | |||
@@ -0,0 +1,84 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | ||
2 | import { ServerService } from '@app/core' | ||
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
4 | |||
5 | @Component({ | ||
6 | selector: 'my-instance-features-table', | ||
7 | templateUrl: './instance-features-table.component.html', | ||
8 | styleUrls: [ './instance-features-table.component.scss' ] | ||
9 | }) | ||
10 | export class InstanceFeaturesTableComponent implements OnInit { | ||
11 | features: { label: string, value?: boolean }[] = [] | ||
12 | quotaHelpIndication = '' | ||
13 | |||
14 | constructor ( | ||
15 | private i18n: I18n, | ||
16 | private serverService: ServerService | ||
17 | ) { | ||
18 | } | ||
19 | |||
20 | get initialUserVideoQuota () { | ||
21 | return this.serverService.getConfig().user.videoQuota | ||
22 | } | ||
23 | |||
24 | ngOnInit () { | ||
25 | this.serverService.configLoaded | ||
26 | .subscribe(() => { | ||
27 | this.buildFeatures() | ||
28 | this.buildQuotaHelpIndication() | ||
29 | }) | ||
30 | } | ||
31 | |||
32 | private buildFeatures () { | ||
33 | const config = this.serverService.getConfig() | ||
34 | |||
35 | this.features = [ | ||
36 | { | ||
37 | label: this.i18n('Transcode your videos in multiple resolutions'), | ||
38 | value: config.transcoding.enabledResolutions.length !== 0 | ||
39 | }, | ||
40 | { | ||
41 | label: this.i18n('HTTP import (YouTube, Vimeo, direct URL...)'), | ||
42 | value: config.import.videos.http.enabled | ||
43 | }, | ||
44 | { | ||
45 | label: this.i18n('Torrent import'), | ||
46 | value: config.import.videos.torrent.enabled | ||
47 | } | ||
48 | ] | ||
49 | |||
50 | } | ||
51 | |||
52 | private getApproximateTime (seconds: number) { | ||
53 | const hours = Math.floor(seconds / 3600) | ||
54 | let pluralSuffix = '' | ||
55 | if (hours > 1) pluralSuffix = 's' | ||
56 | if (hours > 0) return `~ ${hours} hour${pluralSuffix}` | ||
57 | |||
58 | const minutes = Math.floor(seconds % 3600 / 60) | ||
59 | |||
60 | return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes }) | ||
61 | } | ||
62 | |||
63 | private buildQuotaHelpIndication () { | ||
64 | if (this.initialUserVideoQuota === -1) return | ||
65 | |||
66 | const initialUserVideoQuotaBit = this.initialUserVideoQuota * 8 | ||
67 | |||
68 | // 1080p: ~ 6Mbps | ||
69 | // 720p: ~ 4Mbps | ||
70 | // 360p: ~ 1.5Mbps | ||
71 | const fullHdSeconds = initialUserVideoQuotaBit / (6 * 1000 * 1000) | ||
72 | const hdSeconds = initialUserVideoQuotaBit / (4 * 1000 * 1000) | ||
73 | const normalSeconds = initialUserVideoQuotaBit / (1.5 * 1000 * 1000) | ||
74 | |||
75 | const lines = [ | ||
76 | this.i18n('{{seconds}} of full HD videos', { seconds: this.getApproximateTime(fullHdSeconds) }), | ||
77 | this.i18n('{{seconds}} of HD videos', { seconds: this.getApproximateTime(hdSeconds) }), | ||
78 | this.i18n('{{seconds}} of average quality videos', { seconds: this.getApproximateTime(normalSeconds) }) | ||
79 | ] | ||
80 | |||
81 | this.quotaHelpIndication = lines.join('<br />') | ||
82 | } | ||
83 | |||
84 | } | ||
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 413159059..2cbaaf4ae 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts | |||
@@ -51,6 +51,7 @@ import { VideoImportService } from '@app/shared/video-import/video-import.servic | |||
51 | import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' | 51 | import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component' |
52 | import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' | 52 | import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap' |
53 | import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription' | 53 | import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription' |
54 | import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component' | ||
54 | 55 | ||
55 | @NgModule({ | 56 | @NgModule({ |
56 | imports: [ | 57 | imports: [ |
@@ -86,7 +87,8 @@ import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/u | |||
86 | HelpComponent, | 87 | HelpComponent, |
87 | ReactiveFileComponent, | 88 | ReactiveFileComponent, |
88 | PeertubeCheckboxComponent, | 89 | PeertubeCheckboxComponent, |
89 | SubscribeButtonComponent | 90 | SubscribeButtonComponent, |
91 | InstanceFeaturesTableComponent | ||
90 | ], | 92 | ], |
91 | 93 | ||
92 | exports: [ | 94 | exports: [ |
@@ -119,6 +121,7 @@ import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/u | |||
119 | ReactiveFileComponent, | 121 | ReactiveFileComponent, |
120 | PeertubeCheckboxComponent, | 122 | PeertubeCheckboxComponent, |
121 | SubscribeButtonComponent, | 123 | SubscribeButtonComponent, |
124 | InstanceFeaturesTableComponent, | ||
122 | 125 | ||
123 | NumberFormatterPipe, | 126 | NumberFormatterPipe, |
124 | ObjectLengthPipe, | 127 | ObjectLengthPipe, |
diff --git a/client/src/app/signup/signup.component.html b/client/src/app/signup/signup.component.html index 5fd630b09..f7b8f587b 100644 --- a/client/src/app/signup/signup.component.html +++ b/client/src/app/signup/signup.component.html | |||
@@ -4,19 +4,7 @@ | |||
4 | Create an account | 4 | Create an account |
5 | </div> | 5 | </div> |
6 | 6 | ||
7 | <div class="initial-user-quota"> | 7 | <my-instance-features-table></my-instance-features-table> |
8 | <span i18n class="initial-user-quota-label">Initial video quota:</span> | ||
9 | |||
10 | <span *ngIf="initialUserVideoQuota !== -1"> | ||
11 | {{ initialUserVideoQuota | bytes: 0 }} | ||
12 | |||
13 | <my-help helpType="custom" [customHtml]="quotaHelpIndication"></my-help> | ||
14 | </span> | ||
15 | |||
16 | <ng-container i18n *ngIf="initialUserVideoQuota === -1"> | ||
17 | Unlimited | ||
18 | </ng-container> | ||
19 | </div> | ||
20 | 8 | ||
21 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | 9 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> |
22 | 10 | ||
diff --git a/client/src/app/signup/signup.component.scss b/client/src/app/signup/signup.component.scss index 1c992faf5..a98c3c732 100644 --- a/client/src/app/signup/signup.component.scss +++ b/client/src/app/signup/signup.component.scss | |||
@@ -1,13 +1,10 @@ | |||
1 | @import '_variables'; | 1 | @import '_variables'; |
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | .initial-user-quota { | 4 | my-instance-features-table { |
5 | font-size: 15px; | 5 | display: block; |
6 | margin-bottom: 20px; | ||
7 | 6 | ||
8 | .initial-user-quota-label { | 7 | margin-bottom: 40px; |
9 | font-weight: $font-semibold; | ||
10 | } | ||
11 | } | 8 | } |
12 | 9 | ||
13 | .form-group-terms { | 10 | .form-group-terms { |
@@ -15,11 +12,11 @@ | |||
15 | } | 12 | } |
16 | 13 | ||
17 | .input-group { | 14 | .input-group { |
18 | @include peertube-input-group(340px); | 15 | @include peertube-input-group(400px); |
19 | } | 16 | } |
20 | 17 | ||
21 | input:not([type=submit]) { | 18 | input:not([type=submit]) { |
22 | @include peertube-input-text(340px); | 19 | @include peertube-input-text(400px); |
23 | display: block; | 20 | display: block; |
24 | 21 | ||
25 | &#username { | 22 | &#username { |
diff --git a/client/src/app/signup/signup.component.ts b/client/src/app/signup/signup.component.ts index ed68487ae..47f9bc6f4 100644 --- a/client/src/app/signup/signup.component.ts +++ b/client/src/app/signup/signup.component.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnInit } from '@angular/core' |
2 | import { Router } from '@angular/router' | 2 | import { Router } from '@angular/router' |
3 | import { ServerService } from '@app/core/server' | ||
4 | import { NotificationsService } from 'angular2-notifications' | 3 | import { NotificationsService } from 'angular2-notifications' |
5 | import { UserCreate } from '../../../../shared' | 4 | import { UserCreate } from '../../../../shared' |
6 | import { FormReactive, UserService, UserValidatorsService } from '../shared' | 5 | import { FormReactive, UserService, UserValidatorsService } from '../shared' |
@@ -15,7 +14,6 @@ import { FormValidatorService } from '@app/shared/forms/form-validators/form-val | |||
15 | }) | 14 | }) |
16 | export class SignupComponent extends FormReactive implements OnInit { | 15 | export class SignupComponent extends FormReactive implements OnInit { |
17 | error: string = null | 16 | error: string = null |
18 | quotaHelpIndication = '' | ||
19 | 17 | ||
20 | constructor ( | 18 | constructor ( |
21 | protected formValidatorService: FormValidatorService, | 19 | protected formValidatorService: FormValidatorService, |
@@ -24,16 +22,11 @@ export class SignupComponent extends FormReactive implements OnInit { | |||
24 | private notificationsService: NotificationsService, | 22 | private notificationsService: NotificationsService, |
25 | private userService: UserService, | 23 | private userService: UserService, |
26 | private redirectService: RedirectService, | 24 | private redirectService: RedirectService, |
27 | private serverService: ServerService, | ||
28 | private i18n: I18n | 25 | private i18n: I18n |
29 | ) { | 26 | ) { |
30 | super() | 27 | super() |
31 | } | 28 | } |
32 | 29 | ||
33 | get initialUserVideoQuota () { | ||
34 | return this.serverService.getConfig().user.videoQuota | ||
35 | } | ||
36 | |||
37 | get instanceHost () { | 30 | get instanceHost () { |
38 | return window.location.host | 31 | return window.location.host |
39 | } | 32 | } |
@@ -45,9 +38,6 @@ export class SignupComponent extends FormReactive implements OnInit { | |||
45 | email: this.userValidatorsService.USER_EMAIL, | 38 | email: this.userValidatorsService.USER_EMAIL, |
46 | terms: this.userValidatorsService.USER_TERMS | 39 | terms: this.userValidatorsService.USER_TERMS |
47 | }) | 40 | }) |
48 | |||
49 | this.serverService.configLoaded | ||
50 | .subscribe(() => this.buildQuotaHelpIndication()) | ||
51 | } | 41 | } |
52 | 42 | ||
53 | signup () { | 43 | signup () { |
@@ -67,37 +57,4 @@ export class SignupComponent extends FormReactive implements OnInit { | |||
67 | err => this.error = err.message | 57 | err => this.error = err.message |
68 | ) | 58 | ) |
69 | } | 59 | } |
70 | |||
71 | private getApproximateTime (seconds: number) { | ||
72 | const hours = Math.floor(seconds / 3600) | ||
73 | let pluralSuffix = '' | ||
74 | if (hours > 1) pluralSuffix = 's' | ||
75 | if (hours > 0) return `~ ${hours} hour${pluralSuffix}` | ||
76 | |||
77 | const minutes = Math.floor(seconds % 3600 / 60) | ||
78 | if (minutes > 1) pluralSuffix = 's' | ||
79 | |||
80 | return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes }) | ||
81 | } | ||
82 | |||
83 | private buildQuotaHelpIndication () { | ||
84 | if (this.initialUserVideoQuota === -1) return | ||
85 | |||
86 | const initialUserVideoQuotaBit = this.initialUserVideoQuota * 8 | ||
87 | |||
88 | // 1080p: ~ 6Mbps | ||
89 | // 720p: ~ 4Mbps | ||
90 | // 360p: ~ 1.5Mbps | ||
91 | const fullHdSeconds = initialUserVideoQuotaBit / (6 * 1000 * 1000) | ||
92 | const hdSeconds = initialUserVideoQuotaBit / (4 * 1000 * 1000) | ||
93 | const normalSeconds = initialUserVideoQuotaBit / (1.5 * 1000 * 1000) | ||
94 | |||
95 | const lines = [ | ||
96 | this.i18n('{{seconds}} of full HD videos', { seconds: this.getApproximateTime(fullHdSeconds) }), | ||
97 | this.i18n('{{seconds}} of HD videos', { seconds: this.getApproximateTime(hdSeconds) }), | ||
98 | this.i18n('{{seconds}} of average quality videos', { seconds: this.getApproximateTime(normalSeconds) }) | ||
99 | ] | ||
100 | |||
101 | this.quotaHelpIndication = lines.join('<br />') | ||
102 | } | ||
103 | } | 60 | } |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index 6b18dc88a..9bd510c9f 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss | |||
@@ -226,7 +226,7 @@ | |||
226 | } | 226 | } |
227 | 227 | ||
228 | &.action-button-like.activated { | 228 | &.action-button-like.activated { |
229 | background-color: #39CC0B; | 229 | background-color: $green; |
230 | 230 | ||
231 | .icon-like { | 231 | .icon-like { |
232 | background-image: url('../../../assets/images/video/like-white.svg'); | 232 | background-image: url('../../../assets/images/video/like-white.svg'); |
@@ -234,7 +234,7 @@ | |||
234 | } | 234 | } |
235 | 235 | ||
236 | &.action-button-dislike.activated { | 236 | &.action-button-dislike.activated { |
237 | background-color: #FF0000; | 237 | background-color: $red; |
238 | 238 | ||
239 | .icon-dislike { | 239 | .icon-dislike { |
240 | background-image: url('../../../assets/images/video/dislike-white.svg'); | 240 | background-image: url('../../../assets/images/video/dislike-white.svg'); |
diff --git a/client/src/assets/images/global/tick.svg b/client/src/assets/images/global/tick.svg new file mode 100644 index 000000000..230caa111 --- /dev/null +++ b/client/src/assets/images/global/tick.svg | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> | ||
3 | <defs></defs> | ||
4 | <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round"> | ||
5 | <g id="Artboard-4" transform="translate(-356.000000, -115.000000)" stroke="#585858" stroke-width="2"> | ||
6 | <g id="8" transform="translate(356.000000, 115.000000)"> | ||
7 | <path d="M21,6 L9,18" id="Path-14"></path> | ||
8 | <path d="M9,13 L4,18" id="Path-14" transform="translate(6.500000, 15.500000) scale(-1, 1) translate(-6.500000, -15.500000) "></path> | ||
9 | </g> | ||
10 | </g> | ||
11 | </g> | ||
12 | </svg> | ||
diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss index b2d7c2bec..9c4811fec 100644 --- a/client/src/sass/application.scss +++ b/client/src/sass/application.scss | |||
@@ -53,12 +53,12 @@ label { | |||
53 | 53 | ||
54 | .form-error { | 54 | .form-error { |
55 | display: block; | 55 | display: block; |
56 | color: $red-error; | 56 | color: $red; |
57 | margin-top: 5px; | 57 | margin-top: 5px; |
58 | } | 58 | } |
59 | 59 | ||
60 | .input-error { | 60 | .input-error { |
61 | border-color: $red-error !important; | 61 | border-color: $red !important; |
62 | } | 62 | } |
63 | 63 | ||
64 | .glyphicon-black { | 64 | .glyphicon-black { |
diff --git a/client/src/sass/include/_bootstrap.scss b/client/src/sass/include/_bootstrap.scss index 5abec02d5..a8777af71 100644 --- a/client/src/sass/include/_bootstrap.scss +++ b/client/src/sass/include/_bootstrap.scss | |||
@@ -21,7 +21,7 @@ $nav-pills-link-active-color: #000; | |||
21 | //@import '~bootstrap/scss/images'; | 21 | //@import '~bootstrap/scss/images'; |
22 | //@import '~bootstrap/scss/code'; | 22 | //@import '~bootstrap/scss/code'; |
23 | @import '~bootstrap/scss/grid'; | 23 | @import '~bootstrap/scss/grid'; |
24 | //@import '~bootstrap/scss/tables'; | 24 | @import '~bootstrap/scss/tables'; |
25 | @import '~bootstrap/scss/forms'; | 25 | @import '~bootstrap/scss/forms'; |
26 | @import '~bootstrap/scss/buttons'; | 26 | @import '~bootstrap/scss/buttons'; |
27 | //@import '~bootstrap/scss/transitions'; | 27 | //@import '~bootstrap/scss/transitions'; |
diff --git a/client/src/sass/include/_variables.scss b/client/src/sass/include/_variables.scss index e6db98642..ba7abeef1 100644 --- a/client/src/sass/include/_variables.scss +++ b/client/src/sass/include/_variables.scss | |||
@@ -10,7 +10,9 @@ $orange-hoover-color: #F97D46; | |||
10 | 10 | ||
11 | $black-background: #000; | 11 | $black-background: #000; |
12 | $grey-background: #f6f2f2; | 12 | $grey-background: #f6f2f2; |
13 | $red-error: #FF0000; | 13 | |
14 | $red: #FF0000; | ||
15 | $green: #39CC0B; | ||
14 | 16 | ||
15 | $grey-actor-name: #777272; | 17 | $grey-actor-name: #777272; |
16 | 18 | ||
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 8dfc3deb4..25ddd1fa6 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -43,7 +43,7 @@ async function getConfig (req: express.Request, res: express.Response, next: exp | |||
43 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) | 43 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) |
44 | 44 | ||
45 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) | 45 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) |
46 | .filter(key => CONFIG.TRANSCODING.RESOLUTIONS[key] === true) | 46 | .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true) |
47 | .map(r => parseInt(r, 10)) | 47 | .map(r => parseInt(r, 10)) |
48 | 48 | ||
49 | const json: ServerConfig = { | 49 | const json: ServerConfig = { |