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: `
-
+ logo

{{ '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
}