Fix video miniature keyboard navigation

This commit is contained in:
Chocobozzz 2024-09-20 09:32:13 +02:00
parent 4ba9da72a9
commit 8ce037b0c0
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 50 additions and 35 deletions

View File

@ -9,25 +9,25 @@
<ng-template #aContent> <ng-template #aContent>
<img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" /> <img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" />
<div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay"> <div *ngIf="displayWatchLaterPlaylist" class="actions-overlay">
<ng-container *ngIf="inWatchLaterPlaylist !== true"> <button
<button class="video-thumbnail-watch-later-overlay button-unstyle" placement="left" [ngbTooltip]="addToWatchLaterText" container="body" (click)="onWatchLaterClick($event)"> class="watch-icon-overlay button-unstyle"
<my-global-icon iconName="clock" [attr.aria-label]="addToWatchLaterText" role="button"></my-global-icon> placement="left" [ngbTooltip]="getWatchIconText()" container="body" #watchLaterTooltip="ngbTooltip"
(click)="onWatchLaterClick($event)"
>
@if (inWatchLaterPlaylist) {
<my-global-icon iconName="tick" [attr.aria-label]="inWatchLaterPlaylist"></my-global-icon>
} @else {
<my-global-icon iconName="clock" [attr.aria-label]="addToWatchLaterText"></my-global-icon>
}
</button> </button>
</ng-container>
<ng-container *ngIf="inWatchLaterPlaylist === true">
<button class="video-thumbnail-watch-later-overlay button-unstyle" placement="left" [ngbTooltip]="addedToWatchLaterText" container="body" (click)="onWatchLaterClick($event)">
<my-global-icon iconName="tick" [attr.aria-label]="addedToWatchLaterText" role="button"></my-global-icon>
</button>
</ng-container>
</div> </div>
<div class="video-thumbnail-label-overlay warning"><ng-content select="label-warning"></ng-content></div> <div class="label-overlay warning"><ng-content select="label-warning"></ng-content></div>
<div class="video-thumbnail-label-overlay danger"><ng-content select="label-danger"></ng-content></div> <div class="label-overlay danger"><ng-content select="label-danger"></ng-content></div>
<div class="video-thumbnail-duration-overlay" *ngIf="!video.isLive">{{ video.durationLabel }}</div> <div class="duration-overlay" *ngIf="!video.isLive">{{ video.durationLabel }}</div>
<div class="video-thumbnail-live-overlay" [ngClass]="{ 'live-ended': isLiveEnded() }" *ngIf="video.isLive"> <div class="live-overlay" [ngClass]="{ 'live-ended': isLiveEnded() }" *ngIf="video.isLive">
<ng-container i18n *ngIf="!isLiveEnded()">LIVE</ng-container> <ng-container i18n *ngIf="!isLiveEnded()">LIVE</ng-container>
<ng-container i18n *ngIf="isLiveEnded()">LIVE ENDED</ng-container> <ng-container i18n *ngIf="isLiveEnded()">LIVE ENDED</ng-container>
</div> </div>

View File

