diff options
14 files changed, 312 insertions, 249 deletions
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html new file mode 100644 index 000000000..8fb244cc4 --- /dev/null +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.html | |||
@@ -0,0 +1,85 @@ | |||
1 | <div class="video-actions-rates"> | ||
2 | <div class="video-actions full-width justify-content-end"> | ||
3 | <my-video-rate | ||
4 | [video]="video" [isUserLoggedIn]="isUserLoggedIn" | ||
5 | (rateUpdated)="onRateUpdated($event)" (userRatingLoaded)="onRateUpdated($event)" | ||
6 | ></my-video-rate> | ||
7 | |||
8 | <button *ngIf="video.support" (click)="showSupportModal()" (keyup.enter)="showSupportModal()" class="action-button action-button-support" [attr.aria-label]="tooltipSupport" | ||
9 | [ngbTooltip]="tooltipSupport" | ||
10 | placement="bottom auto" | ||
11 | > | ||
12 | <my-global-icon iconName="support" aria-hidden="true"></my-global-icon> | ||
13 | <span class="icon-text" i18n>SUPPORT</span> | ||
14 | </button> | ||
15 | |||
16 | <button (click)="showShareModal()" (keyup.enter)="showShareModal()" class="action-button"> | ||
17 | <my-global-icon iconName="share" aria-hidden="true"></my-global-icon> | ||
18 | <span class="icon-text" i18n>SHARE</span> | ||
19 | </button> | ||
20 | |||
21 | <div | ||
22 | class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside" | ||
23 | *ngIf="isUserLoggedIn" (openChange)="addContent.openChange($event)" | ||
24 | [ngbTooltip]="tooltipSaveToPlaylist" | ||
25 | placement="bottom auto" | ||
26 | > | ||
27 | <button class="action-button action-button-save" ngbDropdownToggle> | ||
28 | <my-global-icon iconName="playlist-add" aria-hidden="true"></my-global-icon> | ||
29 | <span class="icon-text" i18n>SAVE</span> | ||
30 | </button> | ||
31 | |||
32 | <div ngbDropdownMenu> | ||
33 | <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist> | ||
34 | </div> | ||
35 | </div> | ||
36 | |||
37 | <ng-container *ngIf="!isUserLoggedIn && !video.isLive"> | ||
38 | <button | ||
39 | *ngIf="isVideoDownloadable()" class="action-button action-button-save" | ||
40 | (click)="showDownloadModal()" (keydown.enter)="showDownloadModal()" | ||
41 | > | ||
42 | <my-global-icon iconName="download" aria-hidden="true"></my-global-icon> | ||
43 | <span class="icon-text d-none d-sm-inline" i18n>DOWNLOAD</span> | ||
44 | </button> | ||
45 | |||
46 | <my-video-download #videoDownloadModal></my-video-download> | ||
47 | </ng-container> | ||
48 | |||
49 | <ng-container *ngIf="isUserLoggedIn"> | ||
50 | <my-video-actions-dropdown | ||
51 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions" | ||
52 | [displayOptions]="videoActionsOptions" (videoRemoved)="onVideoRemoved()" | ||
53 | ></my-video-actions-dropdown> | ||
54 | </ng-container> | ||
55 | </div> | ||
56 | |||
57 | <div class="likes-dislikes-bar-outer-container"> | ||
58 | <div | ||
59 | class="likes-dislikes-bar-inner-container" | ||
60 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | ||
61 | [ngbTooltip]="likesBarTooltipText" | ||
62 | placement="bottom" | ||
63 | > | ||
64 | <div | ||
65 | class="likes-dislikes-bar" | ||
66 | > | ||
67 | <div class="likes-bar" [ngClass]="{ 'liked': userRating !== 'none' }" [ngStyle]="{ 'width.%': video.likesPercent }"></div> | ||
68 | </div> | ||
69 | </div> | ||
70 | </div> | ||
71 | </div> | ||
72 | |||
73 | <div | ||
74 | class="likes-dislikes-bar" | ||
75 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | ||
76 | [ngbTooltip]="likesBarTooltipText" | ||
77 | placement="bottom" | ||
78 | > | ||
79 | <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div> | ||
80 | </div> | ||
81 | |||
82 | <ng-container *ngIf="video"> | ||
83 | <my-support-modal #supportModal [video]="video"></my-support-modal> | ||
84 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share> | ||
85 | </ng-container> | ||
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss new file mode 100644 index 000000000..967d515e6 --- /dev/null +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.scss | |||
@@ -0,0 +1,99 @@ | |||
1 | @use '_variables' as *; | ||
2 | @use '_mixins' as *; | ||
3 | |||
4 | .video-actions { | ||
5 | height: 40px; // Align with the title | ||
6 | display: flex; | ||
7 | align-items: center; | ||
8 | |||
9 | .action-button:not(:first-child), | ||
10 | .action-dropdown, | ||
11 | my-video-actions-dropdown { | ||
12 | @include margin-left(5px); | ||
13 | } | ||
14 | |||
15 | ::ng-deep.action-button { | ||
16 | @include peertube-button; | ||
17 | @include button-with-icon(21px, 0, -1px); | ||
18 | |||
19 | font-size: 100%; | ||
20 | font-weight: $font-semibold; | ||
21 | display: inline-block; | ||
22 | padding: 0 10px; | ||
23 | white-space: nowrap; | ||
24 | background-color: transparent !important; | ||
25 | color: pvar(--actionButtonColor); | ||
26 | text-transform: uppercase; | ||
27 | |||
28 | &::after { | ||
29 | display: none; | ||
30 | } | ||
31 | |||
32 | &:hover { | ||
33 | opacity: 0.9; | ||
34 | } | ||
35 | |||
36 | &.action-button-support { | ||
37 | color: pvar(--supportButtonColor); | ||
38 | |||
39 | my-global-icon { | ||
40 | @include apply-svg-color(pvar(--supportButtonColor)); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | &.action-button-support { | ||
45 | my-global-icon { | ||
46 | ::ng-deep path:first-child { | ||
47 | fill: pvar(--supportButtonHeartColor) !important; | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | |||
52 | &.action-button-save { | ||
53 | my-global-icon { | ||
54 | top: 0 !important; | ||
55 | right: -1px; | ||
56 | } | ||
57 | } | ||
58 | |||
59 | .icon-text { | ||
60 | @include margin-left(3px); | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | .likes-dislikes-bar-outer-container { | ||
66 | position: relative; | ||
67 | } | ||
68 | |||
69 | .likes-dislikes-bar-inner-container { | ||
70 | position: absolute; | ||
71 | height: 20px; | ||
72 | } | ||
73 | |||
74 | .likes-dislikes-bar { | ||
75 | $likes-bar-height: 2px; | ||
76 | |||
77 | height: $likes-bar-height; | ||
78 | margin-top: -$likes-bar-height; | ||
79 | |||
80 | width: 120px; | ||
81 | background-color: #ccc; | ||
82 | position: relative; | ||
83 | top: 10px; | ||
84 | |||
85 | .likes-bar { | ||
86 | height: 100%; | ||
87 | background-color: #909090; | ||
88 | |||
89 | &.liked { | ||
90 | background-color: pvar(--activatedActionButtonColor); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | @media screen and (max-width: 450px) { | ||
96 | .action-button .icon-text { | ||
97 | display: none !important; | ||
98 | } | ||
99 | } | ||
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.ts b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.ts new file mode 100644 index 000000000..e59238ffe --- /dev/null +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/action-buttons.component.ts | |||
@@ -0,0 +1,93 @@ | |||
1 | import { Component, Input, OnChanges, OnInit, ViewChild } from '@angular/core' | ||
2 | import { RedirectService, ScreenService } from '@app/core' | ||
3 | import { VideoDetails } from '@app/shared/shared-main' | ||
4 | import { VideoShareComponent } from '@app/shared/shared-share-modal' | ||
5 | import { SupportModalComponent } from '@app/shared/shared-support-modal' | ||
6 | import { VideoActionsDisplayType, VideoDownloadComponent } from '@app/shared/shared-video-miniature' | ||
7 | import { VideoPlaylist } from '@app/shared/shared-video-playlist' | ||
8 | import { UserVideoRateType, VideoCaption } from '@shared/models/videos' | ||
9 | |||
10 | @Component({ | ||
11 | selector: 'my-action-buttons', | ||
12 | templateUrl: './action-buttons.component.html', | ||
13 | styleUrls: [ './action-buttons.component.scss' ] | ||
14 | }) | ||
15 | export class ActionButtonsComponent implements OnInit, OnChanges { | ||
16 | @ViewChild('videoShareModal') videoShareModal: VideoShareComponent | ||
17 | @ViewChild('supportModal') supportModal: SupportModalComponent | ||
18 | @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent | ||
19 | |||
20 | @Input() video: VideoDetails | ||
21 | @Input() videoCaptions: VideoCaption[] | ||
22 | @Input() playlist: VideoPlaylist | ||
23 | |||
24 | @Input() isUserLoggedIn: boolean | ||
25 | |||
26 | @Input() currentTime: number | ||
27 | @Input() currentPlaylistPosition: number | ||
28 | |||
29 | likesBarTooltipText = '' | ||
30 | |||
31 | tooltipSupport = '' | ||
32 | tooltipSaveToPlaylist = '' | ||
33 | |||
34 | videoActionsOptions: VideoActionsDisplayType = { | ||
35 | playlist: false, | ||
36 | download: true, | ||
37 | update: true, | ||
38 | blacklist: true, | ||
39 | delete: true, | ||
40 | report: true, | ||
41 | duplicate: true, | ||
42 | mute: true, | ||
43 | liveInfo: true | ||
44 | } | ||
45 | |||
46 | userRating: UserVideoRateType | ||
47 | |||
48 | constructor ( | ||
49 | private screenService: ScreenService, | ||
50 | private redirectService: RedirectService | ||
51 | ) { } | ||
52 | |||
53 | ngOnInit () { | ||
54 | // Hide the tooltips for unlogged users in mobile view, this adds confusion with the popover | ||
55 | if (this.isUserLoggedIn || !this.screenService.isInMobileView()) { | ||
56 | this.tooltipSupport = $localize`Support options for this video` | ||
57 | this.tooltipSaveToPlaylist = $localize`Save to playlist` | ||
58 | } | ||
59 | } | ||
60 | |||
61 | ngOnChanges () { | ||
62 | this.setVideoLikesBarTooltipText() | ||
63 | } | ||
64 | |||
65 | showDownloadModal () { | ||
66 | this.videoDownloadModal.show(this.video, this.videoCaptions) | ||
67 | } | ||
68 | |||
69 | isVideoDownloadable () { | ||
70 | return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled && !this.video.isLive | ||
71 | } | ||
72 | |||
73 | showSupportModal () { | ||
74 | this.supportModal.show() | ||
75 | } | ||
76 | |||
77 | showShareModal () { | ||
78 | this.videoShareModal.show(this.currentTime, this.currentPlaylistPosition) | ||
79 | } | ||
80 | |||
81 | onRateUpdated (userRating: UserVideoRateType) { | ||
82 | this.userRating = userRating | ||
83 | this.setVideoLikesBarTooltipText() | ||
84 | } | ||
85 | |||
86 | onVideoRemoved () { | ||
87 | this.redirectService.redirectToHomepage() | ||
88 | } | ||
89 | |||
90 | private setVideoLikesBarTooltipText () { | ||
91 | this.likesBarTooltipText = `${this.video.likes} likes / ${this.video.dislikes} dislikes` | ||
92 | } | ||
93 | } | ||
diff --git a/client/src/app/+videos/+video-watch/shared/action-buttons/index.ts b/client/src/app/+videos/+video-watch/shared/action-buttons/index.ts new file mode 100644 index 000000000..3844dd12e --- /dev/null +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/index.ts | |||
@@ -0,0 +1,2 @@ | |||
1 | export * from './action-buttons.component' | ||
2 | export * from './video-rate.component' | ||
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.html b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.html index 7dd9b3678..7dd9b3678 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.html +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.html | |||
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.scss b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.scss index f4f696f33..f4f696f33 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.scss +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.scss | |||
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.ts index 89a666a62..ecb5a9281 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-rate.component.ts +++ b/client/src/app/+videos/+video-watch/shared/action-buttons/video-rate.component.ts | |||
@@ -31,7 +31,7 @@ export class VideoRateComponent implements OnInit, OnChanges, OnDestroy { | |||
31 | private screenService: ScreenService | 31 | private screenService: ScreenService |
32 | ) { } | 32 | ) { } |
33 | 33 | ||
34 | async ngOnInit () { | 34 | ngOnInit () { |
35 | // Hide the tooltips for unlogged users in mobile view, this adds confusion with the popover | 35 | // Hide the tooltips for unlogged users in mobile view, this adds confusion with the popover |
36 | if (this.isUserLoggedIn || !this.screenService.isInMobileView()) { | 36 | if (this.isUserLoggedIn || !this.screenService.isInMobileView()) { |
37 | this.tooltipLike = $localize`Like this video` | 37 | this.tooltipLike = $localize`Like this video` |
diff --git a/client/src/app/+videos/+video-watch/shared/index.ts b/client/src/app/+videos/+video-watch/shared/index.ts index 6c5ff7e9b..069f862e2 100644 --- a/client/src/app/+videos/+video-watch/shared/index.ts +++ b/client/src/app/+videos/+video-watch/shared/index.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | export * from './action-buttons' | ||
1 | export * from './comment' | 2 | export * from './comment' |
2 | export * from './information' | 3 | export * from './information' |
3 | export * from './metadata' | 4 | export * from './metadata' |
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/index.ts b/client/src/app/+videos/+video-watch/shared/metadata/index.ts index ba97f7011..7f7ee797b 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/index.ts +++ b/client/src/app/+videos/+video-watch/shared/metadata/index.ts | |||
@@ -1,3 +1,2 @@ | |||
1 | export * from './video-avatar-channel.component' | 1 | export * from './video-avatar-channel.component' |
2 | export * from './video-description.component' | 2 | export * from './video-description.component' |
3 | export * from './video-rate.component' | ||
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts index b554567d9..23d00d31a 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts +++ b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts | |||
@@ -1,4 +1,4 @@ | |||
1 | import { Component, EventEmitter, Inject, Input, LOCALE_ID, OnChanges, Output } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core' |
2 | import { MarkdownService, Notifier } from '@app/core' | 2 | import { MarkdownService, Notifier } from '@app/core' |
3 | import { VideoDetails, VideoService } from '@app/shared/shared-main' | 3 | import { VideoDetails, VideoService } from '@app/shared/shared-main' |
4 | 4 | ||
@@ -21,8 +21,7 @@ export class VideoDescriptionComponent implements OnChanges { | |||
21 | constructor ( | 21 | constructor ( |
22 | private videoService: VideoService, | 22 | private videoService: VideoService, |
23 | private notifier: Notifier, | 23 | private notifier: Notifier, |
24 | private markdownService: MarkdownService, | 24 | private markdownService: MarkdownService |
25 | @Inject(LOCALE_ID) private localeId: string | ||
26 | ) { } | 25 | ) { } |
27 | 26 | ||
28 | ngOnChanges () { | 27 | ngOnChanges () { |
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 2380d5a98..a84bafa2a 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.html +++ b/client/src/app/+videos/+video-watch/video-watch.component.html | |||
@@ -74,90 +74,13 @@ | |||
74 | <my-video-views-counter [video]="video"></my-video-views-counter> | 74 | <my-video-views-counter [video]="video"></my-video-views-counter> |
75 | </div> | 75 | </div> |
76 | 76 | ||
77 | <div class="video-actions-rates"> | 77 | <my-action-buttons |
78 | <div class="video-actions full-width justify-content-end"> | 78 | [video]="video" [isUserLoggedIn]="isUserLoggedIn()" [videoCaptions]="videoCaptions" [playlist]="playlist" |
79 | <my-video-rate | 79 | [currentTime]="getCurrentTime()" [currentPlaylistPosition]="getCurrentPlaylistPosition()" |
80 | [video]="video" [isUserLoggedIn]="isUserLoggedIn()" | 80 | ></my-action-buttons> |
81 | (rateUpdated)="onRateUpdated($event)" (userRatingLoaded)="onRateUpdated($event)" | ||
82 | ></my-video-rate> | ||
83 | |||
84 | <button *ngIf="video.support" (click)="showSupportModal()" (keyup.enter)="showSupportModal()" class="action-button action-button-support" [attr.aria-label]="tooltipSupport" | ||
85 | [ngbTooltip]="tooltipSupport" | ||
86 | placement="bottom auto" | ||
87 | > | ||
88 | <my-global-icon iconName="support" aria-hidden="true"></my-global-icon> | ||
89 | <span class="icon-text" i18n>SUPPORT</span> | ||
90 | </button> | ||
91 | |||
92 | <button (click)="showShareModal()" (keyup.enter)="showShareModal()" class="action-button"> | ||
93 | <my-global-icon iconName="share" aria-hidden="true"></my-global-icon> | ||
94 | <span class="icon-text" i18n>SHARE</span> | ||
95 | </button> | ||
96 | |||
97 | <div | ||
98 | class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside" | ||
99 | *ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)" | ||
100 | [ngbTooltip]="tooltipSaveToPlaylist" | ||
101 | placement="bottom auto" | ||
102 | > | ||
103 | <button class="action-button action-button-save" ngbDropdownToggle> | ||
104 | <my-global-icon iconName="playlist-add" aria-hidden="true"></my-global-icon> | ||
105 | <span class="icon-text" i18n>SAVE</span> | ||
106 | </button> | ||
107 | |||
108 | <div ngbDropdownMenu> | ||
109 | <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist> | ||
110 | </div> | ||
111 | </div> | ||
112 | |||
113 | <ng-container *ngIf="!isUserLoggedIn() && !isLive()"> | ||
114 | <button | ||
115 | *ngIf="isVideoDownloadable()" class="action-button action-button-save" | ||
116 | (click)="showDownloadModal()" (keydown.enter)="showDownloadModal()" | ||
117 | > | ||
118 | <my-global-icon iconName="download" aria-hidden="true"></my-global-icon> | ||
119 | <span class="icon-text d-none d-sm-inline" i18n>DOWNLOAD</span> | ||
120 | </button> | ||
121 | |||
122 | <my-video-download #videoDownloadModal></my-video-download> | ||
123 | </ng-container> | ||
124 | |||
125 | <ng-container *ngIf="isUserLoggedIn()"> | ||
126 | <my-video-actions-dropdown | ||
127 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions" | ||
128 | [displayOptions]="videoActionsOptions" (videoRemoved)="onVideoRemoved()" | ||
129 | ></my-video-actions-dropdown> | ||
130 | </ng-container> | ||
131 | </div> | ||
132 | |||
133 | <div class="video-info-likes-dislikes-bar-outer-container"> | ||
134 | <div | ||
135 | class="video-info-likes-dislikes-bar-inner-container" | ||
136 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | ||
137 | [ngbTooltip]="likesBarTooltipText" | ||
138 | placement="bottom" | ||
139 | > | ||
140 | <div | ||
141 | class="video-info-likes-dislikes-bar" | ||
142 | > | ||
143 | <div class="likes-bar" [ngClass]="{ 'liked': userRating !== 'none' }" [ngStyle]="{ 'width.%': video.likesPercent }"></div> | ||
144 | </div> | ||
145 | </div> | ||
146 | </div> | ||
147 | </div> | ||
148 | |||
149 | <div | ||
150 | class="video-info-likes-dislikes-bar" | ||
151 | *ngIf="video.likes !== 0 || video.dislikes !== 0" | ||
152 | [ngbTooltip]="likesBarTooltipText" | ||
153 | placement="bottom" | ||
154 | > | ||
155 | <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div> | ||
156 | </div> | ||
157 | </div> | 81 | </div> |
158 | </div> | 82 | </div> |
159 | 83 | ||
160 | |||
161 | <div class="pt-3 border-top video-info-channel d-flex"> | 84 | <div class="pt-3 border-top video-info-channel d-flex"> |
162 | <div class="video-info-channel-left d-flex"> | 85 | <div class="video-info-channel-left d-flex"> |
163 | <my-video-avatar-channel [video]="video" [genericChannel]="isChannelDisplayNameGeneric()"></my-video-avatar-channel> | 86 | <my-video-avatar-channel [video]="video" [genericChannel]="isChannelDisplayNameGeneric()"></my-video-avatar-channel> |
@@ -264,9 +187,4 @@ | |||
264 | <my-privacy-concerns></my-privacy-concerns> | 187 | <my-privacy-concerns></my-privacy-concerns> |
265 | </div> | 188 | </div> |
266 | 189 | ||
267 | <ng-container *ngIf="video !== null"> | ||
268 | <my-support-modal #supportModal [video]="video"></my-support-modal> | ||
269 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share> | ||
270 | </ng-container> | ||
271 | |||
272 | <my-player-styles></my-player-styles> | 190 | <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 e075fc57e..1d83fa139 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.scss +++ b/client/src/app/+videos/+video-watch/video-watch.component.scss | |||
@@ -151,6 +151,7 @@ | |||
151 | @include peertube-word-wrap; | 151 | @include peertube-word-wrap; |
152 | 152 | ||
153 | @include margin-right(30px); | 153 | @include margin-right(30px); |
154 | |||
154 | min-height: 40px; // Align with the action buttons | 155 | min-height: 40px; // Align with the action buttons |
155 | font-size: 27px; | 156 | font-size: 27px; |
156 | font-weight: $font-semibold; | 157 | font-weight: $font-semibold; |
@@ -211,106 +212,6 @@ | |||
211 | @include margin-left(5px); | 212 | @include margin-left(5px); |
212 | } | 213 | } |
213 | } | 214 | } |
214 | |||
215 | .video-actions-rates { | ||
216 | @include margin-left(auto); | ||
217 | @include margin-right(0); | ||
218 | |||
219 | margin-top: 0; | ||
220 | margin-bottom: 10px; | ||
221 | |||
222 | align-items: start; | ||
223 | width: max-content; | ||
224 | |||
225 | .video-actions { | ||
226 | height: 40px; // Align with the title | ||
227 | display: flex; | ||
228 | align-items: center; | ||
229 | |||
230 | .action-button:not(:first-child), | ||
231 | .action-dropdown, | ||
232 | my-video-actions-dropdown { | ||
233 | @include margin-left(5px); | ||
234 | } | ||
235 | |||
236 | ::ng-deep.action-button { | ||
237 | @include peertube-button; | ||
238 | @include button-with-icon(21px, 0, -1px); | ||
239 | |||
240 | font-size: 100%; | ||
241 | font-weight: $font-semibold; | ||
242 | display: inline-block; | ||
243 | padding: 0 10px; | ||
244 | white-space: nowrap; | ||
245 | background-color: transparent !important; | ||
246 | color: pvar(--actionButtonColor); | ||
247 | text-transform: uppercase; | ||
248 | |||
249 | &::after { | ||
250 | display: none; | ||
251 | } | ||
252 | |||
253 | &:hover { | ||
254 | opacity: 0.9; | ||
255 | } | ||
256 | |||
257 | &.action-button-support { | ||
258 | color: pvar(--supportButtonColor); | ||
259 | |||
260 | my-global-icon { | ||
261 | @include apply-svg-color(pvar(--supportButtonColor)); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | &.action-button-support { | ||
266 | my-global-icon { | ||
267 | ::ng-deep path:first-child { | ||
268 | fill: pvar(--supportButtonHeartColor) !important; | ||
269 | } | ||
270 | } | ||
271 | } | ||
272 | |||
273 | &.action-button-save { | ||
274 | my-global-icon { | ||
275 | top: 0 !important; | ||
276 | right: -1px; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | .icon-text { | ||
281 | @include margin-left(3px); | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | |||
286 | .video-info-likes-dislikes-bar-outer-container { | ||
287 | position: relative; | ||
288 | } | ||
289 | |||
290 | .video-info-likes-dislikes-bar-inner-container { | ||
291 | position: absolute; | ||
292 | height: 20px; | ||
293 | } | ||
294 | |||
295 | .video-info-likes-dislikes-bar { | ||
296 | $likes-bar-height: 2px; | ||
297 | height: $likes-bar-height; | ||
298 | margin-top: -$likes-bar-height; | ||
299 | width: 120px; | ||
300 | background-color: #ccc; | ||
301 | position: relative; | ||
302 | top: 10px; | ||
303 | |||
304 | .likes-bar { | ||
305 | height: 100%; | ||
306 | background-color: #909090; | ||
307 | |||
308 | &.liked { | ||
309 | background-color: pvar(--activatedActionButtonColor); | ||
310 | } | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | } | 215 | } |
315 | 216 | ||
316 | .video-attributes { | 217 | .video-attributes { |
@@ -351,6 +252,18 @@ | |||
351 | } | 252 | } |
352 | } | 253 | } |
353 | 254 | ||
255 | my-action-buttons { | ||
256 | @include margin-left(auto); | ||
257 | @include margin-right(0); | ||
258 | |||
259 | display: block; | ||
260 | margin-top: 0; | ||
261 | margin-bottom: 10px; | ||
262 | |||
263 | align-items: start; | ||
264 | width: max-content; | ||
265 | } | ||
266 | |||
354 | my-recommended-videos { | 267 | my-recommended-videos { |
355 | @include padding-left(15px); | 268 | @include padding-left(15px); |
356 | 269 | ||
@@ -411,10 +324,6 @@ my-video-comments { | |||
411 | 324 | ||
412 | @media screen and (max-width: 450px) { | 325 | @media screen and (max-width: 450px) { |
413 | .video-bottom { | 326 | .video-bottom { |
414 | .action-button .icon-text { | ||
415 | display: none !important; | ||
416 | } | ||
417 | |||
418 | .video-info .video-info-first-row { | 327 | .video-info .video-info-first-row { |
419 | .video-info-name { | 328 | .video-info-name { |
420 | font-size: 18px; | 329 | font-size: 18px; |
@@ -423,12 +332,12 @@ my-video-comments { | |||
423 | .video-info-date-views { | 332 | .video-info-date-views { |
424 | font-size: 14px; | 333 | font-size: 14px; |
425 | } | 334 | } |
426 | |||
427 | .video-actions-rates { | ||
428 | margin-top: 10px; | ||
429 | } | ||
430 | } | 335 | } |
431 | } | 336 | } |
337 | |||
338 | my-action-buttons { | ||
339 | margin-top: 10px; | ||
340 | } | ||
432 | } | 341 | } |
433 | 342 | ||
434 | 343 | ||
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 5a0109e64..ca20c2b85 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts | |||
@@ -18,24 +18,13 @@ import { | |||
18 | UserService | 18 | UserService |
19 | } from '@app/core' | 19 | } from '@app/core' |
20 | import { HooksService } from '@app/core/plugins/hooks.service' | 20 | import { HooksService } from '@app/core/plugins/hooks.service' |
21 | import { RedirectService } from '@app/core/routing/redirect.service' | ||
22 | import { isXPercentInViewport, scrollToTop } from '@app/helpers' | 21 | import { isXPercentInViewport, scrollToTop } from '@app/helpers' |
23 | import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' | 22 | import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' |
24 | import { VideoShareComponent } from '@app/shared/shared-share-modal' | ||
25 | import { SupportModalComponent } from '@app/shared/shared-support-modal' | ||
26 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' | 23 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' |
27 | import { VideoActionsDisplayType, VideoDownloadComponent } from '@app/shared/shared-video-miniature' | 24 | import { VideoActionsDisplayType } from '@app/shared/shared-video-miniature' |
28 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' | 25 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' |
29 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | 26 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' |
30 | import { | 27 | import { HTMLServerConfig, PeerTubeProblemDocument, ServerErrorCode, VideoCaption, VideoPrivacy, VideoState } from '@shared/models' |
31 | HTMLServerConfig, | ||
32 | PeerTubeProblemDocument, | ||
33 | ServerErrorCode, | ||
34 | UserVideoRateType, | ||
35 | VideoCaption, | ||
36 | VideoPrivacy, | ||
37 | VideoState | ||
38 | } from '@shared/models' | ||
39 | import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage' | 28 | import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage' |
40 | import { | 29 | import { |
41 | CustomizationOptions, | 30 | CustomizationOptions, |
@@ -58,10 +47,7 @@ type URLOptions = CustomizationOptions & { playerMode: PlayerMode } | |||
58 | }) | 47 | }) |
59 | export class VideoWatchComponent implements OnInit, OnDestroy { | 48 | export class VideoWatchComponent implements OnInit, OnDestroy { |
60 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent | 49 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent |
61 | @ViewChild('videoShareModal') videoShareModal: VideoShareComponent | ||
62 | @ViewChild('supportModal') supportModal: SupportModalComponent | ||
63 | @ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent | 50 | @ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent |
64 | @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent | ||
65 | 51 | ||
66 | player: any | 52 | player: any |
67 | playerElement: HTMLVideoElement | 53 | playerElement: HTMLVideoElement |
@@ -95,8 +81,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
95 | liveInfo: true | 81 | liveInfo: true |
96 | } | 82 | } |
97 | 83 | ||
98 | userRating: UserVideoRateType | ||
99 | |||
100 | private nextVideoUuid = '' | 84 | private nextVideoUuid = '' |
101 | private nextVideoTitle = '' | 85 | private nextVideoTitle = '' |
102 | private currentTime: number | 86 | private currentTime: number |
@@ -124,7 +108,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
124 | private restExtractor: RestExtractor, | 108 | private restExtractor: RestExtractor, |
125 | private notifier: Notifier, | 109 | private notifier: Notifier, |
126 | private zone: NgZone, | 110 | private zone: NgZone, |
127 | private redirectService: RedirectService, | ||
128 | private videoCaptionService: VideoCaptionService, | 111 | private videoCaptionService: VideoCaptionService, |
129 | private hotkeysService: HotkeysService, | 112 | private hotkeysService: HotkeysService, |
130 | private hooks: HooksService, | 113 | private hooks: HooksService, |
@@ -203,20 +186,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
203 | this.hotkeysService.remove(this.hotkeys) | 186 | this.hotkeysService.remove(this.hotkeys) |
204 | } | 187 | } |
205 | 188 | ||
206 | showDownloadModal () { | 189 | getCurrentTime () { |
207 | this.videoDownloadModal.show(this.video, this.videoCaptions) | 190 | return this.currentTime |
208 | } | ||
209 | |||
210 | isVideoDownloadable () { | ||
211 | return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled && !this.video.isLive | ||
212 | } | 191 | } |
213 | 192 | ||
214 | showSupportModal () { | 193 | getCurrentPlaylistPosition () { |
215 | this.supportModal.show() | 194 | return this.videoWatchPlaylist.currentPlaylistPosition |
216 | } | ||
217 | |||
218 | showShareModal () { | ||
219 | this.videoShareModal.show(this.currentTime, this.videoWatchPlaylist.currentPlaylistPosition) | ||
220 | } | 195 | } |
221 | 196 | ||
222 | isUserLoggedIn () { | 197 | isUserLoggedIn () { |
@@ -245,10 +220,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
245 | } | 220 | } |
246 | } | 221 | } |
247 | 222 | ||
248 | onVideoRemoved () { | ||
249 | this.redirectService.redirectToHomepage() | ||
250 | } | ||
251 | |||
252 | isVideoToTranscode () { | 223 | isVideoToTranscode () { |
253 | return this.video && this.video.state.id === VideoState.TO_TRANSCODE | 224 | return this.video && this.video.state.id === VideoState.TO_TRANSCODE |
254 | } | 225 | } |
@@ -261,10 +232,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
261 | return this.video && this.video.scheduledUpdate !== undefined | 232 | return this.video && this.video.scheduledUpdate !== undefined |
262 | } | 233 | } |
263 | 234 | ||
264 | isLive () { | ||
265 | return !!(this.video?.isLive) | ||
266 | } | ||
267 | |||
268 | isWaitingForLive () { | 235 | isWaitingForLive () { |
269 | return this.video?.state.id === VideoState.WAITING_FOR_LIVE | 236 | return this.video?.state.id === VideoState.WAITING_FOR_LIVE |
270 | } | 237 | } |
@@ -311,11 +278,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
311 | this.loadVideo(videoId) | 278 | this.loadVideo(videoId) |
312 | } | 279 | } |
313 | 280 | ||
314 | onRateUpdated (userRating: UserVideoRateType) { | ||
315 | this.userRating = userRating | ||
316 | this.setVideoLikesBarTooltipText() | ||
317 | } | ||
318 | |||
319 | displayOtherVideosAsRow () { | 281 | displayOtherVideosAsRow () { |
320 | // Use the same value as in the SASS file | 282 | // Use the same value as in the SASS file |
321 | return this.screenService.getWindowInnerWidth() <= 1100 | 283 | return this.screenService.getWindowInnerWidth() <= 1100 |
@@ -421,10 +383,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
421 | }) | 383 | }) |
422 | } | 384 | } |
423 | 385 | ||
424 | private setVideoLikesBarTooltipText () { | ||
425 | this.likesBarTooltipText = `${this.video.likes} likes / ${this.video.dislikes} dislikes` | ||
426 | } | ||
427 | |||
428 | private handleError (err: any) { | 386 | private handleError (err: any) { |
429 | const errorMessage: string = typeof err === 'string' ? err : err.message | 387 | const errorMessage: string = typeof err === 'string' ? err : err.message |
430 | if (!errorMessage) return | 388 | if (!errorMessage) return |
@@ -467,8 +425,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
467 | this.buildPlayer(urlOptions) | 425 | this.buildPlayer(urlOptions) |
468 | .catch(err => console.error('Cannot build the player', err)) | 426 | .catch(err => console.error('Cannot build the player', err)) |
469 | 427 | ||
470 | this.setVideoLikesBarTooltipText() | ||
471 | |||
472 | this.setOpenGraphTags() | 428 | this.setOpenGraphTags() |
473 | 429 | ||
474 | const hookOptions = { | 430 | const hookOptions = { |
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 c1f40d785..602525342 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 { | |||
19 | VideoDescriptionComponent, | 19 | VideoDescriptionComponent, |
20 | VideoRateComponent, | 20 | VideoRateComponent, |
21 | VideoWatchPlaylistComponent, | 21 | VideoWatchPlaylistComponent, |
22 | ActionButtonsComponent, | ||
22 | PrivacyConcernsComponent | 23 | PrivacyConcernsComponent |
23 | } from './shared' | 24 | } from './shared' |
24 | import { VideoCommentAddComponent } from './shared/comment/video-comment-add.component' | 25 | import { VideoCommentAddComponent } from './shared/comment/video-comment-add.component' |
@@ -53,6 +54,7 @@ import { VideoWatchComponent } from './video-watch.component' | |||
53 | VideoRateComponent, | 54 | VideoRateComponent, |
54 | VideoDescriptionComponent, | 55 | VideoDescriptionComponent, |
55 | PrivacyConcernsComponent, | 56 | PrivacyConcernsComponent, |
57 | ActionButtonsComponent, | ||
56 | 58 | ||
57 | VideoCommentsComponent, | 59 | VideoCommentsComponent, |
58 | VideoCommentAddComponent, | 60 | VideoCommentAddComponent, |