diff --git a/src/app/services/settings-store.service.ts b/src/app/services/settings-store.service.ts index 4cd7dda5c..9b6c6038a 100644 --- a/src/app/services/settings-store.service.ts +++ b/src/app/services/settings-store.service.ts @@ -8,6 +8,7 @@ import { } from '@ngrx/signals'; import { StorageMap } from '@ngx-pwa/local-storage'; import { firstValueFrom } from 'rxjs'; +import { StreamFormat } from '../settings/stream-format.enum'; import { Language } from '../settings/language.enum'; import { Settings, VideoPlayer } from '../settings/settings.interface'; import { Theme } from '../settings/theme.enum'; @@ -15,6 +16,7 @@ import { STORE_KEY } from '../shared/enums/store-keys.enum'; const DEFAULT_SETTINGS: Settings = { player: VideoPlayer.VideoJs, + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, @@ -49,6 +51,7 @@ export const SettingsStore = signalStore( getSettings() { return { player: store.player(), + streamFormat: store.streamFormat(), language: store.language(), showCaptions: store.showCaptions(), theme: store.theme(), diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index 6fc0e8cbd..ce7d60d9b 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -70,7 +70,7 @@ - +
@@ -143,6 +143,31 @@
} +
+
+ {{ 'SETTINGS.STREAM_FORMAT' | translate }} +

{{ 'SETTINGS.STREAM_FORMAT_DESCRIPTION' | translate }}

+
+
+ + {{ + 'SETTINGS.VIDEO_PLAYER_PLACEHOLDER' | translate + }} + + {{ streamFormat.value }} + + + +
+
+
{{ 'SETTINGS.LANGUAGE' | translate }} diff --git a/src/app/settings/settings.component.spec.ts b/src/app/settings/settings.component.spec.ts index 18c09e8d0..af28ecac2 100644 --- a/src/app/settings/settings.component.spec.ts +++ b/src/app/settings/settings.component.spec.ts @@ -27,6 +27,7 @@ import { } from 'ng-mocks'; import { DataService } from '../services/data.service'; import { HeaderComponent } from '../shared/components'; +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { SettingsComponent } from './settings.component'; import { VideoPlayer } from './settings.interface'; @@ -56,6 +57,7 @@ export class MockRouter { const DEFAULT_SETTINGS = { player: VideoPlayer.VideoJs, + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 77f72150c..2adbdef8a 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -49,6 +49,7 @@ import { HeaderComponent } from '../shared/components/header/header.component'; import * as PlaylistActions from '../state/actions'; import { selectIsEpgAvailable } from '../state/selectors'; import { SettingsService } from './../services/settings.service'; +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { VideoPlayer } from './settings.interface'; import { Theme } from './theme.enum'; @@ -70,13 +71,16 @@ import { Theme } from './theme.enum'; ReactiveFormsModule, TranslateModule, MatDialogModule, - ] + ], }) export class SettingsComponent implements OnInit { @Input() isDialog = false; /** List with available languages as enum */ languageEnum = Language; + /** List with allowed formats as enum */ + streamFormatEnum = StreamFormat; + /** Flag that indicates whether the app runs in electron environment */ isTauri = this.dataService.getAppEnvironment() === 'tauri'; @@ -130,6 +134,7 @@ export class SettingsComponent implements OnInit { settingsForm = this.formBuilder.group({ player: [VideoPlayer.VideoJs], ...(this.isTauri ? { epgUrl: new FormArray([]) } : {}), + streamFormat: StreamFormat.M3u8StreamFormat, language: Language.ENGLISH, showCaptions: false, theme: Theme.LightTheme, diff --git a/src/app/settings/settings.interface.ts b/src/app/settings/settings.interface.ts index ddf8176d0..c18062c8e 100644 --- a/src/app/settings/settings.interface.ts +++ b/src/app/settings/settings.interface.ts @@ -1,3 +1,4 @@ +import { StreamFormat } from './stream-format.enum'; import { Language } from './language.enum'; import { Theme } from './theme.enum'; @@ -19,6 +20,7 @@ export enum VideoPlayer { export interface Settings { player: VideoPlayer; epgUrl: string[]; + streamFormat: StreamFormat; language: Language; showCaptions: boolean; theme: Theme; diff --git a/src/app/settings/stream-format.enum.ts b/src/app/settings/stream-format.enum.ts new file mode 100644 index 000000000..f85789b8a --- /dev/null +++ b/src/app/settings/stream-format.enum.ts @@ -0,0 +1,7 @@ +/** + * Enum with all the formats that are allowed in the application + */ +export enum StreamFormat { + TsStreamFormat = 'ts', + M3u8StreamFormat = 'm3u8', +} diff --git a/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts b/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts index b23a6fa6b..e4f6ebb3e 100644 --- a/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts +++ b/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.ts @@ -78,7 +78,8 @@ export class LiveStreamLayoutComponent implements OnInit { playLive(item: any) { const { serverUrl, username, password } = this.xtreamStore.currentPlaylist(); - const streamUrl = `${serverUrl}/live/${username}/${password}/${item.xtream_id}.m3u8`; + const streamFormat = this.settingsStore.streamFormat(); + const streamUrl = `${serverUrl}/live/${username}/${password}/${item.xtream_id}.${streamFormat}`; // TODO: offer option to select TS or m3u8 this.openPlayer(streamUrl, item.title, item.poster_url); this.xtreamStore.setSelectedItem(item); diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index f5a8f1bcf..dcb01a6f1 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -119,6 +119,7 @@ "BACK_TO_HOME": "Back", "NEW_VERSION_AVAILABLE": "There is a new version available", "LATEST_VERSION": "You are using the latest version", + "STREAM_FORMAT": "Stream Format", "LANGUAGE": "Language", "SETTINGS_SAVED": "Success! Configuration was saved.", "THEME": "Visual theme", @@ -126,6 +127,7 @@ "ADD_EPG_SOURCE": "Add EPG source", "EPG_URL_ERROR": "The value is not a valid URL", "VIDEO_PLAYER_DESCRIPTION": "Select default video player", + "STREAM_FORMAT_DESCRIPTION": "Select default stream format (xtream)", "LANGUAGE_DESCRIPTION": "Select language of the application", "THEME_DESCRIPTION": "Select visual theme of the application", "SHOW_CAPTIONS_DESCRIPTION": "Show or hide subtitles by default", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 92c847e42..d15f8aca8 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -115,6 +115,7 @@ "BACK_TO_HOME": "Indietro", "NEW_VERSION_AVAILABLE": "È disponibile una nuova versione", "LATEST_VERSION": "Questa versione è aggiornata", + "STREAM_FORMAT": "Formato streaming", "LANGUAGE": "Lingua", "SETTINGS_SAVED": "La configurazione è stata salvata.", "THEME": "Tema visuale", @@ -122,6 +123,7 @@ "ADD_EPG_SOURCE": "Aggiungi sorgente EPG", "EPG_URL_ERROR": "Il valore non è una URL valida", "VIDEO_PLAYER_DESCRIPTION": "Seleziona lettore video predefinito", + "STREAM_FORMAT_DESCRIPTION": "Seleziona il formato di streaming predefinito (xtream)", "LANGUAGE_DESCRIPTION": "Seleziona la lingua dell'applicazione", "THEME_DESCRIPTION": "Seleziona il tema visivo dell'applicazione", "SHOW_CAPTIONS_DESCRIPTION": "Visualizza/nascondi i sottotitoli per impostazione predefinita",