-<div i18n class="about-peertube-title">
+<h1 i18n class="about-peertube-title">
About PeerTube
-</div>
+</h1>
<div class="description">
<p i18n>PeerTube is a federated (ActivityPub) video streaming platform using P2P (WebTorrent) directly in the web browser.</p>
</div>
<div id="p2p-privacy">
- <div i18n class="section-title">P2P & Privacy</div>
+ <h3 i18n class="section-title">P2P & Privacy</h3>
<p i18n>
PeerTube uses the BitTorrent protocol to share bandwidth between users.
This implies that your IP address is stored in the instance's BitTorrent tracker as long as you download or watch the video.
</p>
- <h4 i18n class="p2p-privacy-title">What are the consequences?</h4>
+ <h6 i18n class="p2p-privacy-title">What are the consequences?</h6>
<p i18n>
In theory, someone with enough technical skills could create a script that tracks which IP is downloading which video.
There are much more effective ways to get that kind of information.
</p>
- <h4 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h4>
+ <h6 i18n class="p2p-privacy-title">How does PeerTube compare with YouTube?</h6>
<p i18n>
The threats to privacy in YouTube are different from PeerTube's.
Moreover, YouTube is owned by Google/Alphabet, a company that tracks you across many websites (via AdSense or Google Analytics).
</p>
- <h4 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h4>
+ <h6 i18n class="p2p-privacy-title">What can I do to limit the exposure of my IP address?</h6>
<p i18n>
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.
Thinking that removing P2P from PeerTube will give you back anonymity doesn't make sense.
</p>
- <h4 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h4>
+ <h6 i18n class="p2p-privacy-title">What will be done to mitigate this problem?</h6>
<p i18n>
PeerTube is only in beta, and want to deliver the best countermeasures possible by the time the stable is released.
@import '_mixins';
.about-peertube-title {
- font-size: 20px;
+ font-size: 25px;
font-weight: bold;
margin-bottom: 15px;
}
@Component({
selector: 'my-about',
- templateUrl: './about.component.html',
- styleUrls: [ './about.component.scss' ]
+ templateUrl: './about.component.html'
})
export class AboutComponent {
super()
}
+ get videoQuotaOptions () {
+ return EditCustomConfigComponent.videoQuotaOptions
+ }
+
+ get videoQuotaDailyOptions () {
+ return EditCustomConfigComponent.videoQuotaDailyOptions
+ }
+
getResolutionKey (resolution: string) {
return 'transcodingResolution' + resolution
}
--- /dev/null
+<div class="feature-table">
+
+ <table class="table">
+ <tr>
+ <td i18n class="label">Video quota</td>
+
+ <td class="value">
+ <ng-container *ngIf="initialUserVideoQuota !== -1">
+ {{ initialUserVideoQuota | bytes: 0 }}
+
+ <my-help helpType="custom" [customHtml]="quotaHelpIndication"></my-help>
+ </ng-container>
+
+ <ng-container i18n *ngIf="initialUserVideoQuota === -1">
+ Unlimited
+ </ng-container>
+ </td>
+ </tr>
+
+ <tr *ngFor="let feature of features">
+ <td class="label">{{ feature.label }}</td>
+ <td>
+ <span *ngIf="feature.value === true" class="glyphicon glyphicon-ok"></span>
+ <span *ngIf="feature.value === false" class="glyphicon glyphicon-remove"></span>
+ </td>
+ </tr>
+ </table>
+</div>
\ No newline at end of file
--- /dev/null
+@import '_variables';
+@import '_mixins';
+
+table {
+ font-size: 14px;
+ max-width: 400px;
+
+ .label {
+ font-weight: $font-semibold;
+ min-width: 330px;
+ }
+
+ .glyphicon-ok {
+ color: $green;
+ }
+
+ .glyphicon-remove {
+ color: $red;
+ }
+}
\ No newline at end of file
--- /dev/null
+import { Component, OnInit } from '@angular/core'
+import { ServerService } from '@app/core'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+
+@Component({
+ selector: 'my-instance-features-table',
+ templateUrl: './instance-features-table.component.html',
+ styleUrls: [ './instance-features-table.component.scss' ]
+})
+export class InstanceFeaturesTableComponent implements OnInit {
+ features: { label: string, value?: boolean }[] = []
+ quotaHelpIndication = ''
+
+ constructor (
+ private i18n: I18n,
+ private serverService: ServerService
+ ) {
+ }
+
+ get initialUserVideoQuota () {
+ return this.serverService.getConfig().user.videoQuota
+ }
+
+ ngOnInit () {
+ this.serverService.configLoaded
+ .subscribe(() => {
+ this.buildFeatures()
+ this.buildQuotaHelpIndication()
+ })
+ }
+
+ private buildFeatures () {
+ const config = this.serverService.getConfig()
+
+ this.features = [
+ {
+ label: this.i18n('Transcode your videos in multiple resolutions'),
+ value: config.transcoding.enabledResolutions.length !== 0
+ },
+ {
+ label: this.i18n('HTTP import (YouTube, Vimeo, direct URL...)'),
+ value: config.import.videos.http.enabled
+ },
+ {
+ label: this.i18n('Torrent import'),
+ value: config.import.videos.torrent.enabled
+ }
+ ]
+
+ }
+
+ private getApproximateTime (seconds: number) {
+ const hours = Math.floor(seconds / 3600)
+ let pluralSuffix = ''
+ if (hours > 1) pluralSuffix = 's'
+ if (hours > 0) return `~ ${hours} hour${pluralSuffix}`
+
+ const minutes = Math.floor(seconds % 3600 / 60)
+
+ return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes })
+ }
+
+ private buildQuotaHelpIndication () {
+ if (this.initialUserVideoQuota === -1) return
+
+ const initialUserVideoQuotaBit = this.initialUserVideoQuota * 8
+
+ // 1080p: ~ 6Mbps
+ // 720p: ~ 4Mbps
+ // 360p: ~ 1.5Mbps
+ const fullHdSeconds = initialUserVideoQuotaBit / (6 * 1000 * 1000)
+ const hdSeconds = initialUserVideoQuotaBit / (4 * 1000 * 1000)
+ const normalSeconds = initialUserVideoQuotaBit / (1.5 * 1000 * 1000)
+
+ const lines = [
+ this.i18n('{{seconds}} of full HD videos', { seconds: this.getApproximateTime(fullHdSeconds) }),
+ this.i18n('{{seconds}} of HD videos', { seconds: this.getApproximateTime(hdSeconds) }),
+ this.i18n('{{seconds}} of average quality videos', { seconds: this.getApproximateTime(normalSeconds) })
+ ]
+
+ this.quotaHelpIndication = lines.join('<br />')
+ }
+
+}
import { ActionDropdownComponent } from '@app/shared/buttons/action-dropdown.component'
import { NgbDropdownModule, NgbModalModule, NgbPopoverModule, NgbTabsetModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
import { SubscribeButtonComponent, UserSubscriptionService } from '@app/shared/user-subscription'
+import { InstanceFeaturesTableComponent } from '@app/shared/instance/instance-features-table.component'
@NgModule({
imports: [
HelpComponent,
ReactiveFileComponent,
PeertubeCheckboxComponent,
- SubscribeButtonComponent
+ SubscribeButtonComponent,
+ InstanceFeaturesTableComponent
],
exports: [
ReactiveFileComponent,
PeertubeCheckboxComponent,
SubscribeButtonComponent,
+ InstanceFeaturesTableComponent,
NumberFormatterPipe,
ObjectLengthPipe,
Create an account
</div>
- <div class="initial-user-quota">
- <span i18n class="initial-user-quota-label">Initial video quota:</span>
-
- <span *ngIf="initialUserVideoQuota !== -1">
- {{ initialUserVideoQuota | bytes: 0 }}
-
- <my-help helpType="custom" [customHtml]="quotaHelpIndication"></my-help>
- </span>
-
- <ng-container i18n *ngIf="initialUserVideoQuota === -1">
- Unlimited
- </ng-container>
- </div>
+ <my-instance-features-table></my-instance-features-table>
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
@import '_variables';
@import '_mixins';
-.initial-user-quota {
- font-size: 15px;
- margin-bottom: 20px;
+my-instance-features-table {
+ display: block;
- .initial-user-quota-label {
- font-weight: $font-semibold;
- }
+ margin-bottom: 40px;
}
.form-group-terms {
}
.input-group {
- @include peertube-input-group(340px);
+ @include peertube-input-group(400px);
}
input:not([type=submit]) {
- @include peertube-input-text(340px);
+ @include peertube-input-text(400px);
display: block;
&#username {
import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'
-import { ServerService } from '@app/core/server'
import { NotificationsService } from 'angular2-notifications'
import { UserCreate } from '../../../../shared'
import { FormReactive, UserService, UserValidatorsService } from '../shared'
})
export class SignupComponent extends FormReactive implements OnInit {
error: string = null
- quotaHelpIndication = ''
constructor (
protected formValidatorService: FormValidatorService,
private notificationsService: NotificationsService,
private userService: UserService,
private redirectService: RedirectService,
- private serverService: ServerService,
private i18n: I18n
) {
super()
}
- get initialUserVideoQuota () {
- return this.serverService.getConfig().user.videoQuota
- }
-
get instanceHost () {
return window.location.host
}
email: this.userValidatorsService.USER_EMAIL,
terms: this.userValidatorsService.USER_TERMS
})
-
- this.serverService.configLoaded
- .subscribe(() => this.buildQuotaHelpIndication())
}
signup () {
err => this.error = err.message
)
}
-
- private getApproximateTime (seconds: number) {
- const hours = Math.floor(seconds / 3600)
- let pluralSuffix = ''
- if (hours > 1) pluralSuffix = 's'
- if (hours > 0) return `~ ${hours} hour${pluralSuffix}`
-
- const minutes = Math.floor(seconds % 3600 / 60)
- if (minutes > 1) pluralSuffix = 's'
-
- return this.i18n('~ {{minutes}} {minutes, plural, =1 {minute} other {minutes}}', { minutes })
- }
-
- private buildQuotaHelpIndication () {
- if (this.initialUserVideoQuota === -1) return
-
- const initialUserVideoQuotaBit = this.initialUserVideoQuota * 8
-
- // 1080p: ~ 6Mbps
- // 720p: ~ 4Mbps
- // 360p: ~ 1.5Mbps
- const fullHdSeconds = initialUserVideoQuotaBit / (6 * 1000 * 1000)
- const hdSeconds = initialUserVideoQuotaBit / (4 * 1000 * 1000)
- const normalSeconds = initialUserVideoQuotaBit / (1.5 * 1000 * 1000)
-
- const lines = [
- this.i18n('{{seconds}} of full HD videos', { seconds: this.getApproximateTime(fullHdSeconds) }),
- this.i18n('{{seconds}} of HD videos', { seconds: this.getApproximateTime(hdSeconds) }),
- this.i18n('{{seconds}} of average quality videos', { seconds: this.getApproximateTime(normalSeconds) })
- ]
-
- this.quotaHelpIndication = lines.join('<br />')
- }
}
}
&.action-button-like.activated {
- background-color: #39CC0B;
+ background-color: $green;
.icon-like {
background-image: url('../../../assets/images/video/like-white.svg');
}
&.action-button-dislike.activated {
- background-color: #FF0000;
+ background-color: $red;
.icon-dislike {
background-image: url('../../../assets/images/video/dislike-white.svg');
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+ <g id="Artboard-4" transform="translate(-356.000000, -115.000000)" stroke="#585858" stroke-width="2">
+ <g id="8" transform="translate(356.000000, 115.000000)">
+ <path d="M21,6 L9,18" id="Path-14"></path>
+ <path d="M9,13 L4,18" id="Path-14" transform="translate(6.500000, 15.500000) scale(-1, 1) translate(-6.500000, -15.500000) "></path>
+ </g>
+ </g>
+ </g>
+</svg>
.form-error {
display: block;
- color: $red-error;
+ color: $red;
margin-top: 5px;
}
.input-error {
- border-color: $red-error !important;
+ border-color: $red !important;
}
.glyphicon-black {
//@import '~bootstrap/scss/images';
//@import '~bootstrap/scss/code';
@import '~bootstrap/scss/grid';
-//@import '~bootstrap/scss/tables';
+@import '~bootstrap/scss/tables';
@import '~bootstrap/scss/forms';
@import '~bootstrap/scss/buttons';
//@import '~bootstrap/scss/transitions';
$black-background: #000;
$grey-background: #f6f2f2;
-$red-error: #FF0000;
+
+$red: #FF0000;
+$green: #39CC0B;
$grey-actor-name: #777272;
const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip)
const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS)
- .filter(key => CONFIG.TRANSCODING.RESOLUTIONS[key] === true)
+ .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true)
.map(r => parseInt(r, 10))
const json: ServerConfig = {