diff options
Diffstat (limited to 'client/src/app/+videos')
35 files changed, 522 insertions, 420 deletions
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html b/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html index 6a07dafa7..092952204 100644 --- a/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html +++ b/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.html | |||
@@ -34,12 +34,12 @@ | |||
34 | 34 | ||
35 | <div class="modal-footer inputs"> | 35 | <div class="modal-footer inputs"> |
36 | <input | 36 | <input |
37 | type="button" role="button" i18n-value value="Cancel" class="action-button action-button-cancel" | 37 | type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button" |
38 | (click)="hide()" (key.enter)="hide()" | 38 | (click)="hide()" (key.enter)="hide()" |
39 | > | 39 | > |
40 | 40 | ||
41 | <input | 41 | <input |
42 | type="submit" i18n-value value="Add this caption" class="action-button-submit" | 42 | type="submit" i18n-value value="Add this caption" class="peertube-button orange-button" |
43 | [disabled]="!form.valid" (click)="addCaption()" | 43 | [disabled]="!form.valid" (click)="addCaption()" |
44 | > | 44 | > |
45 | </div> | 45 | </div> |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts index 8780ca567..8e035b6bb 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts | |||
@@ -1,8 +1,8 @@ | |||
1 | 1 | ||
2 | import { forkJoin } from 'rxjs' | 2 | import { forkJoin } from 'rxjs' |
3 | import { Component, EventEmitter, OnInit, Output } from '@angular/core' | 3 | import { AfterViewChecked, AfterViewInit, Component, EventEmitter, OnInit, Output } from '@angular/core' |
4 | import { Router } from '@angular/router' | 4 | import { Router } from '@angular/router' |
5 | import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' | 5 | import { AuthService, CanComponentDeactivate, HooksService, Notifier, ServerService } from '@app/core' |
6 | import { scrollToTop } from '@app/helpers' | 6 | import { scrollToTop } from '@app/helpers' |
7 | import { FormValidatorService } from '@app/shared/shared-forms' | 7 | import { FormValidatorService } from '@app/shared/shared-forms' |
8 | import { VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 8 | import { VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
@@ -19,7 +19,7 @@ import { VideoSend } from './video-send' | |||
19 | './video-send.scss' | 19 | './video-send.scss' |
20 | ] | 20 | ] |
21 | }) | 21 | }) |
22 | export class VideoGoLiveComponent extends VideoSend implements OnInit, CanComponentDeactivate { | 22 | export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterViewInit, CanComponentDeactivate { |
23 | @Output() firstStepDone = new EventEmitter<string>() | 23 | @Output() firstStepDone = new EventEmitter<string>() |
24 | @Output() firstStepError = new EventEmitter<void>() | 24 | @Output() firstStepError = new EventEmitter<void>() |
25 | 25 | ||
@@ -41,7 +41,8 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, CanCompon | |||
41 | protected videoService: VideoService, | 41 | protected videoService: VideoService, |
42 | protected videoCaptionService: VideoCaptionService, | 42 | protected videoCaptionService: VideoCaptionService, |
43 | private liveVideoService: LiveVideoService, | 43 | private liveVideoService: LiveVideoService, |
44 | private router: Router | 44 | private router: Router, |
45 | private hooks: HooksService | ||
45 | ) { | 46 | ) { |
46 | super() | 47 | super() |
47 | } | 48 | } |
@@ -50,6 +51,10 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, CanCompon | |||
50 | super.ngOnInit() | 51 | super.ngOnInit() |
51 | } | 52 | } |
52 | 53 | ||
54 | ngAfterViewInit () { | ||
55 | this.hooks.runAction('action:go-live.init', 'video-edit') | ||
56 | } | ||
57 | |||
53 | canDeactivate () { | 58 | canDeactivate () { |
54 | return { canDeactivate: true } | 59 | return { canDeactivate: true } |
55 | } | 60 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.scss b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.scss index 1fef74994..dd87641fc 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.scss +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.scss | |||
@@ -3,8 +3,8 @@ | |||
3 | 3 | ||
4 | .first-step-block { | 4 | .first-step-block { |
5 | .torrent-or-magnet { | 5 | .torrent-or-magnet { |
6 | @include divider($color: pvar(--inputPlaceholderColor), $background: pvar(--submenuColor)); | 6 | @include divider($color: pvar(--inputPlaceholderColor), $background: pvar(--submenuBackgroundColor)); |
7 | 7 | ||
8 | &[data-content] { | 8 | &[data-content] { |
9 | margin: 1.5rem 0; | 9 | margin: 1.5rem 0; |
10 | } | 10 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts index 01087e525..3aae24732 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' | 1 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { Router } from '@angular/router' | 2 | import { Router } from '@angular/router' |
3 | import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' | 3 | import { AuthService, CanComponentDeactivate, HooksService, Notifier, ServerService } from '@app/core' |
4 | import { scrollToTop } from '@app/helpers' | 4 | import { scrollToTop } from '@app/helpers' |
5 | import { FormValidatorService } from '@app/shared/shared-forms' | 5 | import { FormValidatorService } from '@app/shared/shared-forms' |
6 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' | 6 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' |
@@ -18,7 +18,7 @@ import { VideoSend } from './video-send' | |||
18 | './video-send.scss' | 18 | './video-send.scss' |
19 | ] | 19 | ] |
20 | }) | 20 | }) |
21 | export class VideoImportTorrentComponent extends VideoSend implements OnInit, CanComponentDeactivate { | 21 | export class VideoImportTorrentComponent extends VideoSend implements OnInit, AfterViewInit, CanComponentDeactivate { |
22 | @Output() firstStepDone = new EventEmitter<string>() | 22 | @Output() firstStepDone = new EventEmitter<string>() |
23 | @Output() firstStepError = new EventEmitter<void>() | 23 | @Output() firstStepError = new EventEmitter<void>() |
24 | @ViewChild('torrentfileInput') torrentfileInput: ElementRef<HTMLInputElement> | 24 | @ViewChild('torrentfileInput') torrentfileInput: ElementRef<HTMLInputElement> |
@@ -43,7 +43,8 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca | |||
43 | protected videoService: VideoService, | 43 | protected videoService: VideoService, |
44 | protected videoCaptionService: VideoCaptionService, | 44 | protected videoCaptionService: VideoCaptionService, |
45 | private router: Router, | 45 | private router: Router, |
46 | private videoImportService: VideoImportService | 46 | private videoImportService: VideoImportService, |
47 | private hooks: HooksService | ||
47 | ) { | 48 | ) { |
48 | super() | 49 | super() |
49 | } | 50 | } |
@@ -52,6 +53,10 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca | |||
52 | super.ngOnInit() | 53 | super.ngOnInit() |
53 | } | 54 | } |
54 | 55 | ||
56 | ngAfterViewInit () { | ||
57 | this.hooks.runAction('action:video-torrent-import.init', 'video-edit') | ||
58 | } | ||
59 | |||
55 | canDeactivate () { | 60 | canDeactivate () { |
56 | return { canDeactivate: true } | 61 | return { canDeactivate: true } |
57 | } | 62 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts index c447c179d..7a9fe369f 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { map, switchMap } from 'rxjs/operators' | 1 | import { map, switchMap } from 'rxjs/operators' |
2 | import { Component, EventEmitter, OnInit, Output } from '@angular/core' | 2 | import { AfterViewInit, Component, EventEmitter, OnInit, Output } from '@angular/core' |
3 | import { Router } from '@angular/router' | 3 | import { Router } from '@angular/router' |
4 | import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' | 4 | import { AuthService, CanComponentDeactivate, HooksService, Notifier, ServerService } from '@app/core' |
5 | import { getAbsoluteAPIUrl, scrollToTop } from '@app/helpers' | 5 | import { getAbsoluteAPIUrl, scrollToTop } from '@app/helpers' |
6 | import { FormValidatorService } from '@app/shared/shared-forms' | 6 | import { FormValidatorService } from '@app/shared/shared-forms' |
7 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' | 7 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' |
@@ -18,7 +18,7 @@ import { VideoSend } from './video-send' | |||
18 | './video-send.scss' | 18 | './video-send.scss' |
19 | ] | 19 | ] |
20 | }) | 20 | }) |
21 | export class VideoImportUrlComponent extends VideoSend implements OnInit, CanComponentDeactivate { | 21 | export class VideoImportUrlComponent extends VideoSend implements OnInit, AfterViewInit, CanComponentDeactivate { |
22 | @Output() firstStepDone = new EventEmitter<string>() | 22 | @Output() firstStepDone = new EventEmitter<string>() |
23 | @Output() firstStepError = new EventEmitter<void>() | 23 | @Output() firstStepError = new EventEmitter<void>() |
24 | 24 | ||
@@ -42,8 +42,9 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, CanCom | |||
42 | protected videoService: VideoService, | 42 | protected videoService: VideoService, |
43 | protected videoCaptionService: VideoCaptionService, | 43 | protected videoCaptionService: VideoCaptionService, |
44 | private router: Router, | 44 | private router: Router, |
45 | private videoImportService: VideoImportService | 45 | private videoImportService: VideoImportService, |
46 | ) { | 46 | private hooks: HooksService |
47 | ) { | ||
47 | super() | 48 | super() |
48 | } | 49 | } |
49 | 50 | ||
@@ -51,6 +52,10 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, CanCom | |||
51 | super.ngOnInit() | 52 | super.ngOnInit() |
52 | } | 53 | } |
53 | 54 | ||
55 | ngAfterViewInit () { | ||
56 | this.hooks.runAction('action:video-url-import.init', 'video-edit') | ||
57 | } | ||
58 | |||
54 | canDeactivate () { | 59 | canDeactivate () { |
55 | return { canDeactivate: true } | 60 | return { canDeactivate: true } |
56 | } | 61 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts index ca21b61cd..effb37077 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts | |||
@@ -1,15 +1,15 @@ | |||
1 | import { Subscription } from 'rxjs' | 1 | import { Subscription } from 'rxjs' |
2 | import { HttpErrorResponse, HttpEventType, HttpResponse } from '@angular/common/http' | 2 | import { HttpErrorResponse, HttpEventType, HttpResponse } from '@angular/common/http' |
3 | import { Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' | 3 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' |
4 | import { Router } from '@angular/router' | 4 | import { Router } from '@angular/router' |
5 | import { AuthService, CanComponentDeactivate, Notifier, ServerService, UserService } from '@app/core' | 5 | import { AuthService, CanComponentDeactivate, HooksService, Notifier, ServerService, UserService } from '@app/core' |
6 | import { scrollToTop, uploadErrorHandler } from '@app/helpers' | 6 | import { scrollToTop, uploadErrorHandler } from '@app/helpers' |
7 | import { FormValidatorService } from '@app/shared/shared-forms' | 7 | import { FormValidatorService } from '@app/shared/shared-forms' |
8 | import { BytesPipe, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 8 | import { BytesPipe, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
9 | import { LoadingBarService } from '@ngx-loading-bar/core' | 9 | import { LoadingBarService } from '@ngx-loading-bar/core' |
10 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | ||
10 | import { VideoPrivacy } from '@shared/models' | 11 | import { VideoPrivacy } from '@shared/models' |
11 | import { VideoSend } from './video-send' | 12 | import { VideoSend } from './video-send' |
12 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | ||
13 | 13 | ||
14 | @Component({ | 14 | @Component({ |
15 | selector: 'my-video-upload', | 15 | selector: 'my-video-upload', |
@@ -20,7 +20,7 @@ import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | |||
20 | './video-send.scss' | 20 | './video-send.scss' |
21 | ] | 21 | ] |
22 | }) | 22 | }) |
23 | export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy, CanComponentDeactivate { | 23 | export class VideoUploadComponent extends VideoSend implements OnInit, AfterViewInit, OnDestroy, CanComponentDeactivate { |
24 | @Output() firstStepDone = new EventEmitter<string>() | 24 | @Output() firstStepDone = new EventEmitter<string>() |
25 | @Output() firstStepError = new EventEmitter<void>() | 25 | @Output() firstStepError = new EventEmitter<void>() |
26 | @ViewChild('videofileInput') videofileInput: ElementRef<HTMLInputElement> | 26 | @ViewChild('videofileInput') videofileInput: ElementRef<HTMLInputElement> |
@@ -60,7 +60,8 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
60 | protected videoService: VideoService, | 60 | protected videoService: VideoService, |
61 | protected videoCaptionService: VideoCaptionService, | 61 | protected videoCaptionService: VideoCaptionService, |
62 | private userService: UserService, | 62 | private userService: UserService, |
63 | private router: Router | 63 | private router: Router, |
64 | private hooks: HooksService | ||
64 | ) { | 65 | ) { |
65 | super() | 66 | super() |
66 | } | 67 | } |
@@ -79,6 +80,10 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
79 | }) | 80 | }) |
80 | } | 81 | } |
81 | 82 | ||
83 | ngAfterViewInit () { | ||
84 | this.hooks.runAction('action:video-upload.init', 'video-edit') | ||
85 | } | ||
86 | |||
82 | ngOnDestroy () { | 87 | ngOnDestroy () { |
83 | if (this.videoUploadObservable) this.videoUploadObservable.unsubscribe() | 88 | if (this.videoUploadObservable) this.videoUploadObservable.unsubscribe() |
84 | } | 89 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add.component.scss b/client/src/app/+videos/+video-edit/video-add.component.scss index 5db9e823d..1ebee946b 100644 --- a/client/src/app/+videos/+video-edit/video-add.component.scss +++ b/client/src/app/+videos/+video-edit/video-add.component.scss | |||
@@ -67,7 +67,7 @@ $nav-link-height: 40px; | |||
67 | &.active { | 67 | &.active { |
68 | border-color: $border-color; | 68 | border-color: $border-color; |
69 | border-bottom-color: transparent; | 69 | border-bottom-color: transparent; |
70 | background-color: pvar(--submenuColor) !important; | 70 | background-color: pvar(--submenuBackgroundColor) !important; |
71 | 71 | ||
72 | span { | 72 | span { |
73 | border-bottom-color: pvar(--mainColor); | 73 | border-bottom-color: pvar(--mainColor); |
@@ -84,7 +84,7 @@ $nav-link-height: 40px; | |||
84 | border: $border-width $border-type $border-color; | 84 | border: $border-width $border-type $border-color; |
85 | border-top: transparent; | 85 | border-top: transparent; |
86 | 86 | ||
87 | background-color: pvar(--submenuColor); | 87 | background-color: pvar(--submenuBackgroundColor); |
88 | border-bottom-left-radius: 3px; | 88 | border-bottom-left-radius: 3px; |
89 | border-bottom-right-radius: 3px; | 89 | border-bottom-right-radius: 3px; |
90 | width: 100%; | 90 | width: 100%; |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html index fdefed09a..7bd9b7c90 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html +++ b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html | |||
@@ -1,6 +1,6 @@ | |||
1 | <form novalidate [formGroup]="form" (ngSubmit)="formValidated()"> | 1 | <form novalidate [formGroup]="form" (ngSubmit)="formValidated()"> |
2 | <div class="avatar-and-textarea"> | 2 | <div class="avatar-and-textarea"> |
3 | <img [src]="getAvatarUrl()" alt="Avatar" /> | 3 | <my-account-avatar [account]="user?.account" size="25"></my-account-avatar> |
4 | 4 | ||
5 | <div class="form-group"> | 5 | <div class="form-group"> |
6 | <textarea i18n-placeholder placeholder="Add comment..." myAutoResize | 6 | <textarea i18n-placeholder placeholder="Add comment..." myAutoResize |
@@ -8,8 +8,8 @@ | |||
8 | (click)="openVisitorModal($event)" | 8 | (click)="openVisitorModal($event)" |
9 | formControlName="text" [ngClass]="{ 'input-error': formErrors['text'] }" | 9 | formControlName="text" [ngClass]="{ 'input-error': formErrors['text'] }" |
10 | (keyup.control.enter)="onValidKey()" (keyup.meta.enter)="onValidKey()" #textarea> | 10 | (keyup.control.enter)="onValidKey()" (keyup.meta.enter)="onValidKey()" #textarea> |
11 | |||
12 | </textarea> | 11 | </textarea> |
12 | |||
13 | <my-help class="markdown-guide" helpType="custom" iconName="markdown" tooltipPlacement="left auto" autoClose="true" i18n-title title="Markdown compatible"> | 13 | <my-help class="markdown-guide" helpType="custom" iconName="markdown" tooltipPlacement="left auto" autoClose="true" i18n-title title="Markdown compatible"> |
14 | <ng-template ptTemplate="customHtml"> | 14 | <ng-template ptTemplate="customHtml"> |
15 | <span i18n>Markdown compatible that supports:</span> | 15 | <span i18n>Markdown compatible that supports:</span> |
@@ -41,10 +41,11 @@ | |||
41 | </div> | 41 | </div> |
42 | 42 | ||
43 | <div class="comment-buttons"> | 43 | <div class="comment-buttons"> |
44 | <button *ngIf="isAddButtonDisplayed()" class="cancel-button" (click)="cancelCommentReply()" type="button" i18n> | 44 | <button *ngIf="isAddButtonDisplayed()" class="peertube-button tertiary-button cancel-button" (click)="cancelCommentReply()" type="button" i18n> |
45 | Cancel | 45 | Cancel |
46 | </button> | 46 | </button> |
47 | <button *ngIf="isAddButtonDisplayed()" [ngClass]="{ disabled: !form.valid || addingComment }"> | 47 | |
48 | <button *ngIf="isAddButtonDisplayed()" class="peertube-button orange-button" [ngClass]="{ disabled: !form.valid || addingComment }"> | ||
48 | {{ addingCommentButtonValue }} | 49 | {{ addingCommentButtonValue }} |
49 | </button> | 50 | </button> |
50 | </div> | 51 | </div> |
@@ -55,6 +56,7 @@ | |||
55 | <h4 class="modal-title" id="modal-basic-title" i18n>You are one step away from commenting</h4> | 56 | <h4 class="modal-title" id="modal-basic-title" i18n>You are one step away from commenting</h4> |
56 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hideModals()"></my-global-icon> | 57 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hideModals()"></my-global-icon> |
57 | </div> | 58 | </div> |
59 | |||
58 | <div class="modal-body"> | 60 | <div class="modal-body"> |
59 | <span i18n> | 61 | <span i18n> |
60 | You can comment using an account on any ActivityPub-compatible instance (PeerTube/Mastodon/Pleroma account for example). | 62 | You can comment using an account on any ActivityPub-compatible instance (PeerTube/Mastodon/Pleroma account for example). |
@@ -62,14 +64,15 @@ | |||
62 | 64 | ||
63 | <my-remote-subscribe [interact]="true" [uri]="getUri()"></my-remote-subscribe> | 65 | <my-remote-subscribe [interact]="true" [uri]="getUri()"></my-remote-subscribe> |
64 | </div> | 66 | </div> |
67 | |||
65 | <div class="modal-footer inputs"> | 68 | <div class="modal-footer inputs"> |
66 | <input | 69 | <input |
67 | type="button" role="button" i18n-value value="Cancel" class="action-button action-button-cancel" | 70 | type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button" |
68 | (click)="hideModals()" (key.enter)="hideModals()" | 71 | (click)="hideModals()" (key.enter)="hideModals()" |
69 | > | 72 | > |
70 | 73 | ||
71 | <input | 74 | <input |
72 | type="submit" i18n-value value="Login to comment" class="action-button-submit" | 75 | type="submit" i18n-value value="Login to comment" class="peertube-button orange-button" |
73 | (click)="gotoLogin()" | 76 | (click)="gotoLogin()" |
74 | > | 77 | > |
75 | </div> | 78 | </div> |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss index d938e2e28..1aa9255c2 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss +++ b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss | |||
@@ -1,6 +1,10 @@ | |||
1 | @import '_variables'; | 1 | @import '_variables'; |
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | $markdown-icon-height: 18px; | ||
5 | $markdown-icon-width: 30px; | ||
6 | $peertube-textarea-height: 60px; | ||
7 | |||
4 | form { | 8 | form { |
5 | margin-bottom: 30px; | 9 | margin-bottom: 30px; |
6 | } | 10 | } |
@@ -9,9 +13,7 @@ form { | |||
9 | display: flex; | 13 | display: flex; |
10 | margin-bottom: 10px; | 14 | margin-bottom: 10px; |
11 | 15 | ||
12 | img { | 16 | my-account-avatar { |
13 | @include avatar(25px); | ||
14 | |||
15 | vertical-align: top; | 17 | vertical-align: top; |
16 | margin-right: 10px; | 18 | margin-right: 10px; |
17 | } | 19 | } |
@@ -20,83 +22,55 @@ form { | |||
20 | flex-grow: 1; | 22 | flex-grow: 1; |
21 | margin: 0; | 23 | margin: 0; |
22 | position: relative; | 24 | position: relative; |
25 | } | ||
23 | 26 | ||
24 | $peertube-textarea-height: 60px; | 27 | textarea { |
25 | $markdown-icon-height: 18px; | 28 | @include peertube-textarea(100%, $peertube-textarea-height); |
26 | $markdown-icon-width: 30px; | 29 | @include button-focus(pvar(--mainColorLightest)); |
27 | |||
28 | .markdown-guide { | ||
29 | position: absolute; | ||
30 | top: 5px; | ||
31 | right: 9px; | ||
32 | |||
33 | ::ng-deep .help-tooltip-button { | ||
34 | my-global-icon { | ||
35 | height: $markdown-icon-height; | ||
36 | width: $markdown-icon-width; | ||
37 | |||
38 | svg { | ||
39 | color: #C6C6C6; | ||
40 | fill: #C6C6C6; | ||
41 | border-radius: 3px; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | &:focus, &:active, &:hover { | ||
46 | my-global-icon svg { | ||
47 | background-color: #C6C6C6; | ||
48 | color: pvar(--mainBackgroundColor); | ||
49 | fill: pvar(--mainBackgroundColor); | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
55 | textarea { | ||
56 | @include peertube-textarea(100%, $peertube-textarea-height); | ||
57 | @include button-focus(pvar(--mainColorLightest)); | ||
58 | 30 | ||
59 | min-height: calc(#{$peertube-textarea-height} - 15px * 2); | 31 | min-height: calc(#{$peertube-textarea-height} - 15px * 2); |
60 | padding-right: $markdown-icon-width + 15px !important; | 32 | padding-right: $markdown-icon-width + 15px !important; |
61 | 33 | ||
62 | @media screen and (max-width: 600px) { | 34 | @media screen and (max-width: 600px) { |
63 | padding-right: $markdown-icon-width + 19px !important; | 35 | padding-right: $markdown-icon-width + 19px !important; |
64 | } | 36 | } |
65 | 37 | ||
66 | &:focus::placeholder { | 38 | &:focus::placeholder { |
67 | opacity: 0; | 39 | opacity: 0; |
68 | } | ||
69 | } | 40 | } |
70 | } | 41 | } |
71 | } | 42 | } |
72 | 43 | ||
73 | .comment-buttons { | 44 | .markdown-guide { |
74 | display: flex; | 45 | position: absolute; |
75 | justify-content: flex-end; | 46 | top: 5px; |
47 | right: 9px; | ||
76 | 48 | ||
77 | button { | 49 | ::ng-deep .help-tooltip-button { |
78 | @include peertube-button; | 50 | my-global-icon { |
79 | @include disable-outline; | 51 | height: $markdown-icon-height; |
80 | @include disable-default-a-behaviour; | 52 | width: $markdown-icon-width; |
81 | 53 | ||
82 | &:not(:last-child) { | 54 | svg { |
83 | margin-right: .5rem; | 55 | color: #C6C6C6; |
56 | fill: #C6C6C6; | ||
57 | border-radius: 3px; | ||
58 | } | ||
84 | } | 59 | } |
85 | 60 | ||
86 | &:last-child { | 61 | &:focus, &:active, &:hover { |
87 | @include orange-button; | 62 | my-global-icon svg { |
63 | background-color: #C6C6C6; | ||
64 | color: pvar(--mainBackgroundColor); | ||
65 | fill: pvar(--mainBackgroundColor); | ||
66 | } | ||
88 | } | 67 | } |
89 | } | 68 | } |
69 | } | ||
90 | 70 | ||
91 | .cancel-button { | 71 | .comment-buttons { |
92 | @include tertiary-button; | 72 | display: flex; |
93 | 73 | justify-content: flex-end; | |
94 | font-weight: $font-semibold; | ||
95 | display: inline-block; | ||
96 | padding: 0 10px 0 10px; | ||
97 | white-space: nowrap; | ||
98 | background: transparent; | ||
99 | } | ||
100 | } | 74 | } |
101 | 75 | ||
102 | .emoji-flex { | 76 | .emoji-flex { |
@@ -119,7 +93,8 @@ form { | |||
119 | } | 93 | } |
120 | 94 | ||
121 | @media screen and (max-width: 600px) { | 95 | @media screen and (max-width: 600px) { |
122 | textarea, .comment-buttons button { | 96 | textarea, |
97 | .comment-buttons button { | ||
123 | font-size: 14px !important; | 98 | font-size: 14px !important; |
124 | } | 99 | } |
125 | 100 | ||
@@ -129,12 +104,7 @@ form { | |||
129 | } | 104 | } |
130 | 105 | ||
131 | .modal-body { | 106 | .modal-body { |
132 | .btn { | 107 | > span { |
133 | @include peertube-button; | ||
134 | @include orange-button; | ||
135 | } | ||
136 | |||
137 | span { | ||
138 | float: left; | 108 | float: left; |
139 | margin-bottom: 20px; | 109 | margin-bottom: 20px; |
140 | } | 110 | } |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.ts b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.ts index f1f0dfeba..0e1362ad3 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.ts +++ b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.ts | |||
@@ -4,7 +4,7 @@ import { Router } from '@angular/router' | |||
4 | import { Notifier, User } from '@app/core' | 4 | import { Notifier, User } from '@app/core' |
5 | import { VIDEO_COMMENT_TEXT_VALIDATOR } from '@app/shared/form-validators/video-comment-validators' | 5 | import { VIDEO_COMMENT_TEXT_VALIDATOR } from '@app/shared/form-validators/video-comment-validators' |
6 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | 6 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
7 | import { Video, Account } from '@app/shared/shared-main' | 7 | import { Video } from '@app/shared/shared-main' |
8 | import { VideoComment, VideoCommentService } from '@app/shared/shared-video-comment' | 8 | import { VideoComment, VideoCommentService } from '@app/shared/shared-video-comment' |
9 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | 9 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' |
10 | import { VideoCommentCreate } from '@shared/models' | 10 | import { VideoCommentCreate } from '@shared/models' |
@@ -143,11 +143,6 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges, | |||
143 | return window.location.href | 143 | return window.location.href |
144 | } | 144 | } |
145 | 145 | ||
146 | getAvatarUrl () { | ||
147 | if (this.user) return this.user.accountAvatarUrl | ||
148 | return Account.GET_DEFAULT_AVATAR_URL() | ||
149 | } | ||
150 | |||
151 | gotoLogin () { | 146 | gotoLogin () { |
152 | this.hideModals() | 147 | this.hideModals() |
153 | this.router.navigate([ '/login' ]) | 148 | this.router.navigate([ '/login' ]) |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.html b/client/src/app/+videos/+video-watch/comment/video-comment.component.html index ba41b6f48..4592c9c69 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment.component.html +++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.html | |||
@@ -1,14 +1,6 @@ | |||
1 | <div *ngIf="isCommentDisplayed()" class="root-comment"> | 1 | <div *ngIf="isCommentDisplayed()" class="root-comment"> |
2 | <div class="left"> | 2 | <div class="left"> |
3 | <a *ngIf="!comment.isDeleted" [href]="comment.account.url" target="_blank" rel="noopener noreferrer"> | 3 | <my-account-avatar *ngIf="!comment.isDeleted" [href]="comment.account.url" [account]="comment.account"></my-account-avatar> |
4 | <img | ||
5 | class="comment-avatar" | ||
6 | [src]="comment.accountAvatarUrl" | ||
7 | (error)="switchToDefaultAvatar($event)" | ||
8 | alt="Avatar" | ||
9 | /> | ||
10 | </a> | ||
11 | |||
12 | <div class="vertical-border"></div> | 4 | <div class="vertical-border"></div> |
13 | </div> | 5 | </div> |
14 | 6 | ||
@@ -46,7 +38,7 @@ | |||
46 | <div *ngIf="isUserLoggedIn()" tabindex=0 (click)="onWantToReply()" class="comment-action-reply" i18n>Reply</div> | 38 | <div *ngIf="isUserLoggedIn()" tabindex=0 (click)="onWantToReply()" class="comment-action-reply" i18n>Reply</div> |
47 | 39 | ||
48 | <my-user-moderation-dropdown | 40 | <my-user-moderation-dropdown |
49 | [prependActions]="prependModerationActions" tabindex=0 | 41 | [prependActions]="prependModerationActions" tabindex=0 [buttonStyled]="false" |
50 | buttonSize="small" [account]="commentAccount" [user]="commentUser" i18n-label label="Options" placement="bottom-left auto" | 42 | buttonSize="small" [account]="commentAccount" [user]="commentUser" i18n-label label="Options" placement="bottom-left auto" |
51 | ></my-user-moderation-dropdown> | 43 | ></my-user-moderation-dropdown> |
52 | </div> | 44 | </div> |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.scss b/client/src/app/+videos/+video-watch/comment/video-comment.component.scss index f6ff376b9..cf33a5b0e 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment.component.scss +++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.scss | |||
@@ -22,144 +22,140 @@ | |||
22 | .right { | 22 | .right { |
23 | width: 100%; | 23 | width: 100%; |
24 | } | 24 | } |
25 | } | ||
25 | 26 | ||
26 | .comment-avatar { | 27 | .comment { |
27 | @include avatar(36px); | 28 | flex-grow: 1; |
28 | } | 29 | // Fix word-wrap with flex |
29 | 30 | min-width: 1px; | |
30 | .comment { | 31 | } |
31 | flex-grow: 1; | ||
32 | // Fix word-wrap with flex | ||
33 | min-width: 1px; | ||
34 | |||
35 | .highlighted-comment { | ||
36 | display: inline-block; | ||
37 | background-color: #F5F5F5; | ||
38 | color: #3d3d3d; | ||
39 | padding: 0 5px; | ||
40 | font-size: 13px; | ||
41 | margin-bottom: 5px; | ||
42 | font-weight: $font-semibold; | ||
43 | border-radius: 3px; | ||
44 | } | ||
45 | 32 | ||
46 | .comment-account-date { | 33 | .highlighted-comment { |
47 | display: flex; | 34 | display: inline-block; |
48 | margin-bottom: 4px; | 35 | background-color: #F5F5F5; |
49 | 36 | color: #3d3d3d; | |
50 | .video-author { | 37 | padding: 0 5px; |
51 | height: 20px; | 38 | font-size: 13px; |
52 | background-color: #888888; | 39 | margin-bottom: 5px; |
53 | border-radius: 12px; | 40 | font-weight: $font-semibold; |
54 | margin-bottom: 2px; | 41 | border-radius: 3px; |
55 | max-width: 100%; | 42 | } |
56 | box-sizing: border-box; | ||
57 | flex-direction: row; | ||
58 | align-items: center; | ||
59 | display: inline-flex; | ||
60 | padding-right: 6px; | ||
61 | padding-left: 6px; | ||
62 | color: white !important; | ||
63 | } | ||
64 | 43 | ||
65 | .comment-account { | 44 | .comment-account-date { |
66 | word-break: break-all; | 45 | display: flex; |
67 | font-weight: 600; | 46 | margin-bottom: 4px; |
68 | font-size: 90%; | 47 | } |
69 | 48 | ||
70 | a { | 49 | .video-author { |
71 | @include disable-default-a-behaviour; | 50 | height: 20px; |
51 | background-color: #888888; | ||
52 | border-radius: 12px; | ||
53 | margin-bottom: 2px; | ||
54 | max-width: 100%; | ||
55 | box-sizing: border-box; | ||
56 | flex-direction: row; | ||
57 | align-items: center; | ||
58 | display: inline-flex; | ||
59 | padding-right: 6px; | ||
60 | padding-left: 6px; | ||
61 | color: white !important; | ||
62 | } | ||
72 | 63 | ||
73 | color: pvar(--mainForegroundColor); | 64 | .comment-account { |
65 | word-break: break-all; | ||
66 | font-weight: 600; | ||
67 | font-size: 90%; | ||
74 | 68 | ||
75 | &:hover { | 69 | a { |
76 | text-decoration: underline; | 70 | @include disable-default-a-behaviour; |
77 | } | ||
78 | } | ||
79 | 71 | ||
80 | .comment-account-fid { | 72 | color: pvar(--mainForegroundColor); |
81 | opacity: .6; | ||
82 | } | ||
83 | } | ||
84 | 73 | ||
85 | .comment-date { | 74 | &:hover { |
86 | font-size: 90%; | 75 | text-decoration: underline; |
87 | color: pvar(--greyForegroundColor); | ||
88 | margin-left: 5px; | ||
89 | text-decoration: none; | ||
90 | |||
91 | &:hover { | ||
92 | text-decoration: underline; | ||
93 | } | ||
94 | } | ||
95 | } | 76 | } |
77 | } | ||
96 | 78 | ||
97 | .comment-html { | 79 | .comment-account-fid { |
98 | @include peertube-word-wrap; | 80 | opacity: .6; |
81 | } | ||
82 | } | ||
99 | 83 | ||
100 | // Mentions | 84 | .comment-date { |
101 | ::ng-deep a { | 85 | font-size: 90%; |
86 | color: pvar(--greyForegroundColor); | ||
87 | margin-left: 5px; | ||
88 | text-decoration: none; | ||
102 | 89 | ||
103 | &:not(.linkified-url) { | 90 | &:hover { |
104 | @include disable-default-a-behaviour; | 91 | text-decoration: underline; |
92 | } | ||
93 | } | ||
105 | 94 | ||
106 | color: pvar(--mainForegroundColor); | 95 | .comment-html { |
96 | @include peertube-word-wrap; | ||
107 | 97 | ||
108 | font-weight: $font-semibold; | 98 | // Mentions |
109 | } | 99 | ::ng-deep a { |
110 | 100 | ||
111 | } | 101 | &:not(.linkified-url) { |
102 | @include disable-default-a-behaviour; | ||
112 | 103 | ||
113 | // Paragraphs | 104 | color: pvar(--mainForegroundColor); |
114 | ::ng-deep p { | ||
115 | margin-bottom: .3rem; | ||
116 | } | ||
117 | 105 | ||
118 | &.comment-html-deleted { | 106 | font-weight: $font-semibold; |
119 | color: pvar(--greyForegroundColor); | ||
120 | margin-bottom: 1rem; | ||
121 | } | ||
122 | } | 107 | } |
123 | 108 | ||
124 | .comment-actions { | 109 | } |
125 | margin-bottom: 10px; | 110 | |
126 | display: flex; | 111 | // Paragraphs |
112 | ::ng-deep p { | ||
113 | margin-bottom: .3rem; | ||
114 | } | ||
127 | 115 | ||
128 | ::ng-deep .dropdown-toggle, | 116 | &.comment-html-deleted { |
129 | .comment-action-reply { | 117 | color: pvar(--greyForegroundColor); |
130 | color: pvar(--greyForegroundColor); | 118 | margin-bottom: 1rem; |
131 | cursor: pointer; | 119 | } |
132 | margin-right: 10px; | 120 | } |
133 | 121 | ||
134 | &:hover, &:active, &:focus, &:focus-visible { | 122 | .comment-actions { |
135 | color: pvar(--mainForegroundColor); | 123 | margin-bottom: 10px; |
136 | } | 124 | display: flex; |
137 | } | ||
138 | 125 | ||
139 | ::ng-deep .action-button { | 126 | ::ng-deep .dropdown-toggle, |
140 | background-color: transparent; | 127 | .comment-action-reply { |
141 | padding: 0; | 128 | color: pvar(--greyForegroundColor); |
142 | font-weight: unset; | 129 | cursor: pointer; |
143 | } | 130 | margin-right: 10px; |
144 | } | ||
145 | 131 | ||
146 | my-video-comment-add { | 132 | &:hover, &:active, &:focus, &:focus-visible { |
147 | ::ng-deep form { | 133 | color: pvar(--mainForegroundColor); |
148 | margin-top: 1rem; | ||
149 | margin-bottom: 0; | ||
150 | } | ||
151 | } | 134 | } |
152 | } | 135 | } |
153 | 136 | ||
154 | .children { | 137 | ::ng-deep .action-button { |
155 | // Reduce avatars size for replies | 138 | background-color: transparent; |
156 | .comment-avatar { | 139 | padding: 0; |
157 | @include avatar(25px); | 140 | font-weight: unset; |
158 | } | 141 | } |
142 | } | ||
159 | 143 | ||
160 | .left { | 144 | my-video-comment-add { |
161 | margin-right: 6px; | 145 | ::ng-deep form { |
162 | } | 146 | margin-top: 1rem; |
147 | margin-bottom: 0; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | .children { | ||
152 | // Reduce avatars size for replies | ||
153 | .comment-avatar { | ||
154 | @include avatar(25px); | ||
155 | } | ||
156 | |||
157 | .left { | ||
158 | margin-right: 6px; | ||
163 | } | 159 | } |
164 | } | 160 | } |
165 | 161 | ||
@@ -170,27 +166,23 @@ | |||
170 | } | 166 | } |
171 | 167 | ||
172 | @media screen and (max-width: 600px) { | 168 | @media screen and (max-width: 600px) { |
173 | .root-comment { | 169 | .children { |
174 | .children { | 170 | margin-left: -20px; |
175 | margin-left: -20px; | ||
176 | 171 | ||
177 | .left { | 172 | .left { |
178 | align-items: flex-start; | 173 | align-items: flex-start; |
179 | 174 | ||
180 | .vertical-border { | 175 | .vertical-border { |
181 | margin-left: 2px; | 176 | margin-left: 2px; |
182 | } | ||
183 | } | 177 | } |
184 | } | 178 | } |
179 | } | ||
185 | 180 | ||
186 | .comment { | 181 | .comment-account-date { |
187 | .comment-account-date { | 182 | flex-direction: column; |
188 | flex-direction: column; | ||
189 | 183 | ||
190 | .comment-date { | 184 | .comment-date { |
191 | margin-left: 0; | 185 | margin-left: 0; |
192 | } | ||
193 | } | ||
194 | } | 186 | } |
195 | } | 187 | } |
196 | } | 188 | } |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.ts b/client/src/app/+videos/+video-watch/comment/video-comment.component.ts index 5c5d72b22..dd3db0c65 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comment.component.ts +++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.ts | |||
@@ -131,10 +131,6 @@ export class VideoCommentComponent implements OnInit, OnChanges { | |||
131 | ) | 131 | ) |
132 | } | 132 | } |
133 | 133 | ||
134 | switchToDefaultAvatar ($event: Event) { | ||
135 | ($event.target as HTMLImageElement).src = Account.GET_DEFAULT_AVATAR_URL() | ||
136 | } | ||
137 | |||
138 | isCommentDisplayed () { | 134 | isCommentDisplayed () { |
139 | // Not deleted | 135 | // Not deleted |
140 | return !this.comment.isDeleted || | 136 | return !this.comment.isDeleted || |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comments.component.html b/client/src/app/+videos/+video-watch/comment/video-comments.component.html index 4a6426d30..9e6fde2e0 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comments.component.html +++ b/client/src/app/+videos/+video-watch/comment/video-comments.component.html | |||
@@ -1,12 +1,7 @@ | |||
1 | <div> | 1 | <div> |
2 | <div class="title-block"> | 2 | <div class="title-block"> |
3 | <h2 class="title-page title-page-single"> | 3 | <h2 class="title-page title-page-single"> |
4 | <ng-container *ngIf="totalNotDeletedComments > 0; then hasComments; else noComments"></ng-container> | 4 | {totalNotDeletedComments, plural, =0 {Comments} =1 {1 Comment} other {{{totalNotDeletedComments}} Comments}} |
5 | <ng-template #hasComments> | ||
6 | <ng-container i18n *ngIf="totalNotDeletedComments === 1; else manyComments">1 Comment</ng-container> | ||
7 | <ng-template i18n #manyComments>{{ totalNotDeletedComments }} Comments</ng-template> | ||
8 | </ng-template> | ||
9 | <ng-template i18n #noComments>Comments</ng-template> | ||
10 | </h2> | 5 | </h2> |
11 | 6 | ||
12 | <my-feed [syndicationItems]="syndicationItems"></my-feed> | 7 | <my-feed [syndicationItems]="syndicationItems"></my-feed> |
@@ -79,15 +74,17 @@ | |||
79 | <span class="glyphicon glyphicon-menu-down"></span> | 74 | <span class="glyphicon glyphicon-menu-down"></span> |
80 | 75 | ||
81 | <ng-container *ngIf="comment.totalRepliesFromVideoAuthor > 0; then hasAuthorComments; else noAuthorComments"></ng-container> | 76 | <ng-container *ngIf="comment.totalRepliesFromVideoAuthor > 0; then hasAuthorComments; else noAuthorComments"></ng-container> |
77 | |||
82 | <ng-template #hasAuthorComments> | 78 | <ng-template #hasAuthorComments> |
83 | <ng-container *ngIf="comment.totalReplies !== comment.totalRepliesFromVideoAuthor; else onlyAuthorComments" i18n> | 79 | <ng-container *ngIf="comment.totalReplies !== comment.totalRepliesFromVideoAuthor; else onlyAuthorComments" i18n> |
84 | View {{ comment.totalReplies }} replies from {{ video?.account?.displayName || 'the author' }} and others | 80 | View {comment.totalReplies, plural, =1 {1 reply} other {{{ comment.totalReplies }} replies}} from {{ video?.account?.displayName || 'the author' }} and others |
85 | </ng-container> | 81 | </ng-container> |
86 | <ng-template i18n #onlyAuthorComments> | 82 | <ng-template i18n #onlyAuthorComments> |
87 | View {{ comment.totalReplies }} replies from {{ video?.account?.displayName || 'the author' }} | 83 | View {comment.totalReplies, plural, =1 {1 reply} other {{{ comment.totalReplies }} replies}} from {{ video?.account?.displayName || 'the author' }} |
88 | </ng-template> | 84 | </ng-template> |
89 | </ng-template> | 85 | </ng-template> |
90 | <ng-template i18n #noAuthorComments>View {{ comment.totalReplies }} replies</ng-template> | 86 | |
87 | <ng-template i18n #noAuthorComments>View {comment.totalReplies, plural, =1 {1 reply} other {{{ comment.totalReplies }} replies}}</ng-template> | ||
91 | 88 | ||
92 | <my-small-loader class="comment-thread-loading ml-1" [loading]="threadLoading[comment.id]"></my-small-loader> | 89 | <my-small-loader class="comment-thread-loading ml-1" [loading]="threadLoading[comment.id]"></my-small-loader> |
93 | </div> | 90 | </div> |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comments.component.scss b/client/src/app/+videos/+video-watch/comment/video-comments.component.scss index df42fae73..e6778e1a9 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comments.component.scss +++ b/client/src/app/+videos/+video-watch/comment/video-comments.component.scss | |||
@@ -27,7 +27,11 @@ | |||
27 | margin-left: 5px; | 27 | margin-left: 5px; |
28 | opacity: 0; | 28 | opacity: 0; |
29 | transition: ease-in .2s opacity; | 29 | transition: ease-in .2s opacity; |
30 | width: 12px; | ||
31 | position: relative; | ||
32 | top: -3px; | ||
30 | } | 33 | } |
34 | |||
31 | &:hover my-feed { | 35 | &:hover my-feed { |
32 | opacity: 1; | 36 | opacity: 1; |
33 | } | 37 | } |
diff --git a/client/src/app/+videos/+video-watch/comment/video-comments.component.ts b/client/src/app/+videos/+video-watch/comment/video-comments.component.ts index d36dd9e34..210236b61 100644 --- a/client/src/app/+videos/+video-watch/comment/video-comments.component.ts +++ b/client/src/app/+videos/+video-watch/comment/video-comments.component.ts | |||
@@ -5,7 +5,6 @@ import { AuthService, ComponentPagination, ConfirmService, hasMoreItems, Notifie | |||
5 | import { HooksService } from '@app/core/plugins/hooks.service' | 5 | import { HooksService } from '@app/core/plugins/hooks.service' |
6 | import { Syndication, VideoDetails } from '@app/shared/shared-main' | 6 | import { Syndication, VideoDetails } from '@app/shared/shared-main' |
7 | import { VideoComment, VideoCommentService, VideoCommentThreadTree } from '@app/shared/shared-video-comment' | 7 | import { VideoComment, VideoCommentService, VideoCommentThreadTree } from '@app/shared/shared-video-comment' |
8 | import { ThisReceiver } from '@angular/compiler' | ||
9 | 8 | ||
10 | @Component({ | 9 | @Component({ |
11 | selector: 'my-video-comments', | 10 | selector: 'my-video-comments', |
diff --git a/client/src/app/+videos/+video-watch/modal/video-support.component.html b/client/src/app/+videos/+video-watch/modal/video-support.component.html deleted file mode 100644 index 935656d23..000000000 --- a/client/src/app/+videos/+video-watch/modal/video-support.component.html +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | <ng-template #modal let-hide="close"> | ||
2 | <div class="modal-header"> | ||
3 | <h4 i18n class="modal-title">Support {{ video.account.displayName }}</h4> | ||
4 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> | ||
5 | </div> | ||
6 | |||
7 | <div class="modal-body" [innerHTML]="videoHTMLSupport"></div> | ||
8 | |||
9 | <div class="modal-footer inputs"> | ||
10 | <input | ||
11 | type="button" role="button" i18n-value value="Maybe later" class="action-button action-button-cancel" | ||
12 | (click)="hide()" (key.enter)="hide()" | ||
13 | > | ||
14 | </div> | ||
15 | </ng-template> | ||
diff --git a/client/src/app/+videos/+video-watch/modal/video-support.component.scss b/client/src/app/+videos/+video-watch/modal/video-support.component.scss deleted file mode 100644 index 184e09027..000000000 --- a/client/src/app/+videos/+video-watch/modal/video-support.component.scss +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | .action-button-cancel { | ||
2 | margin-right: 0 !important; | ||
3 | } | ||
diff --git a/client/src/app/+videos/+video-watch/modal/video-support.component.ts b/client/src/app/+videos/+video-watch/modal/video-support.component.ts deleted file mode 100644 index bd5290a72..000000000 --- a/client/src/app/+videos/+video-watch/modal/video-support.component.ts +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | import { Component, Input, ViewChild } from '@angular/core' | ||
2 | import { MarkdownService } from '@app/core' | ||
3 | import { VideoDetails } from '@app/shared/shared-main' | ||
4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'my-video-support', | ||
8 | templateUrl: './video-support.component.html', | ||
9 | styleUrls: [ './video-support.component.scss' ] | ||
10 | }) | ||
11 | export class VideoSupportComponent { | ||
12 | @Input() video: VideoDetails = null | ||
13 | |||
14 | @ViewChild('modal', { static: true }) modal: NgbModal | ||
15 | |||
16 | videoHTMLSupport = '' | ||
17 | |||
18 | constructor ( | ||
19 | private markdownService: MarkdownService, | ||
20 | private modalService: NgbModal | ||
21 | ) { } | ||
22 | |||
23 | show () { | ||
24 | const modalRef = this.modalService.open(this.modal, { centered: true }) | ||
25 | |||
26 | this.markdownService.enhancedMarkdownToHTML(this.video.support) | ||
27 | .then(r => this.videoHTMLSupport = r) | ||
28 | |||
29 | return modalRef | ||
30 | } | ||
31 | } | ||
diff --git a/client/src/app/+videos/+video-watch/player-styles.component.scss b/client/src/app/+videos/+video-watch/player-styles.component.scss new file mode 100644 index 000000000..7f1442a59 --- /dev/null +++ b/client/src/app/+videos/+video-watch/player-styles.component.scss | |||
@@ -0,0 +1,4 @@ | |||
1 | @import 'node_modules/video.js/dist/video-js'; | ||
2 | |||
3 | $assets-path: '../../assets/'; | ||
4 | @import '../../../sass/player/index'; | ||
diff --git a/client/src/app/+videos/+video-watch/player-styles.component.ts b/client/src/app/+videos/+video-watch/player-styles.component.ts new file mode 100644 index 000000000..9b1672a8c --- /dev/null +++ b/client/src/app/+videos/+video-watch/player-styles.component.ts | |||
@@ -0,0 +1,15 @@ | |||
1 | import { Component, ViewEncapsulation } from '@angular/core' | ||
2 | |||
3 | /* | ||
4 | * Allows to lazy load global player styles in the watch component | ||
5 | */ | ||
6 | |||
7 | @Component({ | ||
8 | selector: 'my-player-styles', | ||
9 | template: '', | ||
10 | styleUrls: [ './player-styles.component.scss' ], | ||
11 | // tslint:disable:use-component-view-encapsulation | ||
12 | encapsulation: ViewEncapsulation.None | ||
13 | }) | ||
14 | export class PlayerStylesComponent { | ||
15 | } | ||
diff --git a/client/src/app/+videos/+video-watch/recommendations/recent-videos-recommendation.service.ts b/client/src/app/+videos/+video-watch/recommendations/recent-videos-recommendation.service.ts index 29fa268f4..2a851f13a 100644 --- a/client/src/app/+videos/+video-watch/recommendations/recent-videos-recommendation.service.ts +++ b/client/src/app/+videos/+video-watch/recommendations/recent-videos-recommendation.service.ts | |||
@@ -61,7 +61,7 @@ export class RecentVideosRecommendationService implements RecommendationService | |||
61 | componentPagination: pagination, | 61 | componentPagination: pagination, |
62 | advancedSearch: new AdvancedSearch({ | 62 | advancedSearch: new AdvancedSearch({ |
63 | tagsOneOf: recommendation.tags.join(','), | 63 | tagsOneOf: recommendation.tags.join(','), |
64 | sort: '-createdAt', | 64 | sort: '-publishedAt', |
65 | searchTarget: 'local', | 65 | searchTarget: 'local', |
66 | nsfw: user.nsfwPolicy | 66 | nsfw: user.nsfwPolicy |
67 | ? this.videos.nsfwPolicyToParam(user.nsfwPolicy) | 67 | ? this.videos.nsfwPolicyToParam(user.nsfwPolicy) |
diff --git a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.html b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.html index 3c7c679b8..e0e9f92e7 100644 --- a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.html +++ b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.html | |||
@@ -1,4 +1,4 @@ | |||
1 | <div class="other-videos"> | 1 | <div class="other-videos" [ngClass]="{ 'display-as-row': displayAsRow }"> |
2 | <ng-container *ngIf="hasVideos$ | async"> | 2 | <ng-container *ngIf="hasVideos$ | async"> |
3 | <div class="title-page-container"> | 3 | <div class="title-page-container"> |
4 | <h2 i18n class="title-page title-page-single"> | 4 | <h2 i18n class="title-page title-page-single"> |
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | <ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count"> | 15 | <ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count"> |
16 | <my-video-miniature | 16 | <my-video-miniature |
17 | [displayOptions]="displayOptions" [video]="video" [user]="userMiniature" | 17 | [displayOptions]="displayOptions" [video]="video" [user]="userMiniature" [displayAsRow]="displayAsRow" |
18 | (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()" (videoAccountMuted)="onVideoRemoved()"> | 18 | (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()" (videoAccountMuted)="onVideoRemoved()"> |
19 | </my-video-miniature> | 19 | </my-video-miniature> |
20 | 20 | ||
diff --git a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.scss b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.scss index b278c9654..c9fae6f27 100644 --- a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.scss +++ b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.scss | |||
@@ -1,3 +1,6 @@ | |||
1 | @import '_variables'; | ||
2 | @import '_mixins'; | ||
3 | |||
1 | .title-page-container { | 4 | .title-page-container { |
2 | display: flex; | 5 | display: flex; |
3 | justify-content: space-between; | 6 | justify-content: space-between; |
@@ -11,6 +14,10 @@ | |||
11 | } | 14 | } |
12 | } | 15 | } |
13 | 16 | ||
17 | .title-page { | ||
18 | margin-top: 0; | ||
19 | } | ||
20 | |||
14 | .title-page-autoplay { | 21 | .title-page-autoplay { |
15 | display: flex; | 22 | display: flex; |
16 | width: max-content; | 23 | width: max-content; |
@@ -29,3 +36,29 @@ | |||
29 | hr { | 36 | hr { |
30 | margin-top: 0; | 37 | margin-top: 0; |
31 | } | 38 | } |
39 | |||
40 | my-video-miniature { | ||
41 | display: block; | ||
42 | } | ||
43 | |||
44 | .other-videos:not(.display-as-row) my-video-miniature { | ||
45 | min-width: $video-thumbnail-medium-width; | ||
46 | max-width: $video-thumbnail-medium-width; | ||
47 | } | ||
48 | |||
49 | .display-as-row { | ||
50 | my-video-miniature { | ||
51 | margin-bottom: 20px; | ||
52 | } | ||
53 | |||
54 | hr { | ||
55 | display: none; | ||
56 | } | ||
57 | |||
58 | @media screen and (max-width: $mobile-view) { | ||
59 | my-video-miniature { | ||
60 | margin-bottom: 10px; | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
diff --git a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.ts b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.ts index a1c8e0661..89b9c01b6 100644 --- a/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.ts +++ b/client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.ts | |||
@@ -16,6 +16,8 @@ import { RecommendedVideosStore } from './recommended-videos.store' | |||
16 | export class RecommendedVideosComponent implements OnInit, OnChanges { | 16 | export class RecommendedVideosComponent implements OnInit, OnChanges { |
17 | @Input() inputRecommendation: RecommendationInfo | 17 | @Input() inputRecommendation: RecommendationInfo |
18 | @Input() playlist: VideoPlaylist | 18 | @Input() playlist: VideoPlaylist |
19 | @Input() displayAsRow: boolean | ||
20 | |||
19 | @Output() gotRecommendations = new EventEmitter<Video[]>() | 21 | @Output() gotRecommendations = new EventEmitter<Video[]>() |
20 | 22 | ||
21 | autoPlayNextVideo: boolean | 23 | autoPlayNextVideo: boolean |
diff --git a/client/src/app/+videos/+video-watch/video-avatar-channel.component.html b/client/src/app/+videos/+video-watch/video-avatar-channel.component.html new file mode 100644 index 000000000..a02373f2d --- /dev/null +++ b/client/src/app/+videos/+video-watch/video-avatar-channel.component.html | |||
@@ -0,0 +1,21 @@ | |||
1 | <div class="wrapper" [ngClass]="'avatar-' + size"> | ||
2 | <ng-container *ngIf="!isChannelAvatarNull() && !genericChannel"> | ||
3 | <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle"> | ||
4 | <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" /> | ||
5 | </a> | ||
6 | |||
7 | <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> | ||
8 | </ng-container> | ||
9 | |||
10 | <ng-container *ngIf="!isChannelAvatarNull() && genericChannel"> | ||
11 | <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> | ||
12 | |||
13 | <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle"> | ||
14 | <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" /> | ||
15 | </a> | ||
16 | </ng-container> | ||
17 | |||
18 | <ng-container *ngIf="isChannelAvatarNull()"> | ||
19 | <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> | ||
20 | </ng-container> | ||
21 | </div> | ||
diff --git a/client/src/app/+videos/+video-watch/video-avatar-channel.component.scss b/client/src/app/+videos/+video-watch/video-avatar-channel.component.scss new file mode 100644 index 000000000..4998e85fa --- /dev/null +++ b/client/src/app/+videos/+video-watch/video-avatar-channel.component.scss | |||
@@ -0,0 +1,44 @@ | |||
1 | @import '_mixins'; | ||
2 | |||
3 | .wrapper { | ||
4 | $avatar-size: 35px; | ||
5 | |||
6 | width: $avatar-size; | ||
7 | height: $avatar-size; | ||
8 | position: relative; | ||
9 | margin-right: 5px; | ||
10 | margin-bottom: 5px; | ||
11 | |||
12 | &.avatar-sm { | ||
13 | width: 28px; | ||
14 | height: 28px; | ||
15 | margin-bottom: 3px; | ||
16 | } | ||
17 | |||
18 | a { | ||
19 | @include disable-outline; | ||
20 | } | ||
21 | |||
22 | a img { | ||
23 | height: 100%; | ||
24 | object-fit: cover; | ||
25 | position: absolute; | ||
26 | top:50%; | ||
27 | left:50%; | ||
28 | transform: translate(-50%,-50%); | ||
29 | border-radius: 5px; | ||
30 | |||
31 | &:not(.channel-avatar) { | ||
32 | border-radius: 50%; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | a:nth-of-type(2) img { | ||
37 | height: 60%; | ||
38 | width: 60%; | ||
39 | border: 2px solid pvar(--mainBackgroundColor); | ||
40 | transform: translateX(15%); | ||
41 | position: relative; | ||
42 | background-color: pvar(--mainBackgroundColor); | ||
43 | } | ||
44 | } | ||
diff --git a/client/src/app/+videos/+video-watch/video-avatar-channel.component.ts b/client/src/app/+videos/+video-watch/video-avatar-channel.component.ts new file mode 100644 index 000000000..0b6e796df --- /dev/null +++ b/client/src/app/+videos/+video-watch/video-avatar-channel.component.ts | |||
@@ -0,0 +1,27 @@ | |||
1 | import { Component, Input, OnInit } from '@angular/core' | ||
2 | import { Video } from '@app/shared/shared-main/video' | ||
3 | |||
4 | @Component({ | ||
5 | selector: 'my-video-avatar-channel', | ||
6 | templateUrl: './video-avatar-channel.component.html', | ||
7 | styleUrls: [ './video-avatar-channel.component.scss' ] | ||
8 | }) | ||
9 | export class VideoAvatarChannelComponent implements OnInit { | ||
10 | @Input() video: Video | ||
11 | @Input() byAccount: string | ||
12 | |||
13 | @Input() size: 'md' | 'sm' = 'md' | ||
14 | @Input() genericChannel: boolean | ||
15 | |||
16 | channelLinkTitle = '' | ||
17 | accountLinkTitle = '' | ||
18 | |||
19 | ngOnInit () { | ||
20 | this.channelLinkTitle = $localize`${this.video.account.name} (channel page)` | ||
21 | this.accountLinkTitle = $localize`${this.video.byAccount} (account page)` | ||
22 | } | ||
23 | |||
24 | isChannelAvatarNull () { | ||
25 | return this.video.channel.avatar === null | ||
26 | } | ||
27 | } | ||
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 b17f898ce..eadb2148a 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.html +++ b/client/src/app/+videos/+video-watch/video-watch.component.html | |||
@@ -16,6 +16,8 @@ | |||
16 | [playlist]="playlist" class="playlist" | 16 | [playlist]="playlist" class="playlist" |
17 | (videoFound)="onPlaylistVideoFound($event)" | 17 | (videoFound)="onPlaylistVideoFound($event)" |
18 | ></my-video-watch-playlist> | 18 | ></my-video-watch-playlist> |
19 | |||
20 | <my-plugin-placeholder pluginId="player-next"></my-plugin-placeholder> | ||
19 | </div> | 21 | </div> |
20 | 22 | ||
21 | <div class="row"> | 23 | <div class="row"> |
@@ -142,7 +144,7 @@ | |||
142 | <ng-container *ngIf="isUserLoggedIn()"> | 144 | <ng-container *ngIf="isUserLoggedIn()"> |
143 | <my-video-actions-dropdown | 145 | <my-video-actions-dropdown |
144 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions" | 146 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions" |
145 | [displayOptions]="videoActionsOptions" (videoRemoved)="onVideoRemoved()" (modalOpened)="onModalOpened()" | 147 | [displayOptions]="videoActionsOptions" (videoRemoved)="onVideoRemoved()" |
146 | ></my-video-actions-dropdown> | 148 | ></my-video-actions-dropdown> |
147 | </ng-container> | 149 | </ng-container> |
148 | </div> | 150 | </div> |
@@ -230,8 +232,8 @@ | |||
230 | </div> | 232 | </div> |
231 | 233 | ||
232 | <div *ngIf="video.isLocal === false" class="video-attribute"> | 234 | <div *ngIf="video.isLocal === false" class="video-attribute"> |
233 | <span i18n class="video-attribute-label">Origin instance</span> | 235 | <span i18n class="video-attribute-label">Origin</span> |
234 | <a class="video-attribute-value" target="_blank" rel="noopener noreferrer" [href]="video.originInstanceUrl">{{ video.originInstanceHost }}</a> | 236 | <a class="video-attribute-value" target="_blank" rel="noopener noreferrer" [href]="getVideoUrl()">{{ video.originInstanceHost }}</a> |
235 | </div> | 237 | </div> |
236 | 238 | ||
237 | <div *ngIf="!!video.originallyPublishedAt" class="video-attribute"> | 239 | <div *ngIf="!!video.originallyPublishedAt" class="video-attribute"> |
@@ -289,6 +291,7 @@ | |||
289 | </div> | 291 | </div> |
290 | 292 | ||
291 | <my-recommended-videos | 293 | <my-recommended-videos |
294 | [displayAsRow]="displayOtherVideosAsRow()" | ||
292 | [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" | 295 | [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" |
293 | [playlist]="playlist" | 296 | [playlist]="playlist" |
294 | (gotRecommendations)="onRecommendations($event)" | 297 | (gotRecommendations)="onRecommendations($event)" |
@@ -313,6 +316,8 @@ | |||
313 | </div> | 316 | </div> |
314 | 317 | ||
315 | <ng-container *ngIf="video !== null"> | 318 | <ng-container *ngIf="video !== null"> |
316 | <my-video-support #videoSupportModal [video]="video"></my-video-support> | 319 | <my-support-modal #supportModal [video]="video"></my-support-modal> |
317 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share> | 320 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share> |
318 | </ng-container> | 321 | </ng-container> |
322 | |||
323 | <my-player-styles></my-player-styles> | ||
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 555126cbc..e8ad10a11 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.scss +++ b/client/src/app/+videos/+video-watch/video-watch.component.scss | |||
@@ -3,7 +3,7 @@ | |||
3 | @import '_bootstrap-variables'; | 3 | @import '_bootstrap-variables'; |
4 | @import '_miniature'; | 4 | @import '_miniature'; |
5 | 5 | ||
6 | $player-factor: 1.7; // 16/9 | 6 | $player-factor: 16/9; |
7 | $video-info-margin-left: 44px; | 7 | $video-info-margin-left: 44px; |
8 | 8 | ||
9 | @function getPlayerHeight($width){ | 9 | @function getPlayerHeight($width){ |
@@ -179,12 +179,6 @@ $video-info-margin-left: 44px; | |||
179 | &:hover { | 179 | &:hover { |
180 | opacity: 0.8; | 180 | opacity: 0.8; |
181 | } | 181 | } |
182 | |||
183 | img { | ||
184 | @include avatar(18px); | ||
185 | |||
186 | margin: -2px 5px 0 0; | ||
187 | } | ||
188 | } | 182 | } |
189 | 183 | ||
190 | .video-info-channel-left { | 184 | .video-info-channel-left { |
@@ -212,11 +206,6 @@ $video-info-margin-left: 44px; | |||
212 | } | 206 | } |
213 | } | 207 | } |
214 | 208 | ||
215 | my-feed { | ||
216 | margin-left: 5px; | ||
217 | margin-top: 1px; | ||
218 | } | ||
219 | |||
220 | .video-actions-rates { | 209 | .video-actions-rates { |
221 | margin: 0 0 10px 0; | 210 | margin: 0 0 10px 0; |
222 | align-items: start; | 211 | align-items: start; |
@@ -413,37 +402,12 @@ $video-info-margin-left: 44px; | |||
413 | } | 402 | } |
414 | } | 403 | } |
415 | } | 404 | } |
405 | } | ||
416 | 406 | ||
417 | ::ng-deep .other-videos { | 407 | my-recommended-videos { |
418 | padding-left: 15px; | 408 | display: block; |
419 | min-width: $video-miniature-width; | 409 | padding-left: 15px; |
420 | 410 | min-width: 250px; | |
421 | @media screen and (min-width: 1800px - (3* $video-miniature-width)) { | ||
422 | width: min-content; | ||
423 | } | ||
424 | |||
425 | .title-page { | ||
426 | margin: 0 !important; | ||
427 | } | ||
428 | |||
429 | .video-miniature { | ||
430 | display: flex; | ||
431 | width: max-content; | ||
432 | height: 100%; | ||
433 | padding-bottom: 20px; | ||
434 | flex-wrap: wrap; | ||
435 | } | ||
436 | |||
437 | .video-bottom { | ||
438 | @media screen and (max-width: 1800px - (3* $video-miniature-width)) { | ||
439 | margin-left: 1rem; | ||
440 | } | ||
441 | @media screen and (max-width: 500px) { | ||
442 | margin-left: 0; | ||
443 | margin-top: .5rem; | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | } | 411 | } |
448 | 412 | ||
449 | my-video-comments { | 413 | my-video-comments { |
@@ -537,6 +501,7 @@ my-video-comments { | |||
537 | } | 501 | } |
538 | } | 502 | } |
539 | 503 | ||
504 | // Use the same breakpoint than in the typescript component to display the other video miniatures as row | ||
540 | @media screen and (max-width: 1100px) { | 505 | @media screen and (max-width: 1100px) { |
541 | #video-wrapper { | 506 | #video-wrapper { |
542 | flex-direction: column; | 507 | flex-direction: column; |
@@ -549,15 +514,10 @@ my-video-comments { | |||
549 | 514 | ||
550 | .video-bottom { | 515 | .video-bottom { |
551 | flex-direction: column; | 516 | flex-direction: column; |
517 | } | ||
552 | 518 | ||
553 | ::ng-deep .other-videos { | 519 | my-recommended-videos { |
554 | padding-left: 0 !important; | 520 | padding-left: 0; |
555 | |||
556 | ::ng-deep .video-miniature { | ||
557 | flex-direction: row; | ||
558 | width: auto; | ||
559 | } | ||
560 | } | ||
561 | } | 521 | } |
562 | } | 522 | } |
563 | 523 | ||
@@ -579,10 +539,6 @@ my-video-comments { | |||
579 | } | 539 | } |
580 | } | 540 | } |
581 | 541 | ||
582 | ::ng-deep .other-videos .video-miniature { | ||
583 | flex-direction: column; | ||
584 | } | ||
585 | |||
586 | .privacy-concerns { | 542 | .privacy-concerns { |
587 | width: 100%; | 543 | width: 100%; |
588 | } | 544 | } |
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 7a98cab3b..366e9bb57 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts | |||
@@ -21,6 +21,7 @@ import { RedirectService } from '@app/core/routing/redirect.service' | |||
21 | import { isXPercentInViewport, scrollToTop } from '@app/helpers' | 21 | import { isXPercentInViewport, scrollToTop } from '@app/helpers' |
22 | import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' | 22 | import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' |
23 | import { VideoShareComponent } from '@app/shared/shared-share-modal' | 23 | import { VideoShareComponent } from '@app/shared/shared-share-modal' |
24 | import { SupportModalComponent } from '@app/shared/shared-support-modal' | ||
24 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' | 25 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' |
25 | import { VideoActionsDisplayType, VideoDownloadComponent } from '@app/shared/shared-video-miniature' | 26 | import { VideoActionsDisplayType, VideoDownloadComponent } from '@app/shared/shared-video-miniature' |
26 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' | 27 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' |
@@ -28,7 +29,12 @@ import { MetaService } from '@ngx-meta/core' | |||
28 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 29 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
29 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | 30 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' |
30 | import { ServerConfig, ServerErrorCode, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '@shared/models' | 31 | import { ServerConfig, ServerErrorCode, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '@shared/models' |
31 | import { getStoredP2PEnabled, getStoredTheater } from '../../../assets/player/peertube-player-local-storage' | 32 | import { |
33 | cleanupVideoWatch, | ||
34 | getStoredP2PEnabled, | ||
35 | getStoredTheater, | ||
36 | getStoredVideoWatchHistory | ||
37 | } from '../../../assets/player/peertube-player-local-storage' | ||
32 | import { | 38 | import { |
33 | CustomizationOptions, | 39 | CustomizationOptions, |
34 | P2PMediaLoaderOptions, | 40 | P2PMediaLoaderOptions, |
@@ -39,7 +45,6 @@ import { | |||
39 | } from '../../../assets/player/peertube-player-manager' | 45 | } from '../../../assets/player/peertube-player-manager' |
40 | import { isWebRTCDisabled, timeToInt } from '../../../assets/player/utils' | 46 | import { isWebRTCDisabled, timeToInt } from '../../../assets/player/utils' |
41 | import { environment } from '../../../environments/environment' | 47 | import { environment } from '../../../environments/environment' |
42 | import { VideoSupportComponent } from './modal/video-support.component' | ||
43 | import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' | 48 | import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' |
44 | 49 | ||
45 | type URLOptions = CustomizationOptions & { playerMode: PlayerMode } | 50 | type URLOptions = CustomizationOptions & { playerMode: PlayerMode } |
@@ -54,7 +59,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
54 | 59 | ||
55 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent | 60 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent |
56 | @ViewChild('videoShareModal') videoShareModal: VideoShareComponent | 61 | @ViewChild('videoShareModal') videoShareModal: VideoShareComponent |
57 | @ViewChild('videoSupportModal') videoSupportModal: VideoSupportComponent | 62 | @ViewChild('supportModal') supportModal: SupportModalComponent |
58 | @ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent | 63 | @ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent |
59 | @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent | 64 | @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent |
60 | 65 | ||
@@ -195,6 +200,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
195 | this.theaterEnabled = getStoredTheater() | 200 | this.theaterEnabled = getStoredTheater() |
196 | 201 | ||
197 | this.hooks.runAction('action:video-watch.init', 'video-watch') | 202 | this.hooks.runAction('action:video-watch.init', 'video-watch') |
203 | |||
204 | setTimeout(cleanupVideoWatch, 1500) // Run in timeout to ensure we're not blocking the UI | ||
198 | } | 205 | } |
199 | 206 | ||
200 | ngOnDestroy () { | 207 | ngOnDestroy () { |
@@ -277,23 +284,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
277 | } | 284 | } |
278 | 285 | ||
279 | showSupportModal () { | 286 | showSupportModal () { |
280 | // Check video was playing before opening support modal | 287 | this.supportModal.show() |
281 | const isVideoPlaying = this.isPlaying() | ||
282 | |||
283 | this.pausePlayer() | ||
284 | |||
285 | const modalRef = this.videoSupportModal.show() | ||
286 | |||
287 | modalRef.result.then(() => { | ||
288 | if (isVideoPlaying) { | ||
289 | this.resumePlayer() | ||
290 | } | ||
291 | }) | ||
292 | } | 288 | } |
293 | 289 | ||
294 | showShareModal () { | 290 | showShareModal () { |
295 | this.pausePlayer() | ||
296 | |||
297 | this.videoShareModal.show(this.currentTime, this.videoWatchPlaylist.currentPlaylistPosition) | 291 | this.videoShareModal.show(this.currentTime, this.videoWatchPlaylist.currentPlaylistPosition) |
298 | } | 292 | } |
299 | 293 | ||
@@ -301,6 +295,13 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
301 | return this.authService.isLoggedIn() | 295 | return this.authService.isLoggedIn() |
302 | } | 296 | } |
303 | 297 | ||
298 | getVideoUrl () { | ||
299 | if (!this.video.url) { | ||
300 | return this.video.originInstanceUrl + VideoDetails.buildClientUrl(this.video.uuid) | ||
301 | } | ||
302 | return this.video.url | ||
303 | } | ||
304 | |||
304 | getVideoTags () { | 305 | getVideoTags () { |
305 | if (!this.video || Array.isArray(this.video.tags) === false) return [] | 306 | if (!this.video || Array.isArray(this.video.tags) === false) return [] |
306 | 307 | ||
@@ -316,10 +317,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
316 | } | 317 | } |
317 | } | 318 | } |
318 | 319 | ||
319 | onModalOpened () { | ||
320 | this.pausePlayer() | ||
321 | } | ||
322 | |||
323 | onVideoRemoved () { | 320 | onVideoRemoved () { |
324 | this.redirectService.redirectToHomepage() | 321 | this.redirectService.redirectToHomepage() |
325 | } | 322 | } |
@@ -396,6 +393,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
396 | this.loadVideo(videoId) | 393 | this.loadVideo(videoId) |
397 | } | 394 | } |
398 | 395 | ||
396 | displayOtherVideosAsRow () { | ||
397 | // Use the same value as in the SASS file | ||
398 | return this.screenService.getWindowInnerWidth() <= 1100 | ||
399 | } | ||
400 | |||
399 | private loadVideo (videoId: string) { | 401 | private loadVideo (videoId: string) { |
400 | // Video did not change | 402 | // Video did not change |
401 | if (this.video && this.video.uuid === videoId) return | 403 | if (this.video && this.video.uuid === videoId) return |
@@ -570,7 +572,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
570 | this.setOpenGraphTags() | 572 | this.setOpenGraphTags() |
571 | this.checkUserRating() | 573 | this.checkUserRating() |
572 | 574 | ||
573 | this.hooks.runAction('action:video-watch.video.loaded', 'video-watch', { videojs }) | 575 | const hookOptions = { |
576 | videojs, | ||
577 | video: this.video, | ||
578 | playlist: this.playlist | ||
579 | } | ||
580 | this.hooks.runAction('action:video-watch.video.loaded', 'video-watch', hookOptions) | ||
574 | } | 581 | } |
575 | 582 | ||
576 | private async buildPlayer (urlOptions: URLOptions) { | 583 | private async buildPlayer (urlOptions: URLOptions) { |
@@ -768,9 +775,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
768 | const getStartTime = () => { | 775 | const getStartTime = () => { |
769 | const byUrl = urlOptions.startTime !== undefined | 776 | const byUrl = urlOptions.startTime !== undefined |
770 | const byHistory = video.userHistory && (!this.playlist || urlOptions.resume !== undefined) | 777 | const byHistory = video.userHistory && (!this.playlist || urlOptions.resume !== undefined) |
778 | const byLocalStorage = getStoredVideoWatchHistory(video.uuid) | ||
771 | 779 | ||
772 | if (byUrl) return timeToInt(urlOptions.startTime) | 780 | if (byUrl) return timeToInt(urlOptions.startTime) |
773 | if (byHistory) return video.userHistory.currentTime | 781 | if (byHistory) return video.userHistory.currentTime |
782 | if (byLocalStorage) return byLocalStorage.duration | ||
774 | 783 | ||
775 | return 0 | 784 | return 0 |
776 | } | 785 | } |
@@ -815,6 +824,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
815 | ? this.videoService.getVideoViewUrl(video.uuid) | 824 | ? this.videoService.getVideoViewUrl(video.uuid) |
816 | : null, | 825 | : null, |
817 | embedUrl: video.embedUrl, | 826 | embedUrl: video.embedUrl, |
827 | embedTitle: video.name, | ||
818 | 828 | ||
819 | isLive: video.isLive, | 829 | isLive: video.isLive, |
820 | 830 | ||
@@ -827,7 +837,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
827 | 837 | ||
828 | serverUrl: environment.apiUrl, | 838 | serverUrl: environment.apiUrl, |
829 | 839 | ||
830 | videoCaptions: playerCaptions | 840 | videoCaptions: playerCaptions, |
841 | |||
842 | videoUUID: video.uuid | ||
831 | }, | 843 | }, |
832 | 844 | ||
833 | webtorrent: { | 845 | webtorrent: { |
@@ -867,24 +879,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
867 | return { playerMode: mode, playerOptions: options } | 879 | return { playerMode: mode, playerOptions: options } |
868 | } | 880 | } |
869 | 881 | ||
870 | private pausePlayer () { | ||
871 | if (!this.player) return | ||
872 | |||
873 | this.player.pause() | ||
874 | } | ||
875 | |||
876 | private resumePlayer () { | ||
877 | if (!this.player) return | ||
878 | |||
879 | this.player.play() | ||
880 | } | ||
881 | |||
882 | private isPlaying () { | ||
883 | if (!this.player) return | ||
884 | |||
885 | return !this.player.paused() | ||
886 | } | ||
887 | |||
888 | private async subscribeToLiveEventsIfNeeded (oldVideo: VideoDetails, newVideo: VideoDetails) { | 882 | private async subscribeToLiveEventsIfNeeded (oldVideo: VideoDetails, newVideo: VideoDetails) { |
889 | if (!this.liveVideosSub) { | 883 | if (!this.liveVideosSub) { |
890 | this.liveVideosSub = this.buildLiveEventsSubscription() | 884 | this.liveVideosSub = this.buildLiveEventsSubscription() |
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 fbda9b9c4..cf6afd852 100644 --- a/client/src/app/+videos/+video-watch/video-watch.module.ts +++ b/client/src/app/+videos/+video-watch/video-watch.module.ts | |||
@@ -4,6 +4,7 @@ import { SharedGlobalIconModule } from '@app/shared/shared-icons' | |||
4 | import { SharedMainModule } from '@app/shared/shared-main' | 4 | import { SharedMainModule } from '@app/shared/shared-main' |
5 | import { SharedModerationModule } from '@app/shared/shared-moderation' | 5 | import { SharedModerationModule } from '@app/shared/shared-moderation' |
6 | import { SharedShareModal } from '@app/shared/shared-share-modal' | 6 | import { SharedShareModal } from '@app/shared/shared-share-modal' |
7 | import { SharedSupportModal } from '@app/shared/shared-support-modal' | ||
7 | import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription' | 8 | import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription' |
8 | import { SharedVideoModule } from '@app/shared/shared-video' | 9 | import { SharedVideoModule } from '@app/shared/shared-video' |
9 | import { SharedVideoCommentModule } from '@app/shared/shared-video-comment' | 10 | import { SharedVideoCommentModule } from '@app/shared/shared-video-comment' |
@@ -13,12 +14,14 @@ import { VideoCommentService } from '../../shared/shared-video-comment/video-com | |||
13 | import { VideoCommentAddComponent } from './comment/video-comment-add.component' | 14 | import { VideoCommentAddComponent } from './comment/video-comment-add.component' |
14 | import { VideoCommentComponent } from './comment/video-comment.component' | 15 | import { VideoCommentComponent } from './comment/video-comment.component' |
15 | import { VideoCommentsComponent } from './comment/video-comments.component' | 16 | import { VideoCommentsComponent } from './comment/video-comments.component' |
16 | import { VideoSupportComponent } from './modal/video-support.component' | 17 | import { PlayerStylesComponent } from './player-styles.component' |
17 | import { RecommendationsModule } from './recommendations/recommendations.module' | 18 | import { RecommendationsModule } from './recommendations/recommendations.module' |
18 | import { TimestampRouteTransformerDirective } from './timestamp-route-transformer.directive' | 19 | import { TimestampRouteTransformerDirective } from './timestamp-route-transformer.directive' |
19 | import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' | 20 | import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' |
20 | import { VideoWatchRoutingModule } from './video-watch-routing.module' | 21 | import { VideoWatchRoutingModule } from './video-watch-routing.module' |
21 | import { VideoWatchComponent } from './video-watch.component' | 22 | import { VideoWatchComponent } from './video-watch.component' |
23 | import { SharedAccountAvatarModule } from '../../shared/shared-account-avatar/shared-account-avatar.module' | ||
24 | import { VideoAvatarChannelComponent } from './video-avatar-channel.component' | ||
22 | 25 | ||
23 | @NgModule({ | 26 | @NgModule({ |
24 | imports: [ | 27 | imports: [ |
@@ -34,20 +37,25 @@ import { VideoWatchComponent } from './video-watch.component' | |||
34 | SharedGlobalIconModule, | 37 | SharedGlobalIconModule, |
35 | SharedVideoCommentModule, | 38 | SharedVideoCommentModule, |
36 | SharedShareModal, | 39 | SharedShareModal, |
37 | SharedVideoModule | 40 | SharedVideoModule, |
41 | SharedSupportModal, | ||
42 | SharedAccountAvatarModule | ||
38 | ], | 43 | ], |
39 | 44 | ||
40 | declarations: [ | 45 | declarations: [ |
41 | VideoWatchComponent, | 46 | VideoWatchComponent, |
42 | VideoWatchPlaylistComponent, | 47 | VideoWatchPlaylistComponent, |
43 | 48 | ||
44 | VideoSupportComponent, | ||
45 | VideoCommentsComponent, | 49 | VideoCommentsComponent, |
46 | VideoCommentAddComponent, | 50 | VideoCommentAddComponent, |
47 | VideoCommentComponent, | 51 | VideoCommentComponent, |
52 | VideoAvatarChannelComponent, | ||
53 | |||
54 | VideoAvatarChannelComponent, | ||
48 | 55 | ||
49 | TimestampRouteTransformerDirective, | 56 | TimestampRouteTransformerDirective, |
50 | TimestampRouteTransformerDirective | 57 | |
58 | PlayerStylesComponent | ||
51 | ], | 59 | ], |
52 | 60 | ||
53 | exports: [ | 61 | exports: [ |
diff --git a/client/src/app/+videos/video-list/overview/video-overview.component.html b/client/src/app/+videos/video-list/overview/video-overview.component.html index ca986c634..639a96c43 100644 --- a/client/src/app/+videos/video-list/overview/video-overview.component.html +++ b/client/src/app/+videos/video-list/overview/video-overview.component.html | |||
@@ -14,7 +14,7 @@ | |||
14 | </h1> | 14 | </h1> |
15 | 15 | ||
16 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> | 16 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> |
17 | <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="true"> | 17 | <my-video-miniature [video]="video" [user]="userMiniature" [displayVideoActions]="true"> |
18 | </my-video-miniature> | 18 | </my-video-miniature> |
19 | </div> | 19 | </div> |
20 | </div> | 20 | </div> |
@@ -25,7 +25,7 @@ | |||
25 | </h2> | 25 | </h2> |
26 | 26 | ||
27 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> | 27 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> |
28 | <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="true"> | 28 | <my-video-miniature [video]="video" [user]="userMiniature" [displayVideoActions]="true"> |
29 | </my-video-miniature> | 29 | </my-video-miniature> |
30 | </div> | 30 | </div> |
31 | </div> | 31 | </div> |
@@ -40,7 +40,7 @@ | |||
40 | </div> | 40 | </div> |
41 | 41 | ||
42 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> | 42 | <div class="video-wrapper" *ngFor="let video of buildVideos(object.videos)"> |
43 | <my-video-miniature [video]="video" [fitWidth]="true" [user]="userMiniature" [displayVideoActions]="true"> | 43 | <my-video-miniature [video]="video" [user]="userMiniature" [displayVideoActions]="true"> |
44 | </my-video-miniature> | 44 | </my-video-miniature> |
45 | </div> | 45 | </div> |
46 | </div> | 46 | </div> |
diff --git a/client/src/app/+videos/video-list/overview/video-overview.component.scss b/client/src/app/+videos/video-list/overview/video-overview.component.scss index c1d10188a..ec73c628c 100644 --- a/client/src/app/+videos/video-list/overview/video-overview.component.scss +++ b/client/src/app/+videos/video-list/overview/video-overview.component.scss | |||
@@ -8,9 +8,84 @@ | |||
8 | } | 8 | } |
9 | 9 | ||
10 | .margin-content { | 10 | .margin-content { |
11 | @include fluid-videos-miniature-layout; | 11 | @include grid-videos-miniature-layout; |
12 | } | 12 | } |
13 | 13 | ||
14 | .section { | 14 | .section { |
15 | @include miniature-rows; | 15 | &:first-child { |
16 | padding-top: 30px; | ||
17 | |||
18 | .section-title { | ||
19 | border-top: none !important; | ||
20 | } | ||
21 | } | ||
22 | |||
23 | .section-title { | ||
24 | font-size: 24px; | ||
25 | font-weight: $font-semibold; | ||
26 | padding-top: 15px; | ||
27 | margin-bottom: 15px; | ||
28 | display: flex; | ||
29 | justify-content: space-between; | ||
30 | |||
31 | &:not(h2) { | ||
32 | border-top: 1px solid $separator-border-color; | ||
33 | } | ||
34 | |||
35 | a { | ||
36 | &:hover, &:focus:not(.focus-visible), &:active { | ||
37 | text-decoration: none; | ||
38 | outline: none; | ||
39 | } | ||
40 | |||
41 | color: pvar(--mainForegroundColor); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | &.channel { | ||
46 | .section-title { | ||
47 | a { | ||
48 | display: flex; | ||
49 | width: fit-content; | ||
50 | align-items: center; | ||
51 | |||
52 | img { | ||
53 | @include channel-avatar(28px); | ||
54 | |||
55 | margin-right: 8px; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | .followers { | ||
60 | color: pvar(--greyForegroundColor); | ||
61 | font-weight: normal; | ||
62 | font-size: 14px; | ||
63 | margin-left: 10px; | ||
64 | position: relative; | ||
65 | top: 2px; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | .show-more { | ||
71 | position: relative; | ||
72 | top: -5px; | ||
73 | display: inline-block; | ||
74 | font-size: 16px; | ||
75 | text-transform: uppercase; | ||
76 | color: pvar(--greyForegroundColor); | ||
77 | margin-bottom: 10px; | ||
78 | font-weight: $font-semibold; | ||
79 | text-decoration: none; | ||
80 | } | ||
81 | |||
82 | @media screen and (max-width: $mobile-view) { | ||
83 | max-height: initial; | ||
84 | overflow: initial; | ||
85 | |||
86 | .section-title { | ||
87 | font-size: 17px; | ||
88 | margin-left: 10px; | ||
89 | } | ||
90 | } | ||
16 | } | 91 | } |
diff --git a/client/src/app/+videos/video-list/video-user-subscriptions.component.ts b/client/src/app/+videos/video-list/video-user-subscriptions.component.ts index e352a2b2c..6aabb93a5 100644 --- a/client/src/app/+videos/video-list/video-user-subscriptions.component.ts +++ b/client/src/app/+videos/video-list/video-user-subscriptions.component.ts | |||
@@ -7,7 +7,7 @@ import { HooksService } from '@app/core/plugins/hooks.service' | |||
7 | import { immutableAssign } from '@app/helpers' | 7 | import { immutableAssign } from '@app/helpers' |
8 | import { VideoService } from '@app/shared/shared-main' | 8 | import { VideoService } from '@app/shared/shared-main' |
9 | import { UserSubscriptionService } from '@app/shared/shared-user-subscription' | 9 | import { UserSubscriptionService } from '@app/shared/shared-user-subscription' |
10 | import { AbstractVideoList, OwnerDisplayType } from '@app/shared/shared-video-miniature' | 10 | import { AbstractVideoList } from '@app/shared/shared-video-miniature' |
11 | import { FeedFormat, VideoSortField } from '@shared/models' | 11 | import { FeedFormat, VideoSortField } from '@shared/models' |
12 | import { environment } from '../../../environments/environment' | 12 | import { environment } from '../../../environments/environment' |
13 | import { copyToClipboard } from '../../../root-helpers/utils' | 13 | import { copyToClipboard } from '../../../root-helpers/utils' |
@@ -20,7 +20,6 @@ import { copyToClipboard } from '../../../root-helpers/utils' | |||
20 | export class VideoUserSubscriptionsComponent extends AbstractVideoList implements OnInit, OnDestroy { | 20 | export class VideoUserSubscriptionsComponent extends AbstractVideoList implements OnInit, OnDestroy { |
21 | titlePage: string | 21 | titlePage: string |
22 | sort = '-publishedAt' as VideoSortField | 22 | sort = '-publishedAt' as VideoSortField |
23 | ownerDisplayType: OwnerDisplayType = 'auto' | ||
24 | groupByDate = true | 23 | groupByDate = true |
25 | 24 | ||
26 | constructor ( | 25 | constructor ( |