diff --git a/src/app/xtream/season-container/season-container.component.scss b/src/app/xtream/season-container/season-container.component.scss
index d3667809a..659474277 100644
--- a/src/app/xtream/season-container/season-container.component.scss
+++ b/src/app/xtream/season-container/season-container.component.scss
@@ -13,8 +13,11 @@
.season-item,
.episode-item {
+ min-height: 100px;
+ justify-content: center;
width: 150px;
cursor: pointer;
+ display: block;
}
.episode-item {
diff --git a/src/app/xtream/serial-details/serial-details.component.html b/src/app/xtream/serial-details/serial-details.component.html
index a92230b7c..308360c52 100644
--- a/src/app/xtream/serial-details/serial-details.component.html
+++ b/src/app/xtream/serial-details/serial-details.component.html
@@ -45,5 +45,5 @@
diff --git a/src/app/xtream/serial-details/serial-details.component.ts b/src/app/xtream/serial-details/serial-details.component.ts
index 12f94cbd1..656e6ff06 100644
--- a/src/app/xtream/serial-details/serial-details.component.ts
+++ b/src/app/xtream/serial-details/serial-details.component.ts
@@ -1,12 +1,13 @@
import { JsonPipe, NgIf } from '@angular/common';
import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
-import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
-import { OPEN_MPV_PLAYER } from '../../../../shared/ipc-commands';
-import { XtreamSerieDetails } from '../../../../shared/xtream-serie-details.interface';
-import { DataService } from '../../services/data.service';
+import {
+ XtreamSerieDetails,
+ XtreamSerieEpisode,
+} from '../../../../shared/xtream-serie-details.interface';
import { selectCurrentPlaylist } from '../../state/selectors';
+import { PlayerDialogComponent } from '../player-dialog/player-dialog.component';
import { SeasonContainerComponent } from '../season-container/season-container.component';
@Component({
@@ -14,25 +15,19 @@ import { SeasonContainerComponent } from '../season-container/season-container.c
templateUrl: './serial-details.component.html',
styleUrls: ['../detail-view.scss'],
standalone: true,
- imports: [JsonPipe, MatButtonModule, NgIf, SeasonContainerComponent],
+ imports: [
+ JsonPipe,
+ MatButtonModule,
+ NgIf,
+ SeasonContainerComponent,
+ PlayerDialogComponent,
+ ],
})
export class SerialDetailsComponent {
@Input({ required: true }) item: XtreamSerieDetails;
- @Output() playClicked = new EventEmitter();
+ @Output() playClicked = new EventEmitter
();
- dialog = inject(MatDialog);
store = inject(Store);
- dataService = inject(DataService);
currentPlaylist = this.store.selectSignal(selectCurrentPlaylist);
-
- playEpisode(episode: any) {
- const { serverUrl, username, password } = this.currentPlaylist();
-
- const streamUrl = `${serverUrl}/series/${username}/${password}/${episode.id}.${episode.container_extension}`;
- /* this.dialog.open(PlayerDialogComponent, {
- data: streamUrl,
- }); */
- this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, { url: streamUrl });
- }
}
diff --git a/src/app/xtream/vod-details/vod-details.component.html b/src/app/xtream/vod-details/vod-details.component.html
index bd6e790b2..0c9202a67 100644
--- a/src/app/xtream/vod-details/vod-details.component.html
+++ b/src/app/xtream/vod-details/vod-details.component.html
@@ -41,7 +41,11 @@
{{ item.info.duration }}
-
diff --git a/src/app/xtream/vod-details/vod-details.component.ts b/src/app/xtream/vod-details/vod-details.component.ts
index 21f210392..8feeaf5f4 100644
--- a/src/app/xtream/vod-details/vod-details.component.ts
+++ b/src/app/xtream/vod-details/vod-details.component.ts
@@ -13,5 +13,5 @@ import { XtreamVodDetails } from '../../../../shared/xtream-vod-details.interfac
export class VodDetailsComponent {
@Input({ required: true }) item: XtreamVodDetails;
- @Output() playClicked = new EventEmitter();
+ @Output() playClicked = new EventEmitter();
}
diff --git a/src/app/xtream/xtream-main-container.component.html b/src/app/xtream/xtream-main-container.component.html
index 3109fba86..764ad0b6d 100644
--- a/src/app/xtream/xtream-main-container.component.html
+++ b/src/app/xtream/xtream-main-container.component.html
@@ -6,28 +6,34 @@
/>
-
+
+
+
+
+
-
+
-
+
-
+
-
+
+
diff --git a/src/app/xtream/xtream-main-container.component.scss b/src/app/xtream/xtream-main-container.component.scss
index 37eac69c2..9c3468de1 100644
--- a/src/app/xtream/xtream-main-container.component.scss
+++ b/src/app/xtream/xtream-main-container.component.scss
@@ -1,4 +1,10 @@
.container {
height: calc(100vh - 140px);
overflow-y: auto;
+ display: flex;
+ justify-content: center;
+}
+
+mat-spinner {
+ margin-top: 10px;
}
diff --git a/src/app/xtream/xtream-main-container.component.ts b/src/app/xtream/xtream-main-container.component.ts
index 8d145b947..1e9b94174 100644
--- a/src/app/xtream/xtream-main-container.component.ts
+++ b/src/app/xtream/xtream-main-container.component.ts
@@ -1,5 +1,12 @@
import { JsonPipe, KeyValuePipe, NgFor, NgIf, NgSwitch } from '@angular/common';
-import { Component, NgZone, OnInit, effect, inject } from '@angular/core';
+import {
+ Component,
+ NgZone,
+ OnInit,
+ Signal,
+ effect,
+ inject,
+} from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
@@ -28,7 +35,17 @@ import { NavigationBarComponent } from './navigation-bar/navigation-bar.componen
import { PlayerViewComponent } from './player-view/player-view.component';
import { VodDetailsComponent } from './vod-details/vod-details.component';
-import { XtreamSerieDetails } from '../../../shared/xtream-serie-details.interface';
+import { toSignal } from '@angular/core/rxjs-interop';
+import { MatDialog } from '@angular/material/dialog';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { StorageMap } from '@ngx-pwa/local-storage';
+import {
+ XtreamSerieDetails,
+ XtreamSerieEpisode,
+} from '../../../shared/xtream-serie-details.interface';
+import { Settings, VideoPlayer } from '../settings/settings.interface';
+import { STORE_KEY } from '../shared/enums/store-keys.enum';
+import { PlayerDialogComponent } from './player-dialog/player-dialog.component';
import { SerialDetailsComponent } from './serial-details/serial-details.component';
const ContentTypes = {
@@ -85,12 +102,16 @@ type LayoutView =
PlayerViewComponent,
CategoryContentViewComponent,
SerialDetailsComponent,
+ PlayerDialogComponent,
+ MatProgressSpinnerModule,
],
})
export class XtreamMainContainerComponent implements OnInit {
dataService = inject(DataService);
+ dialog = inject(MatDialog);
ngZone = inject(NgZone);
snackBar = inject(MatSnackBar);
+ storage = inject(StorageMap);
store = inject(Store);
currentPlaylist = this.store.selectSignal(selectCurrentPlaylist);
@@ -100,6 +121,10 @@ export class XtreamMainContainerComponent implements OnInit {
selectedContentType = ContentType.VODS;
currentLayout: LayoutView = 'category';
vodDetails!: XtreamVodDetails | XtreamSerieDetails;
+ settings = toSignal(
+ this.storage.get(STORE_KEY.Settings)
+ ) as Signal;
+ isLoading = true;
commandsList = [
new IpcCommand(XTREAM_RESPONSE, (response: XtreamResponse) =>
@@ -139,7 +164,6 @@ export class XtreamMainContainerComponent implements OnInit {
}
handleResponse(response: XtreamResponse) {
- console.log(response.payload);
switch (response.action) {
case XtreamCodeActions.GetSeriesCategories:
case XtreamCodeActions.GetVodCategories:
@@ -160,6 +184,7 @@ export class XtreamMainContainerComponent implements OnInit {
default:
break;
}
+ this.isLoading = false;
}
getCategories(contentType: ContentType = this.selectedContentType) {
@@ -169,7 +194,6 @@ export class XtreamMainContainerComponent implements OnInit {
this.sendRequest({ action });
}
- // TODO: MAKE IT ABSTRACT SOMEHOW
ngOnDestroy(): void {
if (this.dataService.isElectron) {
this.commandsList.forEach((command) =>
@@ -213,7 +237,7 @@ export class XtreamMainContainerComponent implements OnInit {
title: item.name,
action: XtreamCodeActions.GetLiveStreams,
});
- this.playStream(item);
+ this.playLiveStream(item);
} else if (item.series_id) {
action = XtreamCodeActions.GetSeriesInfo;
this.breadcrumbs.push({ title: item.name, action });
@@ -221,31 +245,47 @@ export class XtreamMainContainerComponent implements OnInit {
}
}
- playStream(item: XtreamLiveStream) {
- this.currentLayout = 'player';
+ playLiveStream(item: XtreamLiveStream) {
const { serverUrl, username, password } = this.currentPlaylist();
-
const streamUrl = `${serverUrl}/${item.stream_type}/${username}/${password}/${item.stream_id}.ts`;
-
- this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
- url: streamUrl,
- });
+ this.openPlayer(streamUrl, item.name);
}
- playVod() {
- this.currentLayout = 'player';
+ openPlayer(streamUrl: string, title: string) {
+ const player = this.settings().player;
+ if (player === VideoPlayer.MPV) {
+ this.currentLayout = 'player';
+ this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
+ url: streamUrl,
+ });
+ } else {
+ this.dialog.open(PlayerDialogComponent, {
+ data: { streamUrl, player, title },
+ width: '80%',
+ });
+ }
+ }
+
+ playVod(vodItem: XtreamVodDetails) {
const { serverUrl, username, password } = this.currentPlaylist();
-
this.items = [];
- const streamUrl = `${serverUrl}/movie/${username}/${password}/${
- (this.vodDetails as XtreamVodDetails).movie_data.stream_id
- }.${
- (this.vodDetails as XtreamVodDetails).movie_data.container_extension
- }`;
+ const streamUrl = `${serverUrl}/movie/${username}/${password}/${vodItem.movie_data.stream_id}.${vodItem.movie_data.container_extension}`;
- this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
- url: streamUrl,
- });
+ this.openPlayer(streamUrl, vodItem.info.name);
+ }
+
+ playEpisode(episode: XtreamSerieEpisode) {
+ const { serverUrl, username, password } = this.currentPlaylist();
+ const player = this.settings().player;
+ const streamUrl = `${serverUrl}/series/${username}/${password}/${episode.id}.${episode.container_extension}`;
+ if (player === VideoPlayer.MPV) {
+ this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, { url: streamUrl });
+ } else {
+ this.dialog.open(PlayerDialogComponent, {
+ data: { streamUrl, player, title: episode.title },
+ width: '80%',
+ });
+ }
}
changeContentType(contentType: ContentType) {
@@ -261,6 +301,7 @@ export class XtreamMainContainerComponent implements OnInit {
null,
{ duration: 4000 }
);
+ this.isLoading = false;
}
/**
@@ -313,6 +354,7 @@ export class XtreamMainContainerComponent implements OnInit {
}
sendRequest(params: Record) {
+ this.isLoading = true;
const { serverUrl, username, password } = this.currentPlaylist();
this.dataService.sendIpcEvent(XTREAM_REQUEST, {
url: serverUrl,