@ -19,10 +19,10 @@
} }
} }
.video-thumbnail-watch-later-overlay, .watch-icon-overlay,
.video-thumbnail-label-overlay, .label-overlay,
.video-thumbnail-duration-overlay, .duration-overlay,
.video-thumbnail-live-overlay { .live-overlay {
border-radius: 3px; border-radius: 3px;
font-size: 12px; font-size: 12px;
font-weight: $font-semibold; font-weight: $font-semibold;
@ -32,7 +32,7 @@
@include static-thumbnail-overlay; @include static-thumbnail-overlay;
} }
.video-thumbnail-label-overlay { .label-overlay {
position: absolute; position: absolute;
padding: 0 5px; padding: 0 5px;
left: 5px; left: 5px;
@ -43,15 +43,15 @@
&.danger { background-color: #ff0000; } &.danger { background-color: #ff0000; }
} }
.video-thumbnail-duration-overlay, .duration-overlay,
.video-thumbnail-live-overlay { .live-overlay {
position: absolute; position: absolute;
padding: 0 3px; padding: 0 3px;
right: 5px; right: 5px;
bottom: 5px; bottom: 5px;
} }
.video-thumbnail-live-overlay { .live-overlay {
font-weight: $font-semibold; font-weight: $font-semibold;
color: #fff; color: #fff;
@ -60,7 +60,7 @@
} }
} }
.video-thumbnail-actions-overlay { .actions-overlay {
position: absolute; position: absolute;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -73,7 +73,7 @@
} }
} }
.video-thumbnail-watch-later-overlay { .watch-icon-overlay {
padding: 3px; padding: 3px;
my-global-icon { my-global-icon {

View File

@ -1,10 +1,10 @@
import { Component, EventEmitter, Input, Output } from '@angular/core' import { NgClass, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common'
import { Component, EventEmitter, Input, Output, ViewChild, viewChild } from '@angular/core'
import { RouterLink } from '@angular/router'
import { ScreenService } from '@app/core' import { ScreenService } from '@app/core'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { VideoState } from '@peertube/peertube-models' import { VideoState } from '@peertube/peertube-models'
import { GlobalIconComponent } from '../shared-icons/global-icon.component' import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { RouterLink } from '@angular/router'
import { NgIf, NgTemplateOutlet, NgClass, NgStyle } from '@angular/common'
import { Video } from '../shared-main/video/video.model' import { Video } from '../shared-main/video/video.model'
@Component({ @Component({
@ -15,6 +15,8 @@ import { Video } from '../shared-main/video/video.model'
imports: [ NgIf, RouterLink, NgTemplateOutlet, NgClass, NgbTooltip, GlobalIconComponent, NgStyle ] imports: [ NgIf, RouterLink, NgTemplateOutlet, NgClass, NgbTooltip, GlobalIconComponent, NgStyle ]
}) })
export class VideoThumbnailComponent { export class VideoThumbnailComponent {
@ViewChild('watchLaterTooltip') watchLaterTooltip: NgbTooltip
@Input() video: Video @Input() video: Video
@Input() nsfw = false @Input() nsfw = false
@ -31,11 +33,17 @@ export class VideoThumbnailComponent {
@Output() watchLaterClick = new EventEmitter<boolean>() @Output() watchLaterClick = new EventEmitter<boolean>()
addToWatchLaterText: string addToWatchLaterText: string
addedToWatchLaterText: string removeFromWatchLaterText: string
constructor (private screenService: ScreenService) { constructor (private screenService: ScreenService) {
this.addToWatchLaterText = $localize`Add to watch later` this.addToWatchLaterText = $localize`Add to watch later`
this.addedToWatchLaterText = $localize`Remove from watch later` this.removeFromWatchLaterText = $localize`Remove from watch later`
}
getWatchIconText () {
if (this.inWatchLaterPlaylist) return this.removeFromWatchLaterText
return this.addToWatchLaterText
} }
isLiveEnded () { isLiveEnded () {
@ -72,6 +80,8 @@ export class VideoThumbnailComponent {
this.watchLaterClick.emit(this.inWatchLaterPlaylist) this.watchLaterClick.emit(this.inWatchLaterPlaylist)
event.stopPropagation() event.stopPropagation()
this.watchLaterTooltip.close()
return false return false
} }
} }

View File

@ -1,4 +1,4 @@
<div class="video-miniature" [ngClass]="getClasses()" (mouseenter)="loadActions()"> <div class="video-miniature" [ngClass]="getClasses()" (mouseenter)="loadActions()" (focusin)="loadActions()">
<my-video-thumbnail <my-video-thumbnail
[ariaLabel]="getAriaLabel()" [ariaLabel]="getAriaLabel()"
[video]="video" [nsfw]="isVideoBlur" [videoRouterLink]="videoRouterLink" [videoHref]="videoHref" [videoTarget]="videoTarget" [video]="video" [nsfw]="isVideoBlur" [videoRouterLink]="videoRouterLink" [videoHref]="videoHref" [videoTarget]="videoTarget"

View File

@ -77,8 +77,9 @@ my-actor-avatar {
} }
} }
.video-miniature:hover { .video-miniature:hover,
::ng-deep .video-thumbnail-actions-overlay, .video-miniature:focus-within {
my-video-thumbnail ::ng-deep .actions-overlay,
.video-actions ::ng-deep .dropdown-root { .video-actions ::ng-deep .dropdown-root {
opacity: 1 !important; opacity: 1 !important;
} }

View File

@ -118,6 +118,7 @@ export class VideoMiniatureComponent implements OnInit {
videoTarget: string videoTarget: string
private ownerDisplayType: 'account' | 'videoChannel' private ownerDisplayType: 'account' | 'videoChannel'
private actionsLoaded = false
constructor ( constructor (
private screenService: ScreenService, private screenService: ScreenService,
@ -244,9 +245,12 @@ export class VideoMiniatureComponent implements OnInit {
} }
loadActions () { loadActions () {
if (this.actionsLoaded) return
if (this.displayVideoActions) this.showActions = true if (this.displayVideoActions) this.showActions = true
this.loadWatchLater() this.loadWatchLater()
this.actionsLoaded = true
} }
onVideoBlocked () { onVideoBlocked () {