mirror of https://github.com/Chocobozzz/PeerTube
Add messages about privacy concerns (P2P)
parent
d7137ad5fb
commit
22b59e8099
|
@ -18,7 +18,7 @@
|
||||||
<ng-template pTemplate="body" let-videoAbuse>
|
<ng-template pTemplate="body" let-videoAbuse>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ videoAbuse.reason }}</td>
|
<td>{{ videoAbuse.reason }}</td>
|
||||||
<td>{{ videoAbuse.reporterServerHost + '@' + videoAbuse.reporterUsername }}</td>
|
<td>{{ videoAbuse.reporterUsername + '@' + videoAbuse.reporterServerHost }}</td>
|
||||||
<td>{{ videoAbuse.createdAt }}</td>
|
<td>{{ videoAbuse.createdAt }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a [routerLink]="getRouterVideoLink(videoAbuse.videoUUID)" title="Go to the video">{{ videoAbuse.videoName }}</a>
|
<a [routerLink]="getRouterVideoLink(videoAbuse.videoUUID)" title="Go to the video">{{ videoAbuse.videoName }}</a>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="submit" value="Confirm" class="action-button-submit" [disabled]="isConfirmationDisabled()"
|
type="submit" [value]="confirmButtonText" class="action-button-submit" [disabled]="isConfirmationDisabled()"
|
||||||
(click)="confirm()"
|
(click)="confirm()"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,7 @@ export class ConfirmComponent implements OnInit {
|
||||||
inputLabel = ''
|
inputLabel = ''
|
||||||
|
|
||||||
inputValue = ''
|
inputValue = ''
|
||||||
|
confirmButtonText = ''
|
||||||
|
|
||||||
constructor (private confirmService: ConfirmService) {
|
constructor (private confirmService: ConfirmService) {
|
||||||
// Empty
|
// Empty
|
||||||
|
@ -30,13 +31,15 @@ export class ConfirmComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.confirmService.showConfirm.subscribe(
|
this.confirmService.showConfirm.subscribe(
|
||||||
({ title, message, expectedInputValue, inputLabel }) => {
|
({ title, message, expectedInputValue, inputLabel, confirmButtonText }) => {
|
||||||
this.title = title
|
this.title = title
|
||||||
this.message = message
|
this.message = message
|
||||||
|
|
||||||
this.inputLabel = inputLabel
|
this.inputLabel = inputLabel
|
||||||
this.expectedInputValue = expectedInputValue
|
this.expectedInputValue = expectedInputValue
|
||||||
|
|
||||||
|
this.confirmButtonText = confirmButtonText || 'Confirm'
|
||||||
|
|
||||||
this.showModal()
|
this.showModal()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,19 +3,27 @@ import { Subject } from 'rxjs/Subject'
|
||||||
import 'rxjs/add/operator/first'
|
import 'rxjs/add/operator/first'
|
||||||
import 'rxjs/add/operator/toPromise'
|
import 'rxjs/add/operator/toPromise'
|
||||||
|
|
||||||
|
type ConfirmOptions = {
|
||||||
|
title: string
|
||||||
|
message: string
|
||||||
|
inputLabel?: string
|
||||||
|
expectedInputValue?: string
|
||||||
|
confirmButtonText?: string
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConfirmService {
|
export class ConfirmService {
|
||||||
showConfirm = new Subject<{ title: string, message: string, inputLabel?: string, expectedInputValue?: string }>()
|
showConfirm = new Subject<ConfirmOptions>()
|
||||||
confirmResponse = new Subject<boolean>()
|
confirmResponse = new Subject<boolean>()
|
||||||
|
|
||||||
confirm (message: string, title = '') {
|
confirm (message: string, title = '', confirmButtonText?: string) {
|
||||||
this.showConfirm.next({ title, message })
|
this.showConfirm.next({ title, message, confirmButtonText })
|
||||||
|
|
||||||
return this.confirmResponse.asObservable().first().toPromise()
|
return this.confirmResponse.asObservable().first().toPromise()
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmWithInput (message: string, inputLabel: string, expectedInputValue: string, title = '') {
|
confirmWithInput (message: string, inputLabel: string, expectedInputValue: string, title = '', confirmButtonText?: string) {
|
||||||
this.showConfirm.next({ title, message, inputLabel, expectedInputValue })
|
this.showConfirm.next({ title, message, inputLabel, expectedInputValue, confirmButtonText })
|
||||||
|
|
||||||
return this.confirmResponse.asObservable().first().toPromise()
|
return this.confirmResponse.asObservable().first().toPromise()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { VideoShareComponent } from './modal/video-share.component'
|
||||||
styleUrls: [ './video-watch.component.scss' ]
|
styleUrls: [ './video-watch.component.scss' ]
|
||||||
})
|
})
|
||||||
export class VideoWatchComponent implements OnInit, OnDestroy {
|
export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
private static LOCAL_STORAGE_PRIVACY_CONCERN_KEY = 'video-watch-privacy-concern'
|
||||||
|
|
||||||
@ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
|
@ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
|
||||||
@ViewChild('videoShareModal') videoShareModal: VideoShareComponent
|
@ViewChild('videoShareModal') videoShareModal: VideoShareComponent
|
||||||
@ViewChild('videoReportModal') videoReportModal: VideoReportComponent
|
@ViewChild('videoReportModal') videoReportModal: VideoReportComponent
|
||||||
|
@ -301,75 +303,76 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private onVideoFetched (video: VideoDetails) {
|
private async onVideoFetched (video: VideoDetails) {
|
||||||
this.video = video
|
this.video = video
|
||||||
|
|
||||||
this.updateOtherVideosDisplayed()
|
this.updateOtherVideosDisplayed()
|
||||||
|
|
||||||
let observable
|
|
||||||
if (this.video.isVideoNSFWForUser(this.user)) {
|
if (this.video.isVideoNSFWForUser(this.user)) {
|
||||||
observable = this.confirmService.confirm(
|
const res = await this.confirmService.confirm(
|
||||||
'This video contains mature or explicit content. Are you sure you want to watch it?',
|
'This video contains mature or explicit content. Are you sure you want to watch it?',
|
||||||
'Mature or explicit content'
|
'Mature or explicit content'
|
||||||
)
|
)
|
||||||
} else {
|
if (res === false) return this.router.navigate([ '/videos/list' ])
|
||||||
observable = Observable.of(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
observable.subscribe(
|
if (!this.hasAlreadyAcceptedPrivacyConcern()) {
|
||||||
res => {
|
const res = await this.confirmService.confirm(
|
||||||
if (res === false) {
|
'PeerTube uses P2P, other may know you are watching that video through your public IP address. ' +
|
||||||
|
'Are you okay with that?',
|
||||||
|
'Privacy concern',
|
||||||
|
'I accept!'
|
||||||
|
)
|
||||||
|
if (res === false) return this.router.navigate([ '/videos/list' ])
|
||||||
|
}
|
||||||
|
|
||||||
return this.router.navigate([ '/videos/list' ])
|
this.acceptedPrivacyConcern()
|
||||||
}
|
|
||||||
|
|
||||||
// Player was already loaded
|
// Player was already loaded
|
||||||
if (this.videoPlayerLoaded !== true) {
|
if (this.videoPlayerLoaded !== true) {
|
||||||
this.playerElement = this.elementRef.nativeElement.querySelector('#video-element')
|
this.playerElement = this.elementRef.nativeElement.querySelector('#video-element')
|
||||||
|
|
||||||
// If autoplay is true, we don't really need a poster
|
// If autoplay is true, we don't really need a poster
|
||||||
if (this.isAutoplay() === false) {
|
if (this.isAutoplay() === false) {
|
||||||
this.playerElement.poster = this.video.previewUrl
|
this.playerElement.poster = this.video.previewUrl
|
||||||
}
|
|
||||||
|
|
||||||
const videojsOptions = {
|
|
||||||
controls: true,
|
|
||||||
autoplay: this.isAutoplay(),
|
|
||||||
plugins: {
|
|
||||||
peertube: {
|
|
||||||
videoFiles: this.video.files,
|
|
||||||
playerElement: this.playerElement,
|
|
||||||
peerTubeLink: false,
|
|
||||||
videoViewUrl: this.videoService.getVideoViewUrl(this.video.uuid),
|
|
||||||
videoDuration: this.video.duration
|
|
||||||
},
|
|
||||||
hotkeys: {
|
|
||||||
enableVolumeScroll: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.videoPlayerLoaded = true
|
|
||||||
|
|
||||||
const self = this
|
|
||||||
this.zone.runOutsideAngular(() => {
|
|
||||||
videojs(this.playerElement, videojsOptions, function () {
|
|
||||||
self.player = this
|
|
||||||
this.on('customError', (event, data) => self.handleError(data.err))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
const videoViewUrl = this.videoService.getVideoViewUrl(this.video.uuid)
|
|
||||||
this.player.peertube().setVideoFiles(this.video.files, videoViewUrl, this.video.duration)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setVideoDescriptionHTML()
|
|
||||||
this.setVideoLikesBarTooltipText()
|
|
||||||
|
|
||||||
this.setOpenGraphTags()
|
|
||||||
this.checkUserRating()
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
const videojsOptions = {
|
||||||
|
controls: true,
|
||||||
|
autoplay: this.isAutoplay(),
|
||||||
|
plugins: {
|
||||||
|
peertube: {
|
||||||
|
videoFiles: this.video.files,
|
||||||
|
playerElement: this.playerElement,
|
||||||
|
peerTubeLink: false,
|
||||||
|
videoViewUrl: this.videoService.getVideoViewUrl(this.video.uuid),
|
||||||
|
videoDuration: this.video.duration
|
||||||
|
},
|
||||||
|
hotkeys: {
|
||||||
|
enableVolumeScroll: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.videoPlayerLoaded = true
|
||||||
|
|
||||||
|
const self = this
|
||||||
|
this.zone.runOutsideAngular(() => {
|
||||||
|
videojs(this.playerElement, videojsOptions, function () {
|
||||||
|
self.player = this
|
||||||
|
this.on('customError', (event, data) => self.handleError(data.err))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const videoViewUrl = this.videoService.getVideoViewUrl(this.video.uuid)
|
||||||
|
this.player.peertube().setVideoFiles(this.video.files, videoViewUrl, this.video.duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setVideoDescriptionHTML()
|
||||||
|
this.setVideoLikesBarTooltipText()
|
||||||
|
|
||||||
|
this.setOpenGraphTags()
|
||||||
|
this.checkUserRating()
|
||||||
}
|
}
|
||||||
|
|
||||||
private setRating (nextRating) {
|
private setRating (nextRating) {
|
||||||
|
@ -411,8 +414,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.video.likes += likesToIncrement
|
this.video.likes += likesToIncrement
|
||||||
this.video.dislikes += dislikesToIncrement
|
this.video.dislikes += dislikesToIncrement
|
||||||
this.video.buildLikeAndDislikePercents()
|
|
||||||
|
|
||||||
|
this.video.buildLikeAndDislikePercents()
|
||||||
this.setVideoLikesBarTooltipText()
|
this.setVideoLikesBarTooltipText()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,4 +453,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
// Be sure the autoPlay is set to false
|
// Be sure the autoPlay is set to false
|
||||||
return this.user.autoPlayVideo !== false
|
return this.user.autoPlayVideo !== false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private hasAlreadyAcceptedPrivacyConcern () {
|
||||||
|
return localStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
private acceptedPrivacyConcern () {
|
||||||
|
localStorage.setItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY, 'true')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Thanks: https://github.com/zanechua/videojs-sublime-inspired-skin
|
@charset "utf-8";// Thanks: https://github.com/zanechua/videojs-sublime-inspired-skin
|
||||||
$primary-foreground-color: #fff;
|
$primary-foreground-color: #fff;
|
||||||
$primary-background-color: #000;
|
$primary-background-color: #000;
|
||||||
$font-size: 13px;
|
$font-size: 13px;
|
||||||
|
@ -8,6 +8,28 @@ $control-bar-height: 34px;
|
||||||
font-size: $font-size;
|
font-size: $font-size;
|
||||||
color: $primary-foreground-color;
|
color: $primary-foreground-color;
|
||||||
|
|
||||||
|
.vjs-dock-text {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-dock-description {
|
||||||
|
font-size: 11px;
|
||||||
|
|
||||||
|
&:before, &:after {
|
||||||
|
display: inline-block;
|
||||||
|
content: '\1F308';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
margin-left: 4px;
|
||||||
|
transform: scale(-1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.vjs-button > .vjs-icon-placeholder::before {
|
.vjs-button > .vjs-icon-placeholder::before {
|
||||||
line-height: $control-bar-height;
|
line-height: $control-bar-height;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +376,11 @@ $control-bar-height: 34px;
|
||||||
|
|
||||||
@media screen and (max-width: 300px) {
|
@media screen and (max-width: 300px) {
|
||||||
.vjs-dock-text {
|
.vjs-dock-text {
|
||||||
font-size: 1em;
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vjs-dock-description {
|
||||||
|
font-size: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-big-play-button {
|
.vjs-big-play-button {
|
||||||
|
|
|
@ -44,7 +44,8 @@ loadVideoInfo(videoId)
|
||||||
const player = this
|
const player = this
|
||||||
|
|
||||||
player.dock({
|
player.dock({
|
||||||
title: videoInfo.name
|
title: videoInfo.name,
|
||||||
|
description: 'Use P2P, other may know you are watching that video.'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue