aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+videos
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/+videos')
-rw-r--r--client/src/app/+videos/+video-watch/video-description.component.html19
-rw-r--r--client/src/app/+videos/+video-watch/video-description.component.scss46
-rw-r--r--client/src/app/+videos/+video-watch/video-description.component.ts87
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.html20
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.scss51
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.ts50
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.module.ts2
7 files changed, 158 insertions, 117 deletions
diff --git a/client/src/app/+videos/+video-watch/video-description.component.html b/client/src/app/+videos/+video-watch/video-description.component.html
new file mode 100644
index 000000000..57f682899
--- /dev/null
+++ b/client/src/app/+videos/+video-watch/video-description.component.html
@@ -0,0 +1,19 @@
1<div class="video-info-description">
2 <div
3 class="video-info-description-html"
4 [innerHTML]="videoHTMLDescription"
5 (timestampClicked)="onTimestampClicked($event)"
6 timestampRouteTransformer
7 ></div>
8
9 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
10 <ng-container i18n>Show more</ng-container>
11 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
12 <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader>
13 </div>
14
15 <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more">
16 <ng-container i18n>Show less</ng-container>
17 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span>
18 </div>
19</div>
diff --git a/client/src/app/+videos/+video-watch/video-description.component.scss b/client/src/app/+videos/+video-watch/video-description.component.scss
new file mode 100644
index 000000000..fc8b4574c
--- /dev/null
+++ b/client/src/app/+videos/+video-watch/video-description.component.scss
@@ -0,0 +1,46 @@
1@use '_variables' as *;
2@use '_mixins' as *;
3
4.video-info-description {
5 @include margin-left($video-watch-info-margin-left);
6 @include margin-right(0);
7
8 margin-top: 20px;
9 margin-bottom: 20px;
10 font-size: 15px;
11
12 .video-info-description-html {
13 @include peertube-word-wrap;
14
15 ::ng-deep a {
16 text-decoration: none;
17 }
18 }
19
20 .glyphicon,
21 .description-loading {
22 @include margin-left(3px);
23 }
24
25 .description-loading {
26 display: inline-block;
27 }
28
29 .video-info-description-more {
30 cursor: pointer;
31 font-weight: $font-semibold;
32 color: pvar(--greyForegroundColor);
33 font-size: 14px;
34
35 .glyphicon {
36 position: relative;
37 top: 2px;
38 }
39 }
40}
41
42@media screen and (max-width: 450px) {
43 .video-info-description {
44 font-size: 14px !important;
45 }
46}
diff --git a/client/src/app/+videos/+video-watch/video-description.component.ts b/client/src/app/+videos/+video-watch/video-description.component.ts
new file mode 100644
index 000000000..2ea3b206f
--- /dev/null
+++ b/client/src/app/+videos/+video-watch/video-description.component.ts
@@ -0,0 +1,87 @@
1import { Component, EventEmitter, Inject, Input, LOCALE_ID, OnChanges, Output } from '@angular/core'
2import { MarkdownService, Notifier } from '@app/core'
3import { VideoDetails, VideoService } from '@app/shared/shared-main'
4
5
6@Component({
7 selector: 'my-video-description',
8 templateUrl: './video-description.component.html',
9 styleUrls: [ './video-description.component.scss' ]
10})
11export class VideoDescriptionComponent implements OnChanges {
12 @Input() video: VideoDetails
13
14 @Output() timestampClicked = new EventEmitter<number>()
15
16 descriptionLoading = false
17 completeDescriptionShown = false
18 completeVideoDescription: string
19 shortVideoDescription: string
20 videoHTMLDescription = ''
21
22 constructor (
23 private videoService: VideoService,
24 private notifier: Notifier,
25 private markdownService: MarkdownService,
26 @Inject(LOCALE_ID) private localeId: string
27 ) { }
28
29 ngOnChanges () {
30 this.descriptionLoading = false
31 this.completeDescriptionShown = false
32 this.completeVideoDescription = undefined
33
34 this.setVideoDescriptionHTML()
35 }
36
37 showMoreDescription () {
38 if (this.completeVideoDescription === undefined) {
39 return this.loadCompleteDescription()
40 }
41
42 this.updateVideoDescription(this.completeVideoDescription)
43 this.completeDescriptionShown = true
44 }
45
46 showLessDescription () {
47 this.updateVideoDescription(this.shortVideoDescription)
48 this.completeDescriptionShown = false
49 }
50
51 loadCompleteDescription () {
52 this.descriptionLoading = true
53
54 this.videoService.loadCompleteDescription(this.video.descriptionPath)
55 .subscribe(
56 description => {
57 this.completeDescriptionShown = true
58 this.descriptionLoading = false
59
60 this.shortVideoDescription = this.video.description
61 this.completeVideoDescription = description
62
63 this.updateVideoDescription(this.completeVideoDescription)
64 },
65
66 error => {
67 this.descriptionLoading = false
68 this.notifier.error(error.message)
69 }
70 )
71 }
72
73 onTimestampClicked (timestamp: number) {
74 this.timestampClicked.emit(timestamp)
75 }
76
77 private updateVideoDescription (description: string) {
78 this.video.description = description
79 this.setVideoDescriptionHTML()
80 .catch(err => console.error(err))
81 }
82
83 private async setVideoDescriptionHTML () {
84 const html = await this.markdownService.textMarkdownToHTML(this.video.description)
85 this.videoHTMLDescription = this.markdownService.processVideoTimestamps(html)
86 }
87}
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 a659a7db1..40efa7b35 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.html
+++ b/client/src/app/+videos/+video-watch/video-watch.component.html
@@ -186,25 +186,7 @@
186 186
187 </div> 187 </div>
188 188
189 <div class="video-info-description"> 189 <my-video-description [video]="video"></my-video-description>
190 <div
191 class="video-info-description-html"
192 [innerHTML]="videoHTMLDescription"
193 (timestampClicked)="handleTimestampClicked($event)"
194 timestampRouteTransformer
195 ></div>
196
197 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
198 <ng-container i18n>Show more</ng-container>
199 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
200 <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader>
201 </div>
202
203 <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more">
204 <ng-container i18n>Show less</ng-container>
205 <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span>
206 </div>
207 </div>
208 190
209 <div class="video-attributes mb-3"> 191 <div class="video-attributes mb-3">
210 <div class="video-attribute"> 192 <div class="video-attribute">
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 4d68504f5..f25f3bf31 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.scss
+++ b/client/src/app/+videos/+video-watch/video-watch.component.scss
@@ -4,15 +4,12 @@
4@use '_bootstrap-variables'; 4@use '_bootstrap-variables';
5@use '_miniature' as *; 5@use '_miniature' as *;
6 6
7$player-factor: math.div(16, 9);
8$video-info-margin-left: 44px;
9
10@function getPlayerHeight ($width) { 7@function getPlayerHeight ($width) {
11 @return calc(#{$width} / #{$player-factor}); 8 @return calc(#{$width} / #{$video-watch-player-factor});
12} 9}
13 10
14@function getPlayerWidth ($height) { 11@function getPlayerWidth ($height) {
15 @return calc(#{$height} * #{$player-factor}); 12 @return calc(#{$height} * #{$video-watch-player-factor});
16} 13}
17 14
18@mixin playlist-below-player { 15@mixin playlist-below-player {
@@ -316,46 +313,8 @@ $video-info-margin-left: 44px;
316 } 313 }
317 } 314 }
318 315
319 .video-info-description {
320 @include margin-left($video-info-margin-left);
321 @include margin-right(0);
322
323 margin-top: 20px;
324 margin-bottom: 20px;
325 font-size: 15px;
326
327 .video-info-description-html {
328 @include peertube-word-wrap;
329
330 ::ng-deep a {
331 text-decoration: none;
332 }
333 }
334
335 .glyphicon,
336 .description-loading {
337 @include margin-left(3px);
338 }
339
340 .description-loading {
341 display: inline-block;
342 }
343
344 .video-info-description-more {
345 cursor: pointer;
346 font-weight: $font-semibold;
347 color: pvar(--greyForegroundColor);
348 font-size: 14px;
349
350 .glyphicon {
351 position: relative;
352 top: 2px;
353 }
354 }
355 }
356
357 .video-attributes { 316 .video-attributes {
358 @include margin-left($video-info-margin-left); 317 @include margin-left($video-watch-info-margin-left);
359 } 318 }
360 319
361 .video-attributes .video-attribute { 320 .video-attributes .video-attribute {
@@ -555,10 +514,6 @@ my-video-comments {
555 margin-top: 10px; 514 margin-top: 10px;
556 } 515 }
557 } 516 }
558
559 .video-info-description {
560 font-size: 14px !important;
561 }
562 } 517 }
563} 518}
564 519
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 e2fbf7524..e6b353220 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.component.ts
@@ -8,7 +8,6 @@ import {
8 AuthService, 8 AuthService,
9 AuthUser, 9 AuthUser,
10 ConfirmService, 10 ConfirmService,
11 MarkdownService,
12 MetaService, 11 MetaService,
13 Notifier, 12 Notifier,
14 PeerTubeSocket, 13 PeerTubeSocket,
@@ -139,7 +138,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
139 private serverService: ServerService, 138 private serverService: ServerService,
140 private restExtractor: RestExtractor, 139 private restExtractor: RestExtractor,
141 private notifier: Notifier, 140 private notifier: Notifier,
142 private markdownService: MarkdownService,
143 private zone: NgZone, 141 private zone: NgZone,
144 private redirectService: RedirectService, 142 private redirectService: RedirectService,
145 private videoCaptionService: VideoCaptionService, 143 private videoCaptionService: VideoCaptionService,
@@ -228,20 +226,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
228 this.hotkeysService.remove(this.hotkeys) 226 this.hotkeysService.remove(this.hotkeys)
229 } 227 }
230 228
231 showMoreDescription () {
232 if (this.completeVideoDescription === undefined) {
233 return this.loadCompleteDescription()
234 }
235
236 this.updateVideoDescription(this.completeVideoDescription)
237 this.completeDescriptionShown = true
238 }
239
240 showLessDescription () {
241 this.updateVideoDescription(this.shortVideoDescription)
242 this.completeDescriptionShown = false
243 }
244
245 showDownloadModal () { 229 showDownloadModal () {
246 this.videoDownloadModal.show(this.video, this.videoCaptions) 230 this.videoDownloadModal.show(this.video, this.videoCaptions)
247 } 231 }
@@ -250,28 +234,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
250 return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled && !this.video.isLive 234 return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled && !this.video.isLive
251 } 235 }
252 236
253 loadCompleteDescription () {
254 this.descriptionLoading = true
255
256 this.videoService.loadCompleteDescription(this.video.descriptionPath)
257 .subscribe(
258 description => {
259 this.completeDescriptionShown = true
260 this.descriptionLoading = false
261
262 this.shortVideoDescription = this.video.description
263 this.completeVideoDescription = description
264
265 this.updateVideoDescription(this.completeVideoDescription)
266 },
267
268 error => {
269 this.descriptionLoading = false
270 this.notifier.error(error.message)
271 }
272 )
273 }
274
275 showSupportModal () { 237 showSupportModal () {
276 this.supportModal.show() 238 this.supportModal.show()
277 } 239 }
@@ -492,17 +454,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
492 }) 454 })
493 } 455 }
494 456
495 private updateVideoDescription (description: string) {
496 this.video.description = description
497 this.setVideoDescriptionHTML()
498 .catch(err => console.error(err))
499 }
500
501 private async setVideoDescriptionHTML () {
502 const html = await this.markdownService.textMarkdownToHTML(this.video.description)
503 this.videoHTMLDescription = this.markdownService.processVideoTimestamps(html)
504 }
505
506 private setVideoLikesBarTooltipText () { 457 private setVideoLikesBarTooltipText () {
507 this.likesBarTooltipText = `${this.video.likes} likes / ${this.video.dislikes} dislikes` 458 this.likesBarTooltipText = `${this.video.likes} likes / ${this.video.dislikes} dislikes`
508 } 459 }
@@ -552,7 +503,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
552 this.buildPlayer(urlOptions) 503 this.buildPlayer(urlOptions)
553 .catch(err => console.error('Cannot build the player', err)) 504 .catch(err => console.error('Cannot build the player', err))
554 505
555 this.setVideoDescriptionHTML()
556 this.setVideoLikesBarTooltipText() 506 this.setVideoLikesBarTooltipText()
557 507
558 this.setOpenGraphTags() 508 this.setOpenGraphTags()
diff --git a/client/src/app/+videos/+video-watch/video-watch.module.ts b/client/src/app/+videos/+video-watch/video-watch.module.ts
index 57f36c723..93b143542 100644
--- a/client/src/app/+videos/+video-watch/video-watch.module.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.module.ts
@@ -19,6 +19,7 @@ import { PlayerStylesComponent } from './player-styles.component'
19import { RecommendationsModule } from './recommendations/recommendations.module' 19import { RecommendationsModule } from './recommendations/recommendations.module'
20import { TimestampRouteTransformerDirective } from './timestamp-route-transformer.directive' 20import { TimestampRouteTransformerDirective } from './timestamp-route-transformer.directive'
21import { VideoAvatarChannelComponent } from './video-avatar-channel.component' 21import { VideoAvatarChannelComponent } from './video-avatar-channel.component'
22import { VideoDescriptionComponent } from './video-description.component'
22import { VideoRateComponent } from './video-rate.component' 23import { VideoRateComponent } from './video-rate.component'
23import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' 24import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
24import { VideoWatchRoutingModule } from './video-watch-routing.module' 25import { VideoWatchRoutingModule } from './video-watch-routing.module'
@@ -47,6 +48,7 @@ import { VideoWatchComponent } from './video-watch.component'
47 VideoWatchComponent, 48 VideoWatchComponent,
48 VideoWatchPlaylistComponent, 49 VideoWatchPlaylistComponent,
49 VideoRateComponent, 50 VideoRateComponent,
51 VideoDescriptionComponent,
50 52
51 VideoCommentsComponent, 53 VideoCommentsComponent,
52 VideoCommentAddComponent, 54 VideoCommentAddComponent,