diff --git a/apps/electron-backend/src/app/api/main.preload.ts b/apps/electron-backend/src/app/api/main.preload.ts
index 00eb3efba..b3726b765 100644
--- a/apps/electron-backend/src/app/api/main.preload.ts
+++ b/apps/electron-backend/src/app/api/main.preload.ts
@@ -3,8 +3,8 @@ import { contextBridge, ipcRenderer } from 'electron';
contextBridge.exposeInMainWorld('electron', {
getAppVersion: () => ipcRenderer.invoke('get-app-version'),
platform: process.platform,
- fetchPlaylistByUrl: (url: string) =>
- ipcRenderer.invoke('fetch-playlist-by-url', url),
+ fetchPlaylistByUrl: (url: string, title?: string) =>
+ ipcRenderer.invoke('fetch-playlist-by-url', url, title),
updatePlaylistFromFilePath: (filePath: string, title: string) =>
ipcRenderer.invoke('update-playlist-from-file-path', filePath, title),
openPlaylistFromFile: () => ipcRenderer.invoke('open-playlist-from-file'),
diff --git a/apps/electron-backend/src/app/events/playlist.events.ts b/apps/electron-backend/src/app/events/playlist.events.ts
index 81cecee45..25a4da892 100644
--- a/apps/electron-backend/src/app/events/playlist.events.ts
+++ b/apps/electron-backend/src/app/events/playlist.events.ts
@@ -17,7 +17,7 @@ export default class PlaylistEvents {
const https = require('https');
-ipcMain.handle('fetch-playlist-by-url', async (event, url) => {
+ipcMain.handle('fetch-playlist-by-url', async (event, url, title?: string) => {
try {
const agent = new https.Agent({
rejectUnauthorized: false,
@@ -33,7 +33,7 @@ ipcMain.handle('fetch-playlist-by-url', async (event, url) => {
: extractedName;
const playlistObject = createPlaylistObject(
- playlistName,
+ title ?? playlistName,
parsedPlaylist,
url,
'URL'
@@ -62,7 +62,6 @@ ipcMain.handle(
);
ipcMain.handle('open-playlist-from-file', async () => {
- // 1. Await the result from the dialog
const { canceled, filePaths } = await dialog.showOpenDialog({
properties: ['openFile'],
filters: [
@@ -89,13 +88,9 @@ ipcMain.handle('open-playlist-from-file', async () => {
'FILE'
);
- console.log('Sending playlist object to renderer:', playlistObject);
-
- // 5. Return the final object. This value is sent back to Angular.
return playlistObject;
} catch (error) {
console.error('Error reading or parsing the file:', error);
- // It's good practice to throw the error so the renderer can catch it
throw new Error('Failed to process the selected file.');
}
});
diff --git a/apps/web/src/app/services/tauri.service.ts b/apps/web/src/app/services/tauri.service.ts
index a0ee902f8..c5fc6dec7 100644
--- a/apps/web/src/app/services/tauri.service.ts
+++ b/apps/web/src/app/services/tauri.service.ts
@@ -1,6 +1,7 @@
import { inject, Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Params } from '@angular/router';
+import { DataService } from '@iptvnator/services';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
import { readTextFile } from '@tauri-apps/plugin-fs';
@@ -19,7 +20,6 @@ import {
PLAYLIST_UPDATE_RESPONSE,
XTREAM_RESPONSE,
} from 'shared-interfaces';
-import { DataService } from '../../../../../libs/services/src/lib/data.service';
import { AppConfig } from '../../environments/environment';
@Injectable({
@@ -58,11 +58,11 @@ export class TauriService extends DataService {
if (type === PLAYLIST_PARSE_BY_URL) {
this.fetchM3uPlaylistFromUrl(payload);
} else if (type === PLAYLIST_UPDATE) {
- // TODO: update playlist from URL?
this.updateM3uPlaylistFromFile(
payload as {
id: string;
- filePath: string;
+ filePath?: string;
+ url?: string;
title: string;
}
);
@@ -201,24 +201,42 @@ export class TauriService extends DataService {
private async updateM3uPlaylistFromFile(data: {
id: string;
- filePath: string;
+ url?: string;
+ filePath?: string;
title: string;
}) {
- window.electron
- .updatePlaylistFromFilePath(data.filePath, data.title)
- .then((playlistObject) => {
- window.postMessage({
- type: PLAYLIST_UPDATE_RESPONSE,
- payload: {
- message:
- 'Success! The playlist was successfully updated',
- playlist: {
- ...playlistObject,
- _id: data.id,
- },
+ let methodToCall = null;
+ if (data.url && !data.filePath) {
+ // fetch from url
+ methodToCall = window.electron.fetchPlaylistByUrl(
+ data.url,
+ data.title
+ );
+ } else if (data.filePath && !data.url) {
+ // update from file path
+ methodToCall = window.electron.updatePlaylistFromFilePath(
+ data.filePath,
+ data.title
+ );
+ } else {
+ console.error(
+ 'Either url or filePath must be provided, but not both.'
+ );
+ return;
+ }
+
+ methodToCall.then((playlistObject) => {
+ window.postMessage({
+ type: PLAYLIST_UPDATE_RESPONSE,
+ payload: {
+ message: 'Success! The playlist was successfully updated',
+ playlist: {
+ ...playlistObject,
+ _id: data.id,
},
- });
+ },
});
+ });
}
/* private getErrorMessageByStatusCode(status: number) {
diff --git a/apps/web/src/app/shared/components/about-dialog/about-dialog.component.ts b/apps/web/src/app/shared/components/about-dialog/about-dialog.component.ts
index 459c32b39..f480c518e 100644
--- a/apps/web/src/app/shared/components/about-dialog/about-dialog.component.ts
+++ b/apps/web/src/app/shared/components/about-dialog/about-dialog.component.ts
@@ -1,4 +1,4 @@
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { TranslateModule } from '@ngx-translate/core';
@@ -7,7 +7,11 @@ import { TranslateModule } from '@ngx-translate/core';
imports: [MatIconModule, TranslateModule],
template: `
-

+
{{ 'ABOUT.TITLE' | translate }}
{{ 'ABOUT.DESCRIPTION' | translate }}
{{ 'ABOUT.VERSION' | translate }}: {{ appVersion }}
@@ -19,7 +23,8 @@ import { TranslateModule } from '@ngx-translate/core';
[attr.aria-label]="'ABOUT.GITHUB_TOOLTIP' | translate"
>
(MAT_DIALOG_DATA);
}
diff --git a/apps/web/src/app/shared/components/add-playlist/add-playlist-dialog.component.ts b/apps/web/src/app/shared/components/add-playlist/add-playlist-dialog.component.ts
index 10be580b8..d0619474e 100644
--- a/apps/web/src/app/shared/components/add-playlist/add-playlist-dialog.component.ts
+++ b/apps/web/src/app/shared/components/add-playlist/add-playlist-dialog.component.ts
@@ -1,4 +1,4 @@
-import { Component, inject, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import {
MAT_DIALOG_DATA,
@@ -22,14 +22,14 @@ export type PlaylistType = 'xtream' | 'url' | 'text' | 'file' | 'stalker';
@Component({
imports: [
+ FileUploadComponent,
MatButtonModule,
MatDialogModule,
- TranslateModule,
- FileUploadComponent,
- XtreamCodeImportComponent,
StalkerPortalImportComponent,
TextImportComponent,
+ TranslateModule,
UrlUploadComponent,
+ XtreamCodeImportComponent,
],
selector: 'app-add-playlist',
templateUrl: './add-playlist-dialog.component.html',
@@ -40,11 +40,12 @@ export class AddPlaylistDialogComponent {
private store = inject(Store);
private snackBar = inject(MatSnackBar);
private translateService = inject(TranslateService);
+ readonly data = inject<{ type: PlaylistType }>(MAT_DIALOG_DATA);
readonly playlistType!: PlaylistType;
- constructor(@Inject(MAT_DIALOG_DATA) data: { type: PlaylistType }) {
- this.playlistType = data.type;
+ constructor() {
+ this.playlistType = this.data.type;
}
/**
diff --git a/apps/web/src/app/shared/components/confirm-dialog/confirm-dialog-data.interface.ts b/apps/web/src/app/shared/components/confirm-dialog/confirm-dialog-data.interface.ts
deleted file mode 100644
index 691695278..000000000
--- a/apps/web/src/app/shared/components/confirm-dialog/confirm-dialog-data.interface.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export interface ConfirmDialogData {
- title: string;
- message: string;
- confirmLabel?: string;
- cancelLabel?: string;
- onConfirm: () => void;
-}
diff --git a/apps/web/src/app/shared/components/external-player-info-dialog/external-player-info-dialog.component.ts b/apps/web/src/app/shared/components/external-player-info-dialog/external-player-info-dialog.component.ts
index 999bfeb98..7e3bcb30b 100644
--- a/apps/web/src/app/shared/components/external-player-info-dialog/external-player-info-dialog.component.ts
+++ b/apps/web/src/app/shared/components/external-player-info-dialog/external-player-info-dialog.component.ts
@@ -65,10 +65,11 @@ import { PortalStore } from '../../../xtream/portal.store';
MatIconModule,
RouterLink,
TranslateModule,
- ]
+ ],
})
export class ExternalPlayerInfoDialogComponent {
- portalStore = inject(PortalStore);
+ readonly portalStore = inject(PortalStore);
+
openUrl(url: string) {
window.open(url, '_blank');
}
diff --git a/apps/web/src/app/shared/components/header/header.component.ts b/apps/web/src/app/shared/components/header/header.component.ts
index c6751f282..1f3bffaba 100644
--- a/apps/web/src/app/shared/components/header/header.component.ts
+++ b/apps/web/src/app/shared/components/header/header.component.ts
@@ -9,16 +9,16 @@ import { MatMenuModule } from '@angular/material/menu';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { ActivatedRoute, Router } from '@angular/router';
+import {
+ DataService,
+ SortBy,
+ SortOrder,
+ SortService,
+} from '@iptvnator/services';
import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
import { open } from '@tauri-apps/plugin-shell';
import { selectActiveTypeFilters, setSelectedFilters } from 'm3u-state';
-import { DataService } from '../../../../../../../libs/services/src/lib/data.service';
-import {
- SortBy,
- SortOrder,
- SortService,
-} from '../../../../../../../libs/services/src/lib/sort.service';
import { HomeComponent } from '../../../home/home.component';
import { AboutDialogComponent } from '../about-dialog/about-dialog.component';
import {
diff --git a/apps/web/src/app/stalker/stalker-content-types.ts b/apps/web/src/app/stalker/stalker-content-types.ts
index 79e5b7497..cf969457e 100644
--- a/apps/web/src/app/stalker/stalker-content-types.ts
+++ b/apps/web/src/app/stalker/stalker-content-types.ts
@@ -1,4 +1,4 @@
-import { StalkerPortalActions } from '../../shared/stalker-portal-actions.enum';
+import { StalkerPortalActions } from 'shared-interfaces';
export const StalkerContentTypes = {
stb: {
diff --git a/apps/web/src/app/stalker/stalker-search/stalker-search.component.ts b/apps/web/src/app/stalker/stalker-search/stalker-search.component.ts
index bff341d46..d42787f90 100644
--- a/apps/web/src/app/stalker/stalker-search/stalker-search.component.ts
+++ b/apps/web/src/app/stalker/stalker-search/stalker-search.component.ts
@@ -4,12 +4,11 @@ import { MatCardModule } from '@angular/material/card';
import { MatIcon } from '@angular/material/icon';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { ActivatedRoute } from '@angular/router';
+import { DataService } from '@iptvnator/services';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
import { selectPlaylistById } from 'm3u-state';
-import { STALKER_REQUEST } from 'shared-interfaces';
-import { DataService } from '../../../../../../libs/services/src/lib/data.service';
-import { StalkerPortalActions } from '../../../shared/stalker-portal-actions.enum';
+import { STALKER_REQUEST, StalkerPortalActions } from 'shared-interfaces';
import { SearchFormComponent } from '../../shared/components/search-form/search-form.component';
import { SearchResultItemComponent } from '../../shared/components/search-result-item/search-result-item.component';
import { PlaylistErrorViewComponent } from '../../xtream-tauri/playlist-error-view/playlist-error-view.component';
diff --git a/apps/web/src/app/stalker/stalker.store.ts b/apps/web/src/app/stalker/stalker.store.ts
index 1d9d30799..590364dc3 100644
--- a/apps/web/src/app/stalker/stalker.store.ts
+++ b/apps/web/src/app/stalker/stalker.store.ts
@@ -1,5 +1,6 @@
import { computed, inject, resource, signal } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
+import { DataService, PlaylistsService } from '@iptvnator/services';
import {
patchState,
signalStore,
@@ -9,10 +10,11 @@ import {
withState,
} from '@ngrx/signals';
import { TranslateService } from '@ngx-translate/core';
-import { PlaylistMeta, STALKER_REQUEST } from 'shared-interfaces';
-import { DataService } from '../../../../../libs/services/src/lib/data.service';
-import { PlaylistsService } from '../../../../../libs/services/src/lib/playlists.service';
-import { StalkerPortalActions } from '../../shared/stalker-portal-actions.enum';
+import {
+ PlaylistMeta,
+ STALKER_REQUEST,
+ StalkerPortalActions,
+} from 'shared-interfaces';
import { PlayerService } from '../services/player.service';
import { ContentType } from '../xtream/content-type.enum';
import { StalkerSeason } from './models/stalker-season.interface';
diff --git a/apps/web/src/app/xtream-tauri/category-view/category-view.component.ts b/apps/web/src/app/xtream-tauri/category-view/category-view.component.ts
index 673481715..2f5a3d395 100644
--- a/apps/web/src/app/xtream-tauri/category-view/category-view.component.ts
+++ b/apps/web/src/app/xtream-tauri/category-view/category-view.component.ts
@@ -6,7 +6,7 @@ import {
} from '@angular/core';
import { MatListModule } from '@angular/material/list';
import { TranslatePipe } from '@ngx-translate/core';
-import { XtreamCategory } from '../../../shared/xtream-category.interface';
+import { XtreamCategory } from 'shared-interfaces';
import { PlaylistErrorViewComponent } from '../playlist-error-view/playlist-error-view.component';
@Component({
diff --git a/apps/web/src/app/xtream-tauri/favorites/favorites.component.ts b/apps/web/src/app/xtream-tauri/favorites/favorites.component.ts
index a43a49600..ff1af6c1d 100644
--- a/apps/web/src/app/xtream-tauri/favorites/favorites.component.ts
+++ b/apps/web/src/app/xtream-tauri/favorites/favorites.component.ts
@@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { Store } from '@ngrx/store';
import { selectActivePlaylist } from 'm3u-state';
import { BehaviorSubject, switchMap } from 'rxjs';
-import { XtreamCategory } from '../../../shared/xtream-category.interface';
+import { XtreamCategory } from 'shared-interfaces';
import { FavoritesLayoutComponent } from '../../shared/components/favorites-layout/favorites-layout.component';
import { FavoriteItem } from '../services/favorite-item.interface';
import { FavoritesService } from '../services/favorites.service';
diff --git a/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts b/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts
index c75d0c89b..759f0ff8e 100644
--- a/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts
+++ b/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts
@@ -12,7 +12,7 @@ import { MatInputModule } from '@angular/material/input';
import { MatListModule } from '@angular/material/list';
import { ActivatedRoute } from '@angular/router';
import { TranslatePipe } from '@ngx-translate/core';
-import { XtreamCategory } from '../../../shared/xtream-category.interface';
+import { XtreamCategory } from 'shared-interfaces';
import { EpgViewComponent, WebPlayerViewComponent } from 'shared-portals';
import { SettingsStore } from '../../services/settings-store.service';
import { MpvPlayerBarComponent } from '../../shared/components/mpv-player-bar/mpv-player-bar.component';
diff --git a/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.ts b/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.ts
index 62ad16e0a..bf64b76bd 100644
--- a/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.ts
+++ b/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.ts
@@ -24,8 +24,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
import { ActivatedRoute } from '@angular/router';
import { FilterPipe } from '@iptvnator/pipes';
import { TranslatePipe } from '@ngx-translate/core';
-import { XtreamItem } from '../../../../../../libs/shared/interfaces/src/lib/xtream-item.interface';
-import { XtreamCategory } from '../../../shared/xtream-category.interface';
+import { XtreamCategory, XtreamItem } from 'shared-interfaces';
import { FavoritesService } from '../services/favorites.service';
import { XtreamStore } from '../xtream.store';
diff --git a/apps/web/src/app/xtream-tauri/season-container/season-container.component.ts b/apps/web/src/app/xtream-tauri/season-container/season-container.component.ts
index de4f2ecf4..b8675228f 100644
--- a/apps/web/src/app/xtream-tauri/season-container/season-container.component.ts
+++ b/apps/web/src/app/xtream-tauri/season-container/season-container.component.ts
@@ -3,7 +3,7 @@ import { Component, EventEmitter, Output, input } from '@angular/core';
import { MatButton } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatIcon } from '@angular/material/icon';
-import { XtreamSerieEpisode } from '../../../shared/xtream-serie-details.interface';
+import { XtreamSerieEpisode } from 'shared-interfaces';
@Component({
selector: 'app-season-container',
diff --git a/apps/web/src/app/xtream-tauri/serial-details/serial-details.component.ts b/apps/web/src/app/xtream-tauri/serial-details/serial-details.component.ts
index ed601489f..fe6961ef3 100644
--- a/apps/web/src/app/xtream-tauri/serial-details/serial-details.component.ts
+++ b/apps/web/src/app/xtream-tauri/serial-details/serial-details.component.ts
@@ -3,7 +3,7 @@ import { MatButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { ActivatedRoute } from '@angular/router';
import { TranslatePipe } from '@ngx-translate/core';
-import { XtreamSerieEpisode } from '../../../shared/xtream-serie-details.interface';
+import { XtreamSerieEpisode } from 'shared-interfaces';
import { SeasonContainerComponent } from '../season-container/season-container.component';
import { XtreamStore } from '../xtream.store';
diff --git a/apps/web/src/app/xtream-tauri/vod-details/vod-details.component.ts b/apps/web/src/app/xtream-tauri/vod-details/vod-details.component.ts
index 3af52fd6e..8719fb69a 100644
--- a/apps/web/src/app/xtream-tauri/vod-details/vod-details.component.ts
+++ b/apps/web/src/app/xtream-tauri/vod-details/vod-details.component.ts
@@ -4,7 +4,7 @@ import { MatIcon } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ActivatedRoute } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
-import { XtreamVodDetails } from '../../../shared/xtream-vod-details.interface';
+import { XtreamVodDetails } from 'shared-interfaces';
import { SettingsStore } from '../../services/settings-store.service';
import { XtreamStore } from '../xtream.store';
import { SafePipe } from './safe.pipe';
diff --git a/apps/web/src/app/xtream-tauri/xtream-main-container.component.ts b/apps/web/src/app/xtream-tauri/xtream-main-container.component.ts
index c974ac0fb..a30554f57 100644
--- a/apps/web/src/app/xtream-tauri/xtream-main-container.component.ts
+++ b/apps/web/src/app/xtream-tauri/xtream-main-container.component.ts
@@ -1,12 +1,11 @@
import { Component, inject, OnInit } from '@angular/core';
-import { CategoryViewComponent } from './category-view/category-view.component';
-
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
-import { XtreamCategory } from '../../shared/xtream-category.interface';
+import { XtreamCategory } from 'shared-interfaces';
import { MpvPlayerBarComponent } from '../shared/components/mpv-player-bar/mpv-player-bar.component';
+import { CategoryViewComponent } from './category-view/category-view.component';
import { XtreamStore } from './xtream.store';
@Component({
diff --git a/apps/web/src/app/xtream-tauri/xtream-state.ts b/apps/web/src/app/xtream-tauri/xtream-state.ts
index 9e9556a88..6db484855 100644
--- a/apps/web/src/app/xtream-tauri/xtream-state.ts
+++ b/apps/web/src/app/xtream-tauri/xtream-state.ts
@@ -1,9 +1,11 @@
-import { GlobalSearchResult } from '../../../../../libs/services/src/lib/database.service';
-import { EpgItem } from '../../../../../libs/shared/interfaces/src/lib/epg-item.interface';
-import { XtreamSerieItem } from '../../../../../libs/shared/interfaces/src/lib/xtream-serie-item.interface';
-import { XtreamCategory } from '../../shared/xtream-category.interface';
-import { XtreamLiveStream } from '../../shared/xtream-live-stream.interface';
-import { XtreamVodStream } from '../../shared/xtream-vod-stream.interface';
+import { GlobalSearchResult } from '@iptvnator/services';
+import {
+ EpgItem,
+ XtreamCategory,
+ XtreamLiveStream,
+ XtreamSerieItem,
+ XtreamVodStream,
+} from 'shared-interfaces';
export type ContentType = 'live' | 'vod' | 'series';
diff --git a/apps/web/src/app/xtream-tauri/xtream.store.ts b/apps/web/src/app/xtream-tauri/xtream.store.ts
index 84997f539..26722b1b0 100644
--- a/apps/web/src/app/xtream-tauri/xtream.store.ts
+++ b/apps/web/src/app/xtream-tauri/xtream.store.ts
@@ -1,5 +1,6 @@
import { computed, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
+import { DatabaseService, DataService } from '@iptvnator/services';
import {
patchState,
signalStore,
@@ -20,15 +21,13 @@ import {
switchMap,
tap,
} from 'rxjs';
-import { Playlist } from 'shared-interfaces';
-import { DataService } from '../../../../../libs/services/src/lib/data.service';
-import { DatabaseService } from '../../../../../libs/services/src/lib/database.service';
-import { XtreamCodeActions } from '../../shared/xtream-code-actions';
import {
+ Playlist,
+ XtreamCodeActions,
XtreamSerieDetails,
XtreamSerieEpisode,
-} from '../../shared/xtream-serie-details.interface';
-import { XtreamVodDetails } from '../../shared/xtream-vod-details.interface';
+ XtreamVodDetails,
+} from 'shared-interfaces';
import { PlayerService } from '../services/player.service';
import { SettingsStore } from '../services/settings-store.service';
import { XtreamAccountInfo } from './account-info/account-info.interface';
@@ -85,8 +84,8 @@ export const XtreamStore = signalStore(
return type === 'live'
? store.liveCategories()
: type === 'vod'
- ? store.vodCategories()
- : store.serialCategories();
+ ? store.vodCategories()
+ : store.serialCategories();
}),
getSelectedCategory: computed(() => {
const categoryId = store.selectedCategoryId();
@@ -103,8 +102,8 @@ export const XtreamStore = signalStore(
categoryType === 'live'
? store.liveStreams()
: categoryType === 'vod'
- ? store.vodStreams()
- : store.serialStreams();
+ ? store.vodStreams()
+ : store.serialStreams();
if (!store.selectedItem()) return null;
@@ -129,8 +128,8 @@ export const XtreamStore = signalStore(
categoryType === 'live'
? store.liveStreams()
: categoryType === 'vod'
- ? store.vodStreams()
- : store.serialStreams();
+ ? store.vodStreams()
+ : store.serialStreams();
return content
.filter((item) => item.category_id === categoryId)
@@ -149,13 +148,13 @@ export const XtreamStore = signalStore(
.filter((i) => Number((i as any).id) === categoryId)
.length
: categoryType === 'vod'
- ? store
- .vodStreams()
- .filter((i) => Number(i.category_id) === categoryId)
- .length
- : store
- .serialStreams()
- .filter((i) => i.category_id === categoryId).length;
+ ? store
+ .vodStreams()
+ .filter((i) => Number(i.category_id) === categoryId)
+ .length
+ : store
+ .serialStreams()
+ .filter((i) => i.category_id === categoryId).length;
return Math.ceil(totalItems / store.limit());
}),
@@ -166,8 +165,8 @@ export const XtreamStore = signalStore(
categoryType === 'live'
? store.liveStreams()
: categoryType === 'vod'
- ? store.vodStreams()
- : store.serialStreams();
+ ? store.vodStreams()
+ : store.serialStreams();
return content.filter((item) => item.category_id === categoryId);
}),
@@ -223,7 +222,9 @@ export const XtreamStore = signalStore(
}
const remoteData = await dataService.fetchData(
- `${store.currentPlaylist().serverUrl}/player_api.php`,
+ `${
+ store.currentPlaylist().serverUrl
+ }/player_api.php`,
queryParams
);
@@ -293,7 +294,9 @@ export const XtreamStore = signalStore(
}
const remoteData = await dataService.fetchData(
- `${store.currentPlaylist().serverUrl}/player_api.php`,
+ `${
+ store.currentPlaylist().serverUrl
+ }/player_api.php`,
queryParams
);
@@ -758,7 +761,9 @@ export const XtreamStore = signalStore(
async loadChannelEpg(streamId: number) {
try {
const response = await dataService.fetchData(
- `${store.currentPlaylist().serverUrl}/player_api.php`,
+ `${
+ store.currentPlaylist().serverUrl
+ }/player_api.php`,
{
action: 'get_short_epg',
username: store.currentPlaylist().username,
diff --git a/apps/web/src/app/xtream/breadcrumb.interface.ts b/apps/web/src/app/xtream/breadcrumb.interface.ts
index ef26fc25a..e70fcd1c7 100644
--- a/apps/web/src/app/xtream/breadcrumb.interface.ts
+++ b/apps/web/src/app/xtream/breadcrumb.interface.ts
@@ -1,5 +1,4 @@
-import { StalkerPortalActions } from '../../shared/stalker-portal-actions.enum';
-import { XtreamCodeActions } from '../../shared/xtream-code-actions';
+import { StalkerPortalActions, XtreamCodeActions } from 'shared-interfaces';
export type PortalActions = StalkerPortalActions | XtreamCodeActions;
diff --git a/apps/web/src/app/xtream/category-view/category-view.component.ts b/apps/web/src/app/xtream/category-view/category-view.component.ts
index 44fa0a8b8..8c308a56e 100644
--- a/apps/web/src/app/xtream/category-view/category-view.component.ts
+++ b/apps/web/src/app/xtream/category-view/category-view.component.ts
@@ -3,53 +3,43 @@ import { MatCardModule } from '@angular/material/card';
import { MatIconModule } from '@angular/material/icon';
import { FilterPipe } from '@iptvnator/pipes';
import { TranslateModule } from '@ngx-translate/core';
-import { XtreamCategory } from '../../../shared/xtream-category.interface';
+import { XtreamCategory } from 'shared-interfaces';
import { PlaylistErrorViewComponent } from '../playlist-error-view/playlist-error-view.component';
import { PortalStore } from '../portal.store';
@Component({
selector: 'app-category-view',
template: `
- @if (items?.length > 0) {
- @for (
- item of items() | filterBy: searchPhrase() : 'category_name';
- track $index
- ) {
-
-
- {{
- item.category_name ||
- item.name ||
- 'No category name'
- }}
-
-
- }
- @if (
- !(items() | filterBy: searchPhrase() : 'category_name')?.length
- ) {
-
- }
- } @else {
-
+ @if (items?.length > 0) { @for ( item of items() | filterBy:
+ searchPhrase() : 'category_name'; track $index ) {
+
+
+ {{ item.category_name || item.name || 'No category name' }}
+
+
+ } @if ( !(items() | filterBy: searchPhrase() : 'category_name')?.length
+ ) {
+
+ } } @else {
+
}
`,
styleUrl: './category-view.component.scss',
diff --git a/apps/web/src/app/xtream/navigation-bar/navigation-bar.component.ts b/apps/web/src/app/xtream/navigation-bar/navigation-bar.component.ts
index 8c60daad2..85f9ac241 100644
--- a/apps/web/src/app/xtream/navigation-bar/navigation-bar.component.ts
+++ b/apps/web/src/app/xtream/navigation-bar/navigation-bar.component.ts
@@ -29,7 +29,7 @@ import {
distinctUntilChanged,
map,
} from 'rxjs';
-import { XtreamLiveStream } from '../../../shared/xtream-live-stream.interface';
+import { XtreamLiveStream } from 'shared-interfaces';
import { SettingsComponent } from '../../settings/settings.component';
import { SettingsStore } from '../../services/settings-store.service';
diff --git a/apps/web/src/app/xtream/season-container/season-container.component.ts b/apps/web/src/app/xtream/season-container/season-container.component.ts
index ceec26898..3cea4ab34 100644
--- a/apps/web/src/app/xtream/season-container/season-container.component.ts
+++ b/apps/web/src/app/xtream/season-container/season-container.component.ts
@@ -1,7 +1,7 @@
import { KeyValuePipe } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
-import { XtreamSerieEpisode } from '../../../shared/xtream-serie-details.interface';
+import { XtreamSerieEpisode } from 'shared-interfaces';
@Component({
selector: 'app-season-container',
diff --git a/apps/web/src/app/xtream/serial-details/serial-details.component.ts b/apps/web/src/app/xtream/serial-details/serial-details.component.ts
index 8e19ba497..63d144726 100644
--- a/apps/web/src/app/xtream/serial-details/serial-details.component.ts
+++ b/apps/web/src/app/xtream/serial-details/serial-details.component.ts
@@ -2,14 +2,11 @@ import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { ActivatedRoute } from '@angular/router';
+import { PlaylistsService } from '@iptvnator/services';
import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
import { selectCurrentPlaylist } from 'm3u-state';
-import { PlaylistsService } from '../../../../../../libs/services/src/lib/playlists.service';
-import {
- XtreamSerieDetails,
- XtreamSerieEpisode,
-} from '../../../shared/xtream-serie-details.interface';
+import { XtreamSerieDetails, XtreamSerieEpisode } from 'shared-interfaces';
import { SeasonContainerComponent } from '../season-container/season-container.component';
@Component({
diff --git a/apps/web/src/app/xtream/vod-details/vod-details.component.ts b/apps/web/src/app/xtream/vod-details/vod-details.component.ts
index 00502bf79..648837fdf 100644
--- a/apps/web/src/app/xtream/vod-details/vod-details.component.ts
+++ b/apps/web/src/app/xtream/vod-details/vod-details.component.ts
@@ -10,9 +10,9 @@ import { MatButtonModule } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { ActivatedRoute } from '@angular/router';
+import { PlaylistsService } from '@iptvnator/services';
import { TranslatePipe } from '@ngx-translate/core';
-import { PlaylistsService } from '../../../../../../libs/services/src/lib/playlists.service';
-import { XtreamVodDetails } from '../../../shared/xtream-vod-details.interface';
+import { XtreamVodDetails } from 'shared-interfaces';
import { SafePipe } from './safe.pipe';
@Component({
diff --git a/apps/web/src/app/xtream/xtream-main-container.component.ts b/apps/web/src/app/xtream/xtream-main-container.component.ts
index 3cb46c7a1..a703b79de 100644
--- a/apps/web/src/app/xtream/xtream-main-container.component.ts
+++ b/apps/web/src/app/xtream/xtream-main-container.component.ts
@@ -14,7 +14,7 @@ import { MatDialog } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar } from '@angular/material/snack-bar';
-import { DataService } from '@iptvnator/services';
+import { DataService, PlaylistsService } from '@iptvnator/services';
import { Store } from '@ngrx/store';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { selectCurrentPlaylist } from 'm3u-state';
@@ -30,18 +30,15 @@ import {
VideoPlayer,
XTREAM_REQUEST,
XTREAM_RESPONSE,
-} from 'shared-interfaces';
-import { LiveStreamLayoutComponent } from 'shared-portals';
-import { PlaylistsService } from '../../../../../libs/services/src/lib/playlists.service';
-import { XtreamCategory } from '../../shared/xtream-category.interface';
-import { XtreamCodeActions } from '../../shared/xtream-code-actions';
-import { XtreamLiveStream } from '../../shared/xtream-live-stream.interface';
-import { XtreamResponse } from '../../shared/xtream-response.interface';
-import {
+ XtreamCategory,
+ XtreamCodeActions,
+ XtreamLiveStream,
+ XtreamResponse,
XtreamSerieDetails,
XtreamSerieEpisode,
-} from '../../shared/xtream-serie-details.interface';
-import { XtreamVodDetails } from '../../shared/xtream-vod-details.interface';
+ XtreamVodDetails,
+} from 'shared-interfaces';
+import { LiveStreamLayoutComponent } from 'shared-portals';
import { SettingsStore } from '../services/settings-store.service';
import { ExternalPlayerInfoDialogComponent } from '../shared/components/external-player-info-dialog/external-player-info-dialog.component';
import { PlaylistErrorViewComponent } from '../xtream/playlist-error-view/playlist-error-view.component';
diff --git a/apps/web/src/global.d.ts b/apps/web/src/global.d.ts
index cc3729674..bd78dad19 100644
--- a/apps/web/src/global.d.ts
+++ b/apps/web/src/global.d.ts
@@ -12,7 +12,10 @@ declare global {
electron: {
getAppVersion: () => Promise;
platform: string;
- fetchPlaylistByUrl: (url: string) => Promise;
+ fetchPlaylistByUrl: (
+ url: string,
+ title?: string
+ ) => Promise;
updatePlaylistFromFilePath: (
filePath: string,
title: string
diff --git a/libs/services/src/lib/dialog.service.ts b/libs/services/src/lib/dialog.service.ts
index 1fd99f4e5..0bef6399e 100644
--- a/libs/services/src/lib/dialog.service.ts
+++ b/libs/services/src/lib/dialog.service.ts
@@ -1,7 +1,6 @@
import { inject, Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
-import { ConfirmDialogData } from '../../../../apps/web/src/app/shared/components/confirm-dialog/confirm-dialog-data.interface';
-import { ConfirmDialogComponent } from '../../../../apps/web/src/app/shared/components/confirm-dialog/confirm-dialog.component';
+import { ConfirmDialogComponent, ConfirmDialogData } from 'components';
@Injectable({
providedIn: 'root',
diff --git a/libs/shared/interfaces/src/index.ts b/libs/shared/interfaces/src/index.ts
index 847448d24..95fb850dd 100644
--- a/libs/shared/interfaces/src/index.ts
+++ b/libs/shared/interfaces/src/index.ts
@@ -12,8 +12,16 @@ export * from './lib/parsed-playlist.interface';
export * from './lib/playlist-meta.type';
export * from './lib/playlist.interface';
export * from './lib/settings.interface';
+export * from './lib/stalker-portal-actions.enum';
export * from './lib/store-keys.enum';
export * from './lib/stream-format.enum';
export * from './lib/theme.enum';
+export * from './lib/xtream-category.interface';
+export * from './lib/xtream-code-actions';
export * from './lib/xtream-item.interface';
+export * from './lib/xtream-live-stream.interface';
+export * from './lib/xtream-response.interface';
+export * from './lib/xtream-serie-details.interface';
export * from './lib/xtream-serie-item.interface';
+export * from './lib/xtream-vod-details.interface';
+export * from './lib/xtream-vod-stream.interface';
diff --git a/apps/web/src/shared/stalker-portal-actions.enum.ts b/libs/shared/interfaces/src/lib/stalker-portal-actions.enum.ts
similarity index 100%
rename from apps/web/src/shared/stalker-portal-actions.enum.ts
rename to libs/shared/interfaces/src/lib/stalker-portal-actions.enum.ts
diff --git a/apps/web/src/shared/xtream-category.interface.ts b/libs/shared/interfaces/src/lib/xtream-category.interface.ts
similarity index 100%
rename from apps/web/src/shared/xtream-category.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-category.interface.ts
diff --git a/apps/web/src/shared/xtream-code-actions.ts b/libs/shared/interfaces/src/lib/xtream-code-actions.ts
similarity index 100%
rename from apps/web/src/shared/xtream-code-actions.ts
rename to libs/shared/interfaces/src/lib/xtream-code-actions.ts
diff --git a/apps/web/src/shared/xtream-live-stream.interface.ts b/libs/shared/interfaces/src/lib/xtream-live-stream.interface.ts
similarity index 64%
rename from apps/web/src/shared/xtream-live-stream.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-live-stream.interface.ts
index bb686e9a7..1fa44ab69 100644
--- a/apps/web/src/shared/xtream-live-stream.interface.ts
+++ b/libs/shared/interfaces/src/lib/xtream-live-stream.interface.ts
@@ -1,4 +1,4 @@
-import { XtreamItem } from '../../../../libs/shared/interfaces/src/lib/xtream-item.interface';
+import { XtreamItem } from 'shared-interfaces';
export interface XtreamLiveStream extends XtreamItem {
stream_type: 'live';
diff --git a/apps/web/src/shared/xtream-response.interface.ts b/libs/shared/interfaces/src/lib/xtream-response.interface.ts
similarity index 100%
rename from apps/web/src/shared/xtream-response.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-response.interface.ts
diff --git a/apps/web/src/shared/xtream-serie-details.interface.ts b/libs/shared/interfaces/src/lib/xtream-serie-details.interface.ts
similarity index 100%
rename from apps/web/src/shared/xtream-serie-details.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-serie-details.interface.ts
diff --git a/apps/web/src/shared/xtream-vod-details.interface.ts b/libs/shared/interfaces/src/lib/xtream-vod-details.interface.ts
similarity index 100%
rename from apps/web/src/shared/xtream-vod-details.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-vod-details.interface.ts
diff --git a/apps/web/src/shared/xtream-vod-stream.interface.ts b/libs/shared/interfaces/src/lib/xtream-vod-stream.interface.ts
similarity index 63%
rename from apps/web/src/shared/xtream-vod-stream.interface.ts
rename to libs/shared/interfaces/src/lib/xtream-vod-stream.interface.ts
index 3959cfb3c..ecf3c95d6 100644
--- a/apps/web/src/shared/xtream-vod-stream.interface.ts
+++ b/libs/shared/interfaces/src/lib/xtream-vod-stream.interface.ts
@@ -1,4 +1,4 @@
-import { XtreamItem } from '../../../../libs/shared/interfaces/src/lib/xtream-item.interface';
+import { XtreamItem } from 'shared-interfaces';
export interface XtreamVodStream extends XtreamItem {
stream_type: 'movie';
diff --git a/libs/ui/components/src/index.ts b/libs/ui/components/src/index.ts
index fb6ece784..f80362922 100644
--- a/libs/ui/components/src/index.ts
+++ b/libs/ui/components/src/index.ts
@@ -1,6 +1,7 @@
export * from './lib/art-player/art-player.component';
export * from './lib/audio-player/audio-player.component';
export * from './lib/channel-list-container/channel-list-container.component';
+export * from './lib/confirm-dialog/confirm-dialog.component';
export * from './lib/epg-list/epg-item-description/epg-item-description.component';
export * from './lib/epg-list/epg-list-item/epg-list-item.component';
export * from './lib/epg-list/epg-list.component';
diff --git a/apps/web/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts b/libs/ui/components/src/lib/confirm-dialog/confirm-dialog.component.ts
similarity index 61%
rename from apps/web/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts
rename to libs/ui/components/src/lib/confirm-dialog/confirm-dialog.component.ts
index 3a6c4fcbb..c23fe6dc6 100644
--- a/apps/web/src/app/shared/components/confirm-dialog/confirm-dialog.component.ts
+++ b/libs/ui/components/src/lib/confirm-dialog/confirm-dialog.component.ts
@@ -1,8 +1,16 @@
-import { Component, Inject } from '@angular/core';
+import { Component, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
-import { ConfirmDialogData } from './confirm-dialog-data.interface';
+
+export interface ConfirmDialogData {
+ title: string;
+ message: string;
+ confirmLabel?: string;
+ cancelLabel?: string;
+ onConfirm: () => void;
+}
+
@Component({
imports: [MatButtonModule, MatDialogModule, TranslateModule],
template: `
@@ -14,19 +22,19 @@ import { ConfirmDialogData } from './confirm-dialog-data.interface';
- `
+ `,
})
export class ConfirmDialogComponent {
- /** Contains meta information to show in the dialog */
- dialogData!: ConfirmDialogData;
+ readonly dialogData!: ConfirmDialogData;
+ readonly data = inject(MAT_DIALOG_DATA);
- constructor(@Inject(MAT_DIALOG_DATA) data: ConfirmDialogData) {
- this.dialogData = data;
+ constructor() {
+ this.dialogData = this.data;
}
}
diff --git a/libs/ui/shared-portals/src/lib/live-stream-layout/live-stream-layout.component.html b/libs/ui/shared-portals/src/lib/live-stream-layout/live-stream-layout.component.html
index 3090dbde8..c580d133b 100644
--- a/libs/ui/shared-portals/src/lib/live-stream-layout/live-stream-layout.component.html
+++ b/libs/ui/shared-portals/src/lib/live-stream-layout/live-stream-layout.component.html
@@ -26,11 +26,13 @@
@@ -39,6 +41,7 @@
class="stream-icon"
*ngIf="item.stream_icon"
[src]="item.stream_icon"
+ alt="channel icon"
/>
{{ item.name }}
@@ -48,20 +51,17 @@
- @if (player === 'videojs' || player === 'html5') {
- @if (streamUrl) {
-
- }
- }
- @if (streamUrl) {
-
-
+ @if (player === 'videojs' || player === 'html5') { @if (streamUrl) {
+
+ } } @if (streamUrl) {
+
} @else {
-
Please select a channel
+
Please select a channel
}