feat(playback): restyle inline player header as now-playing bar

Adds a back button (emits the existing closed output — in watch state
back returns to browse, not route navigation) and replaces the
hardcoded header strings with i18n keys (PORTALS.NOW_PLAYING,
CLOSE_PLAYER, BACK_TO_BROWSE).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Fable 5 committed 2026-07-04 18:15:54 +02:00
1 parent 329be253eb
commit d2883a9e2b
5 files changed
+60 -16

No files matched your search

+4
View File
@@ -918,6 +918,10 @@
},
"STREAM_URL_COPIED": "Stream URL copied to clipboard",
"COPY_STREAM_URL": "Copy Stream URL",
"NOW_PLAYING": "Now playing",
"CLOSE_PLAYER": "Close player",
"BACK_TO_BROWSE": "Back to details",
"ABOUT": "About",
"SELECT_CATEGORY": "Select a category",
"PAGE": "Page",
"CONTENT_NOT_AVAILABLE": "This content is not available on this server",
@@ -1,17 +1,30 @@
@if (hasPlayback()) {
<section class="player-shell" aria-label="Inline player">
<header class="player-shell__header">
<div class="player-shell__eyebrow">Now Playing</div>
<div class="player-shell__title-row">
<button
mat-icon-button
type="button"
class="player-shell__back"
data-testid="inline-player-back"
[attr.aria-label]="'PORTALS.BACK_TO_BROWSE' | translate"
[matTooltip]="'PORTALS.BACK_TO_BROWSE' | translate"
(click)="onClose()"
>
<mat-icon>arrow_back</mat-icon>
</button>
<div class="player-shell__heading">
<div class="player-shell__eyebrow">
{{ 'PORTALS.NOW_PLAYING' | translate }}
</div>
<h3 class="player-shell__title" [matTooltip]="title()">
{{ title() }}
@if (episodeMetadataText(); as episodeText) {
<span class="player-shell__episode-meta">
· {{ episodeText }}
</span>
}
</h3>
@if (episodeMetadataText(); as episodeText) {
<div class="player-shell__episode-meta">
{{ episodeText }}
</div>
}
</div>
<div class="player-shell__actions">
<button
@@ -22,7 +35,7 @@
(click)="onCopied()"
>
<mat-icon>content_copy</mat-icon>
Copy Stream URL
{{ 'PORTALS.COPY_STREAM_URL' | translate }}
</button>
<button
mat-stroked-button
@@ -30,7 +43,7 @@
(click)="onClose()"
>
<mat-icon>close</mat-icon>
Close Player
{{ 'PORTALS.CLOSE_PLAYER' | translate }}
</button>
</div>
</div>
@@ -35,10 +35,14 @@
.player-shell__title-row {
display: flex;
gap: 12px;
align-items: flex-start;
align-items: center;
justify-content: space-between;
}
.player-shell__back {
flex: none;
}
.player-shell__heading {
min-width: 0;
}
@@ -49,17 +53,15 @@
font-weight: 700;
line-height: 1.2;
color: #161616;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.player-shell__episode-meta {
margin-top: 4px;
overflow: hidden;
color: rgba(26, 26, 26, 0.64);
font-size: 0.9rem;
font-size: 0.95rem;
font-weight: 600;
line-height: 1.35;
text-overflow: ellipsis;
white-space: nowrap;
}
.player-shell__actions {
@@ -1,6 +1,7 @@
import { Component, input, output } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core';
import type { PortalInlinePlayerComponent as PortalInlinePlayerComponentInstance } from './portal-inline-player.component';
jest.unstable_mockModule('video.js', () => ({
@@ -46,7 +47,7 @@ describe('PortalInlinePlayerComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PortalInlinePlayerComponent],
imports: [PortalInlinePlayerComponent, TranslateModule.forRoot()],
})
.overrideComponent(PortalInlinePlayerComponent, {
remove: {
@@ -120,4 +121,26 @@ describe('PortalInlinePlayerComponent', () => {
expect(events).toEqual(['ended', 'previous', 'next']);
});
it('emits closed from the back button in the now-playing bar', () => {
let closedCount = 0;
fixture.componentRef.setInput('playback', {
streamUrl: 'https://example.test/vod/1.mp4',
title: 'Movie',
});
(
component as unknown as {
closed: { subscribe: (fn: () => void) => void };
}
).closed.subscribe(() => closedCount++);
fixture.detectChanges();
const backButton = fixture.nativeElement.querySelector(
'[data-testid="inline-player-back"]'
) as HTMLButtonElement;
expect(backButton).toBeTruthy();
backButton.click();
expect(closedCount).toBe(1);
});
});
@@ -9,6 +9,7 @@ import {
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatTooltipModule } from '@angular/material/tooltip';
import { TranslateModule } from '@ngx-translate/core';
import {
PlayerContentInfo,
ResolvedPortalPlayback,
@@ -29,6 +30,7 @@ import type {
MatButtonModule,
MatIconModule,
MatTooltipModule,
TranslateModule,
WebPlayerViewComponent,
],
changeDetection: ChangeDetectionStrategy.OnPush,