mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-13 12:36:15 -08:00
136 lines
4.1 KiB
TypeScript
136 lines
4.1 KiB
TypeScript
import {
|
|
ChangeDetectionStrategy,
|
|
Component,
|
|
computed,
|
|
effect,
|
|
inject,
|
|
input,
|
|
output,
|
|
signal,
|
|
} from '@angular/core';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatIcon } from '@angular/material/icon';
|
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
import { TranslatePipe } from '@ngx-translate/core';
|
|
import { ExternalPlayerSession } from '@iptvnator/shared/interfaces';
|
|
import { SettingsStore } from '@iptvnator/services';
|
|
import { applyChannelNameStrip } from '@iptvnator/shared/m3u-utils';
|
|
|
|
@Component({
|
|
selector: 'app-external-playback-dock',
|
|
imports: [
|
|
MatButtonModule,
|
|
MatIcon,
|
|
MatProgressSpinnerModule,
|
|
TranslatePipe,
|
|
],
|
|
templateUrl: './external-playback-dock.component.html',
|
|
styleUrl: './external-playback-dock.component.scss',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
})
|
|
export class ExternalPlaybackDockComponent {
|
|
private readonly settingsStore = inject(SettingsStore);
|
|
|
|
readonly session = input.required<ExternalPlayerSession>();
|
|
readonly compact = input(false);
|
|
|
|
readonly closeClicked = output<void>();
|
|
readonly dismissClicked = output<void>();
|
|
readonly artworkClicked = output<void>();
|
|
private readonly artworkFailed = signal(false);
|
|
|
|
/**
|
|
* Sessions with contentInfo are tracked VOD/episode playback — their
|
|
* titles are movie/episode names, so the channel-prefix strip is
|
|
* applied only to sessions without it (live channels).
|
|
*/
|
|
readonly displayTitle = computed(() =>
|
|
applyChannelNameStrip(
|
|
this.session().title,
|
|
!this.session().contentInfo &&
|
|
this.settingsStore.stripCountryPrefix?.()
|
|
)
|
|
);
|
|
|
|
readonly playerLabel = computed(() => this.session().player.toUpperCase());
|
|
readonly artworkUrl = computed(
|
|
() => this.session().thumbnail?.trim() ?? ''
|
|
);
|
|
readonly statusLabelKey = computed(() => {
|
|
const session = this.session();
|
|
|
|
switch (session.status) {
|
|
case 'launching':
|
|
return 'WORKSPACE.SHELL.EXTERNAL_PLAYBACK_OPENING';
|
|
case 'opened':
|
|
return 'WORKSPACE.SHELL.EXTERNAL_PLAYBACK_STARTED';
|
|
case 'playing':
|
|
return 'WORKSPACE.SHELL.EXTERNAL_PLAYBACK_PLAYING';
|
|
case 'error':
|
|
return 'WORKSPACE.SHELL.EXTERNAL_PLAYBACK_FAILED';
|
|
default:
|
|
return 'WORKSPACE.SHELL.EXTERNAL_PLAYBACK_CLOSED';
|
|
}
|
|
});
|
|
|
|
readonly statusIcon = computed(() => {
|
|
const status = this.session().status;
|
|
if (status === 'error') return 'error_outline';
|
|
if (status === 'playing') return 'play_circle';
|
|
return 'open_in_new';
|
|
});
|
|
|
|
readonly showSpinner = computed(
|
|
() => this.session().status === 'launching'
|
|
);
|
|
readonly showStatusIcon = computed(
|
|
() => this.session().status !== 'launching'
|
|
);
|
|
readonly showArtwork = computed(
|
|
() => !!this.artworkUrl() && !this.artworkFailed()
|
|
);
|
|
readonly artworkPlaceholderIcon = computed(() => {
|
|
const contentType = this.session().contentInfo?.contentType;
|
|
|
|
switch (contentType) {
|
|
case 'vod':
|
|
return 'movie';
|
|
case 'episode':
|
|
return 'video_library';
|
|
default:
|
|
return 'live_tv';
|
|
}
|
|
});
|
|
readonly artworkInteractive = computed(
|
|
() => !!this.session().contentInfo?.playlistId
|
|
);
|
|
readonly showCloseAction = computed(() => this.session().canClose);
|
|
readonly showDismissAction = computed(
|
|
() => this.session().status === 'error' && !this.session().canClose
|
|
);
|
|
|
|
constructor() {
|
|
effect(() => {
|
|
this.artworkUrl();
|
|
this.artworkFailed.set(false);
|
|
});
|
|
}
|
|
|
|
onArtworkError(): void {
|
|
this.artworkFailed.set(true);
|
|
}
|
|
|
|
onArtworkClick(): void {
|
|
if (!this.artworkInteractive()) return;
|
|
this.artworkClicked.emit();
|
|
}
|
|
|
|
onCloseClick(): void {
|
|
this.closeClicked.emit();
|
|
}
|
|
|
|
onDismissClick(): void {
|
|
this.dismissClicked.emit();
|
|
}
|
|
}
|