mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-09 01:16:15 -08:00
feat(epg): add a Guide button to the timeline toolbar
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
44e421103e
commit
688fd4584d
5 files changed
+60
-6
No files matched your search
@@ -28,6 +28,7 @@ export class StubEpgTimelineComponent {
|
||||
readonly collapsed = input(false);
|
||||
readonly summary = input<LiveEpgPanelSummary | null>(null);
|
||||
readonly summaryLabelKey = input('');
|
||||
readonly guideAvailable = input(false);
|
||||
readonly programActivated = output<{
|
||||
program?: EpgProgram;
|
||||
type: 'timeshift' | 'live';
|
||||
@@ -37,4 +38,5 @@ export class StubEpgTimelineComponent {
|
||||
readonly openEpgSettings = output<void>();
|
||||
readonly retry = output<void>();
|
||||
readonly collapsedChange = output<boolean>();
|
||||
readonly openGuide = output<void>();
|
||||
}
|
||||
@@ -55,7 +55,10 @@
|
||||
summary()?.title
|
||||
}}</span>
|
||||
@if (progress() !== null) {
|
||||
<span class="epg-timeline__summary-bar" aria-hidden="true">
|
||||
<span
|
||||
class="epg-timeline__summary-bar"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<i [style.width.%]="progress()"></i>
|
||||
</span>
|
||||
}
|
||||
@@ -97,6 +100,17 @@
|
||||
</button>
|
||||
}
|
||||
@if (showRibbonControls()) {
|
||||
@if (guideAvailable()) {
|
||||
<button
|
||||
type="button"
|
||||
class="epg-timeline__guide"
|
||||
(click)="openGuide.emit()"
|
||||
[matTooltip]="'EPG.TIMELINE.OPEN_GUIDE' | translate"
|
||||
>
|
||||
<mat-icon>grid_view</mat-icon>
|
||||
{{ 'EPG.TIMELINE.GUIDE' | translate }}
|
||||
</button>
|
||||
}
|
||||
<button
|
||||
type="button"
|
||||
class="epg-timeline__jump"
|
||||
@@ -145,7 +159,8 @@
|
||||
}
|
||||
</span>
|
||||
<small>{{
|
||||
viewDate() | date: 'EEE, d MMM' : '' : currentLocale()
|
||||
viewDate()
|
||||
| date: 'EEE, d MMM' : '' : currentLocale()
|
||||
}}</small>
|
||||
</div>
|
||||
<button
|
||||
@@ -166,13 +181,17 @@
|
||||
@if (state === 'ribbon' && !archivePlaybackAvailable()) {
|
||||
<div class="epg-timeline__notice" role="note">
|
||||
<mat-icon>info</mat-icon>
|
||||
<span>{{ 'EPG.TIMELINE.SCHEDULE_ONLY_NOTICE' | translate }}</span>
|
||||
<span>{{
|
||||
'EPG.TIMELINE.SCHEDULE_ONLY_NOTICE' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@switch (state) {
|
||||
@case ('loading') {
|
||||
<div class="epg-timeline__ribbon epg-timeline__ribbon--skeleton">
|
||||
<div
|
||||
class="epg-timeline__ribbon epg-timeline__ribbon--skeleton"
|
||||
>
|
||||
@for (width of skeletonWidths; track $index) {
|
||||
<div
|
||||
class="epg-timeline__sk"
|
||||
|
||||
@@ -161,7 +161,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
.epg-timeline__jump {
|
||||
.epg-timeline__jump,
|
||||
.epg-timeline__guide {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
@@ -189,6 +190,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
.epg-timeline__guide {
|
||||
color: $accent-text;
|
||||
border-color: $accent-blue;
|
||||
}
|
||||
|
||||
.epg-timeline__stepper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -40,7 +40,9 @@ describe('EpgTimelineComponent', () => {
|
||||
providers: [
|
||||
{
|
||||
provide: MatDialog,
|
||||
useValue: { open: () => ({ afterClosed: () => of(undefined) }) },
|
||||
useValue: {
|
||||
open: () => ({ afterClosed: () => of(undefined) }),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: TranslateService,
|
||||
@@ -48,6 +50,9 @@ describe('EpgTimelineComponent', () => {
|
||||
currentLang: 'en',
|
||||
defaultLang: 'en',
|
||||
onLangChange: new BehaviorSubject(null),
|
||||
onTranslationChange: new BehaviorSubject(null),
|
||||
onDefaultLangChange: new BehaviorSubject(null),
|
||||
get: (key: string) => of(key),
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -238,4 +243,23 @@ describe('EpgTimelineComponent', () => {
|
||||
});
|
||||
expect(component.scale()).toBeGreaterThan(3);
|
||||
});
|
||||
|
||||
it('shows a Guide button only when the host offers a guide and emits openGuide', () => {
|
||||
setInputs({ programs: [programAt(0, 120, 'Now')] });
|
||||
fixture.detectChanges();
|
||||
expect(
|
||||
fixture.nativeElement.querySelector('.epg-timeline__guide')
|
||||
).toBeNull();
|
||||
|
||||
const openGuide = jest.fn();
|
||||
component.openGuide.subscribe(openGuide);
|
||||
setInputs({ guideAvailable: true });
|
||||
fixture.detectChanges();
|
||||
const button = fixture.nativeElement.querySelector(
|
||||
'.epg-timeline__guide'
|
||||
) as HTMLButtonElement;
|
||||
expect(button).not.toBeNull();
|
||||
button.click();
|
||||
expect(openGuide).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -99,6 +99,8 @@ export class EpgTimelineComponent {
|
||||
readonly summary = input<EpgTimelineSummary | null>(null);
|
||||
readonly summaryLabelKey = input('EPG.CURRENT_PROGRAM');
|
||||
readonly offsetMinutes = input(0);
|
||||
/** The host can open a multi-channel guide; renders the Guide button. */
|
||||
readonly guideAvailable = input(false);
|
||||
|
||||
readonly programActivated = output<EpgProgramActivationEvent>();
|
||||
readonly returnToLive = output<void>();
|
||||
@@ -106,6 +108,7 @@ export class EpgTimelineComponent {
|
||||
readonly openEpgSettings = output<void>();
|
||||
readonly retry = output<void>();
|
||||
readonly collapsedChange = output<boolean>();
|
||||
readonly openGuide = output<void>();
|
||||
|
||||
private readonly programmeDialog = inject(EpgProgrammeDialogService);
|
||||
private readonly translate = inject(TranslateService);
|
||||
|
||||
Reference in new issue
Block a user