Files
iptvnator/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts
T

177 lines
6.0 KiB
TypeScript

import {
afterNextRender,
ChangeDetectionStrategy,
Component,
computed,
ElementRef,
inject,
Injector,
OnInit,
viewChild,
} from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatIconButton } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIcon } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { MatTooltipModule } from '@angular/material/tooltip';
import { ActivatedRoute } from '@angular/router';
import { TranslatePipe } from '@ngx-translate/core';
import { PlaylistSwitcherComponent, ResizableDirective } from 'components';
import { XtreamCategory } from 'shared-interfaces';
import { EpgViewComponent, WebPlayerViewComponent } from 'shared-portals';
import { SettingsStore } from '../../services/settings-store.service';
import {
CategoryManagementDialogComponent,
CategoryManagementDialogData,
} from '../category-management-dialog/category-management-dialog.component';
import {
CategoryViewComponent,
} from '../category-view/category-view.component';
import { PortalChannelsListComponent } from '../portal-channels-list/portal-channels-list.component';
import { FavoritesService } from '../services/favorites.service';
import { XtreamStore } from '../stores/xtream.store';
@Component({
selector: 'app-live-stream-layout',
templateUrl: './live-stream-layout.component.html',
styleUrls: ['./live-stream-layout.component.scss', '../sidebar.scss'],
imports: [
CategoryViewComponent,
EpgViewComponent,
FormsModule,
MatFormFieldModule,
MatIcon,
MatIconButton,
MatInputModule,
MatListModule,
MatTooltipModule,
/* MpvPlayerBarComponent, */
PlaylistSwitcherComponent,
PortalChannelsListComponent,
ResizableDirective,
TranslatePipe,
WebPlayerViewComponent,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class LiveStreamLayoutComponent implements OnInit {
private readonly favoritesService = inject(FavoritesService);
private readonly xtreamStore = inject(XtreamStore);
private readonly settingsStore = inject(SettingsStore);
private readonly dialog = inject(MatDialog);
private readonly route = inject(ActivatedRoute);
readonly categories = this.xtreamStore.getCategoriesBySelectedType;
readonly categoryItemCounts = this.xtreamStore.getCategoryItemCounts;
readonly currentPlaylist = this.xtreamStore.currentPlaylist;
readonly epgItems = this.xtreamStore.epgItems;
readonly selectedCategoryId = this.xtreamStore.selectedCategoryId;
readonly selectedCategoryInfo = computed(() => {
const categoryId = this.selectedCategoryId();
if (!categoryId) return null;
const categories = this.categories();
const category = categories?.find(
(c: any) => (c.category_id ?? c.id) === categoryId
);
const count = this.categoryItemCounts()?.get(categoryId) ?? 0;
return {
name: category?.category_name ?? category?.name ?? 'Channels',
count,
};
});
private readonly injector = inject(Injector);
private readonly categoryView = viewChild(CategoryViewComponent, {
read: ElementRef,
});
private categoryScrollTop = 0;
readonly player = this.settingsStore.player;
streamUrl: string;
favorites = new Map<number, boolean>();
ngOnInit() {
const playlist = this.xtreamStore.currentPlaylist();
if (playlist) {
this.favoritesService
.getFavorites(playlist.id)
.subscribe((favorites) => {
// Map using content.id instead of xtream_id
favorites.forEach((fav: any) => {
this.favorites.set(fav.xtream_id, true);
});
});
}
const categoryId = this.route.firstChild?.snapshot.params['categoryId'];
if (categoryId)
this.xtreamStore.setSelectedCategory(Number(categoryId));
}
playLive(item: any) {
const streamUrl = this.xtreamStore.constructStreamUrl(item);
this.streamUrl = streamUrl;
const isEmbeddedPlayer =
this.player() === 'videojs' ||
this.player() === 'html5' ||
this.player() === 'artplayer';
if (isEmbeddedPlayer) {
return;
}
this.xtreamStore.openPlayer(streamUrl, item.title, item.poster_url);
}
selectCategory(category: XtreamCategory) {
const el = this.categoryView()?.nativeElement;
if (el) {
this.categoryScrollTop = el.scrollTop;
}
const categoryId = (category as any).category_id ?? category.id;
this.xtreamStore.setSelectedCategory(categoryId);
}
backToCategories() {
this.xtreamStore.setSelectedCategory(null);
afterNextRender(
() => {
const el = this.categoryView()?.nativeElement;
if (el) {
el.scrollTop = this.categoryScrollTop;
}
},
{ injector: this.injector }
);
}
openCategoryManagement(): void {
const playlistId = this.route.parent?.snapshot.params['id'];
const contentType = this.xtreamStore.selectedContentType();
const dialogRef = this.dialog.open<
CategoryManagementDialogComponent,
CategoryManagementDialogData,
boolean
>(CategoryManagementDialogComponent, {
data: {
playlistId,
contentType,
itemCounts: this.categoryItemCounts(),
},
width: '500px',
maxHeight: '80vh',
});
dialogRef.afterClosed().subscribe((result) => {
if (result) {
this.xtreamStore.reloadCategories();
}
});
}
}