aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/videos/+video-watch
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/videos/+video-watch')
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html66
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts41
2 files changed, 60 insertions, 47 deletions
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 583a97562..202a12fb0 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -3,7 +3,7 @@
3 <div [hidden]="videoNotFound" id="video-element-wrapper"> 3 <div [hidden]="videoNotFound" id="video-element-wrapper">
4 </div> 4 </div>
5 5
6 <div *ngIf="videoNotFound" id="video-not-found">Video not found :'(</div> 6 <div i18n *ngIf="videoNotFound" id="video-not-found">Video not found :'(</div>
7 7
8 <!-- Video information --> 8 <!-- Video information -->
9 <div *ngIf="video" class="margin-content video-bottom"> 9 <div *ngIf="video" class="margin-content video-bottom">
@@ -12,21 +12,21 @@
12 <div> 12 <div>
13 <div class="video-info-name">{{ video.name }}</div> 13 <div class="video-info-name">{{ video.name }}</div>
14 14
15 <div class="video-info-date-views"> 15 <div i18n class="video-info-date-views">
16 {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views 16 {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views
17 </div> 17 </div>
18 18
19 <div class="video-info-channel"> 19 <div class="video-info-channel">
20 <a [routerLink]="[ '/video-channels', video.channel.id ]" title="Go the channel page"> 20 <a [routerLink]="[ '/video-channels', video.channel.id ]" i18n-title title="Go the channel page">
21 {{ video.channel.displayName }} 21 {{ video.channel.displayName }}
22 </a> 22 </a>
23 <!-- Here will be the subscribe button --> 23 <!-- Here will be the subscribe button -->
24 <my-help helpType="custom" 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.displayName}}@{{video.account.host}}</strong> and subscribe there. Subscription as a PeerTube user is being worked on in <a href='https://github.com/Chocobozzz/PeerTube/issues/470'>#470</a>."></my-help> 24 <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.displayName}}@{{video.account.host}}</strong> and subscribe there. Subscription as a PeerTube user is being worked on in <a href='https://github.com/Chocobozzz/PeerTube/issues/470'>#470</a>."></my-help>
25 </div> 25 </div>
26 26
27 <div class="video-info-by"> 27 <div class="video-info-by">
28 <a [routerLink]="[ '/accounts', video.by ]" title="Go the account page"> 28 <a [routerLink]="[ '/accounts', video.by ]" i18n-title title="Go the account page">
29 <span>By {{ video.by }}</span> 29 <span i18n>By {{ video.by }}</span>
30 <img [src]="video.accountAvatarUrl" alt="Account avatar" /> 30 <img [src]="video.accountAvatarUrl" alt="Account avatar" />
31 </a> 31 </a>
32 </div> 32 </div>
@@ -38,24 +38,24 @@
38 *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()" 38 *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()"
39 class="action-button action-button-like" 39 class="action-button action-button-like"
40 > 40 >
41 <span class="icon icon-like" title="Like this video" ></span> 41 <span class="icon icon-like" i18n-title title="Like this video" ></span>
42 </div> 42 </div>
43 43
44 <div 44 <div
45 *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()" 45 *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()"
46 class="action-button action-button-dislike" 46 class="action-button action-button-dislike"
47 > 47 >
48 <span class="icon icon-dislike" title="Dislike this video"></span> 48 <span class="icon icon-dislike" i18n-title title="Dislike this video"></span>
49 </div> 49 </div>
50 50
51 <div *ngIf="video.support" (click)="showSupportModal()" class="action-button action-button-support"> 51 <div *ngIf="video.support" (click)="showSupportModal()" class="action-button action-button-support">
52 <span class="icon icon-support"></span> 52 <span class="icon icon-support"></span>
53 <span class="icon-text">Support</span> 53 <span class="icon-text" i18n>Support</span>
54 </div> 54 </div>
55 55
56 <div (click)="showShareModal()" class="action-button action-button-share"> 56 <div (click)="showShareModal()" class="action-button action-button-share">
57 <span class="icon icon-share"></span> 57 <span class="icon icon-share"></span>
58 <span class="icon-text">Share</span> 58 <span class="icon-text" i18n>Share</span>
59 </div> 59 </div>
60 60
61 <div class="action-more" dropdown dropup="true" placement="right"> 61 <div class="action-more" dropdown dropup="true" placement="right">
@@ -65,32 +65,32 @@
65 65
66 <ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button"> 66 <ul *dropdownMenu class="dropdown-menu" id="more-menu" role="menu" aria-labelledby="single-button">
67 <li role="menuitem"> 67 <li role="menuitem">
68 <a class="dropdown-item" title="Download the video" href="#" (click)="showDownloadModal($event)"> 68 <a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
69 <span class="icon icon-download"></span> Download 69 <span class="icon icon-download"></span> <ng-container i18n>Download</ng-container>
70 </a> 70 </a>
71 </li> 71 </li>
72 72
73 <li *ngIf="isUserLoggedIn()" role="menuitem"> 73 <li *ngIf="isUserLoggedIn()" role="menuitem">
74 <a class="dropdown-item" title="Report this video" href="#" (click)="showReportModal($event)"> 74 <a class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
75 <span class="icon icon-alert"></span> Report 75 <span class="icon icon-alert"></span> <ng-container i18n>Report</ng-container>
76 </a> 76 </a>
77 </li> 77 </li>
78 78
79 <li *ngIf="isVideoBlacklistable()" role="menuitem"> 79 <li *ngIf="isVideoBlacklistable()" role="menuitem">
80 <a class="dropdown-item" title="Blacklist this video" href="#" (click)="blacklistVideo($event)"> 80 <a class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="blacklistVideo($event)">
81 <span class="icon icon-blacklist"></span> Blacklist 81 <span class="icon icon-blacklist"></span> <ng-container i18n>Blacklist</ng-container>
82 </a> 82 </a>
83 </li> 83 </li>
84 84
85 <li *ngIf="isVideoUpdatable()" role="menuitem"> 85 <li *ngIf="isVideoUpdatable()" role="menuitem">
86 <a class="dropdown-item" title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]"> 86 <a class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
87 <span class="icon icon-edit"></span> Update 87 <span class="icon icon-edit"></span> <ng-container i18n>Update</ng-container>
88 </a> 88 </a>
89 </li> 89 </li>
90 90
91 <li *ngIf="isVideoRemovable()" role="menuitem"> 91 <li *ngIf="isVideoRemovable()" role="menuitem">
92 <a class="dropdown-item" title="Delete this video" href="#" (click)="removeVideo($event)"> 92 <a class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
93 <span class="icon icon-blacklist"></span> Delete 93 <span class="icon icon-blacklist"></span> <ng-container i18n>Delete</ng-container>
94 </a> 94 </a>
95 </li> 95 </li>
96 </ul> 96 </ul>
@@ -109,20 +109,20 @@
109 <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div> 109 <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div>
110 110
111 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()"> 111 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
112 Show more 112 <ng-container i18n>Show more</ng-container>
113 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span> 113 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
114 <my-loader class="description-loading" [loading]="descriptionLoading"></my-loader> 114 <my-loader class="description-loading" [loading]="descriptionLoading"></my-loader>
115 </div> 115 </div>
116 116
117 <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more"> 117 <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more">
118 Show less 118 <ng-container i18n>Show less</ng-container>
119 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span> 119 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span>
120 </div> 120 </div>
121 </div> 121 </div>
122 122
123 <div class="video-attributes"> 123 <div class="video-attributes">
124 <div class="video-attribute"> 124 <div class="video-attribute">
125 <span class="video-attribute-label"> 125 <span i18n class="video-attribute-label">
126 Privacy 126 Privacy
127 </span> 127 </span>
128 <span class="video-attribute-value"> 128 <span class="video-attribute-value">
@@ -131,7 +131,7 @@
131 </div> 131 </div>
132 132
133 <div class="video-attribute"> 133 <div class="video-attribute">
134 <span class="video-attribute-label"> 134 <span i18n class="video-attribute-label">
135 Category 135 Category
136 </span> 136 </span>
137 <span class="video-attribute-value"> 137 <span class="video-attribute-value">
@@ -140,7 +140,7 @@
140 </div> 140 </div>
141 141
142 <div class="video-attribute"> 142 <div class="video-attribute">
143 <span class="video-attribute-label"> 143 <span i18n class="video-attribute-label">
144 Licence 144 Licence
145 </span> 145 </span>
146 <span class="video-attribute-value"> 146 <span class="video-attribute-value">
@@ -149,7 +149,7 @@
149 </div> 149 </div>
150 150
151 <div class="video-attribute"> 151 <div class="video-attribute">
152 <span class="video-attribute-label"> 152 <span i18n class="video-attribute-label">
153 Language 153 Language
154 </span> 154 </span>
155 <span class="video-attribute-value"> 155 <span class="video-attribute-value">
@@ -158,7 +158,7 @@
158 </div> 158 </div>
159 159
160 <div class="video-attribute"> 160 <div class="video-attribute">
161 <span class="video-attribute-label"> 161 <span i18n class="video-attribute-label">
162 Tags 162 Tags
163 </span> 163 </span>
164 164
@@ -172,7 +172,7 @@
172 </div> 172 </div>
173 173
174 <div class="other-videos"> 174 <div class="other-videos">
175 <div class="title-page title-page-single"> 175 <div i18n class="title-page title-page-single">
176 Other videos 176 Other videos
177 </div> 177 </div>
178 178
@@ -184,13 +184,15 @@
184 184
185 185
186 <div class="privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false"> 186 <div class="privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false">
187 <strong>Friendly Reminder:</strong> 187 <strong i18n>Friendly Reminder:</strong>
188 <div class="privacy-concerns-text"> 188 <div class="privacy-concerns-text">
189 The sharing system used by this video implies that some technical information about your system (such as a public IP address) can be accessed publicly. 189 <ng-container i18n>
190 <a title="Get more information" target="_blank" rel="noopener noreferrer" href="/about#p2p-privacy">More information</a> 190 The sharing system used by this video implies that some technical information about your system (such as a public IP address) can be accessed publicly.
191 </ng-container>
192 <a i18n i18n-title title="Get more information" target="_blank" rel="noopener noreferrer" href="/about#p2p-privacy">More information</a>
191 </div> 193 </div>
192 194
193 <div class="privacy-concerns-okay" (click)="acceptedPrivacyConcern()"> 195 <div i18n class="privacy-concerns-okay" (click)="acceptedPrivacyConcern()">
194 OK 196 OK
195 </div> 197 </div>
196 </div> 198 </div>
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts
index ad572ef58..f3b4f7a2b 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -23,6 +23,7 @@ import { VideoReportComponent } from './modal/video-report.component'
23import { VideoShareComponent } from './modal/video-share.component' 23import { VideoShareComponent } from './modal/video-share.component'
24import { getVideojsOptions } from '../../../assets/player/peertube-player' 24import { getVideojsOptions } from '../../../assets/player/peertube-player'
25import { ServerService } from '@app/core' 25import { ServerService } from '@app/core'
26import { I18n } from '@ngx-translate/i18n-polyfill'
26 27
27@Component({ 28@Component({
28 selector: 'my-video-watch', 29 selector: 'my-video-watch',
@@ -70,7 +71,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
70 private notificationsService: NotificationsService, 71 private notificationsService: NotificationsService,
71 private markdownService: MarkdownService, 72 private markdownService: MarkdownService,
72 private zone: NgZone, 73 private zone: NgZone,
73 private redirectService: RedirectService 74 private redirectService: RedirectService,
75 private i18n: I18n
74 ) {} 76 ) {}
75 77
76 get user () { 78 get user () {
@@ -153,17 +155,20 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
153 async blacklistVideo (event: Event) { 155 async blacklistVideo (event: Event) {
154 event.preventDefault() 156 event.preventDefault()
155 157
156 const res = await this.confirmService.confirm('Do you really want to blacklist this video?', 'Blacklist') 158 const res = await this.confirmService.confirm(this.i18n('Do you really want to blacklist this video?'), this.i18n('Blacklist'))
157 if (res === false) return 159 if (res === false) return
158 160
159 this.videoBlacklistService.blacklistVideo(this.video.id) 161 this.videoBlacklistService.blacklistVideo(this.video.id)
160 .subscribe( 162 .subscribe(
161 status => { 163 status => {
162 this.notificationsService.success('Success', `Video ${this.video.name} had been blacklisted.`) 164 this.notificationsService.success(
165 this.i18n('Success'),
166 this.i18n('Video {{ videoName }} had been blacklisted.', { videoName: this.video.name })
167 )
163 this.redirectService.redirectToHomepage() 168 this.redirectService.redirectToHomepage()
164 }, 169 },
165 170
166 error => this.notificationsService.error('Error', error.message) 171 error => this.notificationsService.error(this.i18n('Error'), error.message)
167 ) 172 )
168 } 173 }
169 174
@@ -198,7 +203,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
198 203
199 error => { 204 error => {
200 this.descriptionLoading = false 205 this.descriptionLoading = false
201 this.notificationsService.error('Error', error.message) 206 this.notificationsService.error(this.i18n('Error'), error.message)
202 } 207 }
203 ) 208 )
204 } 209 }
@@ -252,19 +257,22 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
252 async removeVideo (event: Event) { 257 async removeVideo (event: Event) {
253 event.preventDefault() 258 event.preventDefault()
254 259
255 const res = await this.confirmService.confirm('Do you really want to delete this video?', 'Delete') 260 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this video?'), this.i18n('Delete'))
256 if (res === false) return 261 if (res === false) return
257 262
258 this.videoService.removeVideo(this.video.id) 263 this.videoService.removeVideo(this.video.id)
259 .subscribe( 264 .subscribe(
260 status => { 265 status => {
261 this.notificationsService.success('Success', `Video ${this.video.name} deleted.`) 266 this.notificationsService.success(
267 this.i18n('Success'),
268 this.i18n('Video {{ videoName }} deleted.', { videoName: this.video.name })
269 )
262 270
263 // Go back to the video-list. 271 // Go back to the video-list.
264 this.redirectService.redirectToHomepage() 272 this.redirectService.redirectToHomepage()
265 }, 273 },
266 274
267 error => this.notificationsService.error('Error', error.message) 275 error => this.notificationsService.error(this.i18n('Error'), error.message)
268 ) 276 )
269 } 277 }
270 278
@@ -288,7 +296,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
288 } 296 }
289 297
290 private setVideoLikesBarTooltipText () { 298 private setVideoLikesBarTooltipText () {
291 this.likesBarTooltipText = `${this.video.likes} likes / ${this.video.dislikes} dislikes` 299 this.likesBarTooltipText = this.i18n(
300 '{{ likesNumber }} likes / {{ dislikesNumber }} dislikes',
301 { likesNumber: this.video.likes, dislikes: this.video.dislikes }
302 )
292 } 303 }
293 304
294 private handleError (err: any) { 305 private handleError (err: any) {
@@ -298,12 +309,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
298 let message = '' 309 let message = ''
299 310
300 if (errorMessage.indexOf('http error') !== -1) { 311 if (errorMessage.indexOf('http error') !== -1) {
301 message = 'Cannot fetch video from server, maybe down.' 312 message = this.i18n('Cannot fetch video from server, maybe down.')
302 } else { 313 } else {
303 message = errorMessage 314 message = errorMessage
304 } 315 }
305 316
306 this.notificationsService.error('Error', message) 317 this.notificationsService.error(this.i18n('Error'), message)
307 } 318 }
308 319
309 private checkUserRating () { 320 private checkUserRating () {
@@ -318,7 +329,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
318 } 329 }
319 }, 330 },
320 331
321 err => this.notificationsService.error('Error', err.message) 332 err => this.notificationsService.error(this.i18n('Error'), err.message)
322 ) 333 )
323 } 334 }
324 335
@@ -333,8 +344,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
333 344
334 if (this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig())) { 345 if (this.video.isVideoNSFWForUser(this.user, this.serverService.getConfig())) {
335 const res = await this.confirmService.confirm( 346 const res = await this.confirmService.confirm(
336 'This video contains mature or explicit content. Are you sure you want to watch it?', 347 this.i18n('This video contains mature or explicit content. Are you sure you want to watch it?'),
337 'Mature or explicit content' 348 this.i18n('Mature or explicit content')
338 ) 349 )
339 if (res === false) return this.redirectService.redirectToHomepage() 350 if (res === false) return this.redirectService.redirectToHomepage()
340 } 351 }
@@ -399,7 +410,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
399 this.updateVideoRating(this.userRating, nextRating) 410 this.updateVideoRating(this.userRating, nextRating)
400 this.userRating = nextRating 411 this.userRating = nextRating
401 }, 412 },
402 err => this.notificationsService.error('Error', err.message) 413 err => this.notificationsService.error(this.i18n('Error'), err.message)
403 ) 414 )
404 } 415 }
405 416