From 2a9123781f781a33676a2f00e004d237834f2ce5 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sat, 29 Jul 2023 19:14:56 +0200
Subject: [PATCH 01/27] feat: add experimental vlc player support
---
electron/api.ts | 48 ++++++++++++++++++++++++
shared/ipc-commands.ts | 2 +
src/app/settings/settings.component.html | 20 ++++++++++
src/app/settings/settings.component.ts | 29 +++++++++-----
src/app/settings/settings.interface.ts | 2 +
src/assets/i18n/en.json | 8 +++-
6 files changed, 98 insertions(+), 11 deletions(-)
diff --git a/electron/api.ts b/electron/api.ts
index 2b56d57cb..4002108f8 100644
--- a/electron/api.ts
+++ b/electron/api.ts
@@ -25,11 +25,13 @@ import {
MIGRATE_PLAYLISTS_RESPONSE,
OPEN_FILE,
OPEN_MPV_PLAYER,
+ OPEN_VLC_PLAYER,
PLAYLIST_PARSE_BY_URL,
PLAYLIST_PARSE_RESPONSE,
PLAYLIST_UPDATE,
PLAYLIST_UPDATE_RESPONSE,
SET_MPV_PLAYER_PATH,
+ SET_VLC_PLAYER_PATH,
XTREAM_REQUEST,
XTREAM_RESPONSE,
} from '../shared/ipc-commands';
@@ -39,6 +41,8 @@ import { ParsedPlaylist } from '../src/typings.d';
const fs = require('fs');
const https = require('https');
+const child_process = require('child_process');
+const path = require('path');
const mpvAPI = require('node-mpv');
@@ -63,6 +67,7 @@ const agent = new https.Agent({
});
const MPV_PLAYER_PATH = 'MPV_PLAYER_PATH';
+const VLC_PLAYER_PATH = 'VLC_PLAYER_PATH';
export class Api {
/** Instance of the main application window */
@@ -254,6 +259,24 @@ export class Api {
// recreate mpv player instance with new binary path if it was changed
if (store.get(MPV_PLAYER_PATH, mpvPlayerPath) !== mpvPlayerPath)
this.mpv = this.createMpvInstance();
+ })
+ .on(OPEN_VLC_PLAYER, (event, { url }) => {
+ const proc = child_process.spawn(
+ this.getVlcPath(),
+ [`"${url as string}"`],
+ {
+ shell: true,
+ }
+ );
+
+ proc.on('exit', (code) => {
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ console.log(`VLC exited with code ${code}`);
+ });
+ })
+ .on(SET_VLC_PLAYER_PATH, (_event, vlcPlayerPath) => {
+ console.log('... setting vlc player path', vlcPlayerPath);
+ store.set(VLC_PLAYER_PATH, vlcPlayerPath);
});
// listeners for EPG events
@@ -503,6 +526,31 @@ export class Api {
return parse(m3uString);
}
+ getDefaultVlcPath() {
+ if (process.platform === 'win32') {
+ return path.join(
+ 'C:',
+ 'Program Files (x86)',
+ 'VideoLAN',
+ 'VLC',
+ 'vlc.exe'
+ );
+ } else if (process.platform === 'linux') {
+ return '/usr/bin/vlc';
+ } else if (process.platform === 'darwin') {
+ return '/Applications/VLC.app/Contents/MacOS/VLC';
+ }
+ }
+
+ getVlcPath() {
+ const customVlcPath = this.store.get(VLC_PLAYER_PATH);
+ if (customVlcPath) {
+ return customVlcPath;
+ } else {
+ return this.getDefaultVlcPath();
+ }
+ }
+
/** @deprecated - used only for migration */
getAllPlaylists() {
return db
diff --git a/shared/ipc-commands.ts b/shared/ipc-commands.ts
index 1a57b142b..f3a063276 100644
--- a/shared/ipc-commands.ts
+++ b/shared/ipc-commands.ts
@@ -44,6 +44,8 @@ export const AUTO_UPDATE_PLAYLISTS_RESPONSE = 'AUTO_UPDATE_RESPONSE';
// Experimental
export const OPEN_MPV_PLAYER = 'OPEN_MPV_PLAYER';
export const SET_MPV_PLAYER_PATH = 'SET_MPV_PLAYER_PATH';
+export const OPEN_VLC_PLAYER = 'OPEN_VLC_PLAYER';
+export const SET_VLC_PLAYER_PATH = 'SET_VLC_PLAYER_PATH';
// Xtream
export const XTREAM_REQUEST = 'XTREAM_REQUEST';
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
index 9a3704d21..d899cbc38 100644
--- a/src/app/settings/settings.component.html
+++ b/src/app/settings/settings.component.html
@@ -110,6 +110,26 @@
+
{{ 'SETTINGS.LANGUAGE' | translate }}
diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts
index f133b9ac5..6f5193297 100644
--- a/src/app/settings/settings.component.ts
+++ b/src/app/settings/settings.component.ts
@@ -15,6 +15,7 @@ import * as semver from 'semver';
import {
EPG_FORCE_FETCH,
SET_MPV_PLAYER_PATH,
+ SET_VLC_PLAYER_PATH,
} from '../../../shared/ipc-commands';
import { Playlist } from '../../../shared/playlist.interface';
import { DataService } from '../services/data.service';
@@ -43,6 +44,17 @@ export class SettingsComponent implements OnInit {
/** Flag that indicates whether the app runs in electron environment */
isElectron = this.electronService.isElectron;
+ electronPlayers = [
+ {
+ id: VideoPlayer.MPV,
+ label: 'MPV Player',
+ },
+ {
+ id: VideoPlayer.VLC,
+ label: 'VLC',
+ },
+ ];
+
/** Player options */
players = [
{
@@ -53,15 +65,7 @@ export class SettingsComponent implements OnInit {
id: VideoPlayer.VideoJs,
label: 'VideoJs Player',
},
- ...(this.isElectron
- ?
- [
- {
- id: VideoPlayer.MPV,
- label: 'MPV Player',
- },
- ]
- : []),
+ ...(this.isElectron ? this.electronPlayers : []),
];
/** Current version of the app */
@@ -84,6 +88,7 @@ export class SettingsComponent implements OnInit {
showCaptions: false,
theme: Theme.LightTheme,
mpvPlayerPath: '',
+ vlcPlayerPath: '',
});
/** Form array with epg sources */
@@ -138,6 +143,7 @@ export class SettingsComponent implements OnInit {
? settings.theme
: Theme.LightTheme,
mpvPlayerPath: settings.mpvPlayerPath,
+ vlcPlayerPath: settings.vlcPlayerPath,
});
if (this.isElectron) {
@@ -230,6 +236,11 @@ export class SettingsComponent implements OnInit {
SET_MPV_PLAYER_PATH,
this.settingsForm.value.mpvPlayerPath
);
+
+ this.electronService.sendIpcEvent(
+ SET_VLC_PLAYER_PATH,
+ this.settingsForm.value.mpvPlayerPath
+ );
}
/**
diff --git a/src/app/settings/settings.interface.ts b/src/app/settings/settings.interface.ts
index 605cf6507..f31a3f981 100644
--- a/src/app/settings/settings.interface.ts
+++ b/src/app/settings/settings.interface.ts
@@ -9,6 +9,7 @@ export enum VideoPlayer {
VideoJs = 'videojs',
Html5Player = 'html5',
MPV = 'mpv',
+ VLC = 'vlc',
}
/**
@@ -21,4 +22,5 @@ export interface Settings {
showCaptions: boolean;
theme: Theme;
mpvPlayerPath: string;
+ vlcPlayerPath: string;
}
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index b5f4c3d38..98760d648 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -8,7 +8,8 @@
"FILE_UPLOAD": "Add via file upload",
"URL_UPLOAD": "Add via URL",
"TEXT_IMPORT": "Import as text",
- "XTREME_IMPORT": "Import xtreme code"
+ "XTREME_IMPORT": "Import xtreme code",
+ "STALKER_PORTAL_IMPORT": "Add Stalker Portal"
},
"PLAYLISTS": {
"NO_PLAYLISTS": "No playlists were added",
@@ -119,7 +120,10 @@
"PLAYLISTS_REMOVED": "All playlists were removed.",
"MPV_PLAYER_PATH_LABEL": "mpv path",
"MPV_PLAYER_PATH_DESCRIPTION": "Set path to mpv player in your system. It will use the provided path to a mpv binary instead of using the one found in $PATH.",
- "MPV_PLAYER_PATH": "mpv player path"
+ "MPV_PLAYER_PATH": "mpv player path",
+ "VLC_PLAYER_PATH_LABEL": "VLC path",
+ "VLC_PLAYER_PATH_DESCRIPTION": "Set path to VLC player in your system. It will use the provided path to a VLC binary instead of the default path for our system.",
+ "VLC_PLAYER_PATH": "VLC player path"
},
"THEMES": {
"DARK_THEME": "Dark theme",
From ef80b6fe4f9b4cee79242d120031eb010efd46c8 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sat, 5 Aug 2023 13:29:48 +0200
Subject: [PATCH 02/27] chore: update iptv-playlist-parser and prettier
---
package-lock.json | 128 +++++++++++++++++++++++++++++++++++++++-------
package.json | 4 +-
2 files changed, 112 insertions(+), 20 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 317fec713..7f36521ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "iptvnator",
- "version": "0.13.0",
+ "version": "0.14.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "iptvnator",
- "version": "0.13.0",
+ "version": "0.14.0",
"hasInstallScript": true,
"dependencies": {
"@angular/animations": "16.1.5",
@@ -30,7 +30,7 @@
"electron-store": "8.1.0",
"epg-parser": "0.1.6",
"hls.js": "1.2.7",
- "iptv-playlist-parser": "0.8.0",
+ "iptv-playlist-parser": "github:4gray/iptv-playlist-parser",
"lodash": "4.17.21",
"moment": "2.29.4",
"nedb-promises": "6.0.3",
@@ -94,7 +94,7 @@
"npm-run-all": "4.1.5",
"playwright": "1.31.1",
"playwright-core": "1.31.1",
- "prettier": "2.8.8",
+ "prettier": "3.0.0",
"semantic-release": "19.0.3",
"stylelint": "14.2.0",
"stylelint-config-standard": "24.0.0",
@@ -15746,9 +15746,13 @@
}
},
"node_modules/iptv-playlist-parser": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.8.0.tgz",
- "integrity": "sha512-83+6Fl248rxm6tyzgPi2rqHQU1IBZnZvbWXyGAcBxveitckc+sh6b4+aDqQa+u2IJP2HVZilRd2C229kqJtLuQ=="
+ "version": "0.12.2",
+ "resolved": "git+ssh://git@github.com/4gray/iptv-playlist-parser.git#2b48764180edf25821dae3a4b1c9a6a7d0a3bf84",
+ "license": "MIT",
+ "dependencies": {
+ "is-valid-path": "^0.1.1",
+ "validator": "^13.7.0"
+ }
},
"node_modules/is-arguments": {
"version": "1.1.1",
@@ -15959,6 +15963,36 @@
"node": ">=8"
}
},
+ "node_modules/is-invalid-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz",
+ "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==",
+ "dependencies": {
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-invalid-path/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-invalid-path/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-lambda": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
@@ -16212,6 +16246,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-valid-path": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
+ "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==",
+ "dependencies": {
+ "is-invalid-path": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -24898,15 +24943,15 @@
}
},
"node_modules/prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"dev": true,
"bin": {
- "prettier": "bin-prettier.js"
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
@@ -29130,6 +29175,14 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/validator": {
+ "version": "13.9.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz",
+ "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -41965,9 +42018,12 @@
"dev": true
},
"iptv-playlist-parser": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.8.0.tgz",
- "integrity": "sha512-83+6Fl248rxm6tyzgPi2rqHQU1IBZnZvbWXyGAcBxveitckc+sh6b4+aDqQa+u2IJP2HVZilRd2C229kqJtLuQ=="
+ "version": "git+ssh://git@github.com/4gray/iptv-playlist-parser.git#2b48764180edf25821dae3a4b1c9a6a7d0a3bf84",
+ "from": "iptv-playlist-parser@github:4gray/iptv-playlist-parser",
+ "requires": {
+ "is-valid-path": "^0.1.1",
+ "validator": "^13.7.0"
+ }
},
"is-arguments": {
"version": "1.1.1",
@@ -42109,6 +42165,29 @@
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
"dev": true
},
+ "is-invalid-path": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz",
+ "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==",
+ "requires": {
+ "is-glob": "^2.0.0"
+ },
+ "dependencies": {
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww=="
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "requires": {
+ "is-extglob": "^1.0.0"
+ }
+ }
+ }
+ },
"is-lambda": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
@@ -42275,6 +42354,14 @@
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true
},
+ "is-valid-path": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz",
+ "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==",
+ "requires": {
+ "is-invalid-path": "^0.1.0"
+ }
+ },
"is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -48660,9 +48747,9 @@
"dev": true
},
"prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
"dev": true
},
"pretty-bytes": {
@@ -51901,6 +51988,11 @@
"builtins": "^5.0.0"
}
},
+ "validator": {
+ "version": "13.9.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz",
+ "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA=="
+ },
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
diff --git a/package.json b/package.json
index c81dce98c..221529480 100644
--- a/package.json
+++ b/package.json
@@ -72,7 +72,7 @@
"electron-store": "8.1.0",
"epg-parser": "0.1.6",
"hls.js": "1.2.7",
- "iptv-playlist-parser": "0.8.0",
+ "iptv-playlist-parser": "github:4gray/iptv-playlist-parser",
"lodash": "4.17.21",
"moment": "2.29.4",
"nedb-promises": "6.0.3",
@@ -136,7 +136,7 @@
"npm-run-all": "4.1.5",
"playwright": "1.31.1",
"playwright-core": "1.31.1",
- "prettier": "2.8.8",
+ "prettier": "3.0.0",
"semantic-release": "19.0.3",
"stylelint": "14.2.0",
"stylelint-config-standard": "24.0.0",
From 011204aca12f7f6601886bafcf32055d08c15d6d Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sat, 5 Aug 2023 13:34:16 +0200
Subject: [PATCH 03/27] refactor: update interfaces according to updates
---
shared/channel.interface.ts | 3 +--
shared/playlist.interface.ts | 2 ++
src/app/shared/playlist-meta.type.ts | 2 ++
src/typings.d.ts | 2 --
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/shared/channel.interface.ts b/shared/channel.interface.ts
index f907e59c6..67d18d629 100644
--- a/shared/channel.interface.ts
+++ b/shared/channel.interface.ts
@@ -12,8 +12,6 @@ export interface Channel {
tvg: {
id: string;
name: string;
- language: string;
- country: string;
url: string;
logo: string;
rec: string;
@@ -29,4 +27,5 @@ export interface Channel {
referrer: string;
'user-agent': string;
};
+ radio: string;
}
diff --git a/shared/playlist.interface.ts b/shared/playlist.interface.ts
index 374c4877c..9afc1011b 100644
--- a/shared/playlist.interface.ts
+++ b/shared/playlist.interface.ts
@@ -32,4 +32,6 @@ export interface Playlist {
serverUrl?: string;
username?: string;
password?: string;
+ macAddress?: string;
+ portalUrl?: string;
}
diff --git a/src/app/shared/playlist-meta.type.ts b/src/app/shared/playlist-meta.type.ts
index bc9e4d424..29e09a2b5 100644
--- a/src/app/shared/playlist-meta.type.ts
+++ b/src/app/shared/playlist-meta.type.ts
@@ -18,4 +18,6 @@ export type PlaylistMeta = Pick<
| 'serverUrl'
| 'username'
| 'password'
+ | 'macAddress'
+ | 'portalUrl'
>;
diff --git a/src/typings.d.ts b/src/typings.d.ts
index b3c5bb6fd..dcec9ae7e 100644
--- a/src/typings.d.ts
+++ b/src/typings.d.ts
@@ -23,8 +23,6 @@ export interface ParsedPlaylistItem {
tvg: {
id: string;
name: string;
- language: string;
- country: string;
url: string;
logo: string;
rec: string;
From 1e2ab0b8ed799eeff3d88958e30d60d8eb36eb84 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 21:53:45 +0200
Subject: [PATCH 04/27] feat(stalker): new interfaces and ipc commands
---
shared/ipc-commands.ts | 4 ++++
shared/stalker-portal-actions.enum.ts | 6 ++++++
2 files changed, 10 insertions(+)
create mode 100644 shared/stalker-portal-actions.enum.ts
diff --git a/shared/ipc-commands.ts b/shared/ipc-commands.ts
index f3a063276..a8ab6408c 100644
--- a/shared/ipc-commands.ts
+++ b/shared/ipc-commands.ts
@@ -50,3 +50,7 @@ export const SET_VLC_PLAYER_PATH = 'SET_VLC_PLAYER_PATH';
// Xtream
export const XTREAM_REQUEST = 'XTREAM_REQUEST';
export const XTREAM_RESPONSE = 'XTREAM_RESPONSE';
+
+// Stalker
+export const STALKER_REQUEST = 'STALKER_REQUEST';
+export const STALKER_RESPONSE = 'STALKER_RESPONSE';
diff --git a/shared/stalker-portal-actions.enum.ts b/shared/stalker-portal-actions.enum.ts
new file mode 100644
index 000000000..60d10ce80
--- /dev/null
+++ b/shared/stalker-portal-actions.enum.ts
@@ -0,0 +1,6 @@
+export enum StalkerPortalActions {
+ GetCategories = 'get_categories',
+ GetGenres = 'get_genres',
+ CreateLink = 'create_link',
+ GetOrderedList = 'get_ordered_list',
+}
From a749bec69059aa915dfbad39e62bb3e9c9703d97 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 21:54:52 +0200
Subject: [PATCH 05/27] refactor(xtream): update navigation-bar component
---
.../content-type-navigation-item.interface.ts | 6 ++++
src/app/xtream/content-type.enum.ts | 6 ++--
.../navigation-bar.component.html | 16 +++++-----
.../navigation-bar.component.ts | 6 ++++
src/app/xtream/portal-card-item.interface.ts | 10 ++++++
.../xtream-main-container.component.html | 1 +
.../xtream/xtream-main-container.component.ts | 31 ++++++++++++++-----
7 files changed, 57 insertions(+), 19 deletions(-)
create mode 100644 src/app/xtream/content-type-navigation-item.interface.ts
create mode 100644 src/app/xtream/portal-card-item.interface.ts
diff --git a/src/app/xtream/content-type-navigation-item.interface.ts b/src/app/xtream/content-type-navigation-item.interface.ts
new file mode 100644
index 000000000..70d976686
--- /dev/null
+++ b/src/app/xtream/content-type-navigation-item.interface.ts
@@ -0,0 +1,6 @@
+import { ContentType } from './content-type.enum';
+
+export interface ContentTypeNavigationItem {
+ contentType: ContentType;
+ label: string;
+}
\ No newline at end of file
diff --git a/src/app/xtream/content-type.enum.ts b/src/app/xtream/content-type.enum.ts
index 7125355a3..abd1672fa 100644
--- a/src/app/xtream/content-type.enum.ts
+++ b/src/app/xtream/content-type.enum.ts
@@ -1,5 +1,5 @@
export enum ContentType {
- LIVE_STREAMS = 'LIVE_STREAMS',
- VODS = 'VODS',
- SERIES = 'SERIES',
+ VODS = 'vod',
+ SERIES = 'series',
+ ITV = 'itv',
}
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.html b/src/app/xtream/navigation-bar/navigation-bar.component.html
index c7798b890..ea876fb6d 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.html
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.html
@@ -10,15 +10,15 @@
[value]="contentType"
(change)="contentTypeChanged.emit($event.value)"
>
- Live Streams
- VOD Streams
- Series
+ {{ item.label }}
+
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.ts b/src/app/xtream/navigation-bar/navigation-bar.component.ts
index 3d00134c9..5cf63b6d3 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.ts
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.ts
@@ -6,6 +6,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatIconModule } from '@angular/material/icon';
import { RouterLink } from '@angular/router';
import { Breadcrumb } from '../breadcrumb.interface';
+import { ContentTypeNavigationItem } from '../content-type-navigation-item.interface';
import { ContentType } from '../content-type.enum';
import { PortalStore } from '../portal.store';
@@ -28,6 +29,7 @@ export class NavigationBarComponent {
@Input({ required: true }) breadcrumbs: Breadcrumb[];
@Input({ required: true }) contentType: ContentType;
@Input() searchVisible = true;
+ @Input() contentTypeNavigationItems: ContentTypeNavigationItem[];
@Output() contentTypeChanged = new EventEmitter
();
@Output() breadcrumbClicked = new EventEmitter();
@@ -45,4 +47,8 @@ export class NavigationBarComponent {
setSearchText(text: string) {
this.portalStore.setSearchPhrase(text);
}
+
+ trackByValue(_i: number, value: ContentTypeNavigationItem) {
+ return value.contentType;
+ }
}
diff --git a/src/app/xtream/portal-card-item.interface.ts b/src/app/xtream/portal-card-item.interface.ts
new file mode 100644
index 000000000..8812636d0
--- /dev/null
+++ b/src/app/xtream/portal-card-item.interface.ts
@@ -0,0 +1,10 @@
+// should represent the content of a card element - xtream category or VOD or any item from stalker, vportal etc
+export interface PortalCardItem {
+ // TODO
+ id: string;
+ type: 'category' | 'vod' | 'serial' | 'live'; // TODO: enum
+ name: string;
+ coverUrl?: string;
+ streamType?: 'live' | 'movie'; // TODO: maybe not needed, since type is there
+ categoryId?: string;
+}
diff --git a/src/app/xtream/xtream-main-container.component.html b/src/app/xtream/xtream-main-container.component.html
index e48a0c633..27114e920 100644
--- a/src/app/xtream/xtream-main-container.component.html
+++ b/src/app/xtream/xtream-main-container.component.html
@@ -8,6 +8,7 @@
[searchVisible]="
currentLayout === 'category' || currentLayout === 'category_content'
"
+ [contentTypeNavigationItems]="navigationContentTypes"
/>
diff --git a/src/app/xtream/xtream-main-container.component.ts b/src/app/xtream/xtream-main-container.component.ts
index 8edb4343e..d40787372 100644
--- a/src/app/xtream/xtream-main-container.component.ts
+++ b/src/app/xtream/xtream-main-container.component.ts
@@ -25,6 +25,7 @@ import { IpcCommand } from '../../../shared/ipc-command.class';
import {
ERROR,
OPEN_MPV_PLAYER,
+ OPEN_VLC_PLAYER,
XTREAM_REQUEST,
XTREAM_RESPONSE,
} from '../../../shared/ipc-commands';
@@ -55,24 +56,22 @@ import { PlaylistsService } from '../services/playlists.service';
import { Settings, VideoPlayer } from '../settings/settings.interface';
import { STORE_KEY } from '../shared/enums/store-keys.enum';
import { Breadcrumb } from './breadcrumb.interface';
+import { ContentTypeNavigationItem } from './content-type-navigation-item.interface';
import { PlayerDialogComponent } from './player-dialog/player-dialog.component';
import { PortalStore } from './portal.store';
import { SerialDetailsComponent } from './serial-details/serial-details.component';
const ContentTypes = {
- LIVE_STREAMS: {
- title: 'Live streams',
+ [ContentType.ITV]: {
getContentAction: XtreamCodeActions.GetLiveStreams,
getCategoryAction: XtreamCodeActions.GetLiveCategories,
},
- VODS: {
- title: 'VOD streams',
+ [ContentType.VODS]: {
getContentAction: XtreamCodeActions.GetVodStreams,
getCategoryAction: XtreamCodeActions.GetVodCategories,
getDetailsAction: XtreamCodeActions.GetVodInfo,
},
- SERIES: {
- title: 'Series',
+ [ContentType.SERIES]: {
getContentAction: XtreamCodeActions.GetSeries,
getCategoryAction: XtreamCodeActions.GetSeriesCategories,
getDetailsAction: XtreamCodeActions.GetSeriesInfo,
@@ -123,6 +122,20 @@ export class XtreamMainContainerComponent implements OnInit {
storage = inject(StorageMap);
store = inject(Store);
currentPlaylist = this.store.selectSignal(selectCurrentPlaylist);
+ navigationContentTypes: ContentTypeNavigationItem[] = [
+ {
+ contentType: ContentType.ITV,
+ label: 'Live Streams',
+ },
+ {
+ contentType: ContentType.VODS,
+ label: 'VOD Streams',
+ },
+ {
+ contentType: ContentType.SERIES,
+ label: 'Series',
+ },
+ ];
favorites$: Observable
;
breadcrumbs: Breadcrumb[] = [];
@@ -157,7 +170,6 @@ export class XtreamMainContainerComponent implements OnInit {
ngOnInit() {
this.setInitialBreadcrumb();
- console.log(this.currentPlaylist()._id);
this.favorites$ = this.playlistService.getPortalFavorites(
this.currentPlaylist()._id
);
@@ -276,6 +288,10 @@ export class XtreamMainContainerComponent implements OnInit {
this.dataService.sendIpcEvent(OPEN_MPV_PLAYER, {
url: streamUrl,
});
+ } else if (player === VideoPlayer.VLC) {
+ this.dataService.sendIpcEvent(OPEN_VLC_PLAYER, {
+ url: streamUrl,
+ });
} else {
this.dialog.open(PlayerDialogComponent, {
data: { streamUrl, player, title },
@@ -385,7 +401,6 @@ export class XtreamMainContainerComponent implements OnInit {
}
setSearchPhrase(searchPhrase: string) {
- console.log(searchPhrase);
this.searchPhrase = searchPhrase;
}
From 91568c07050121bfa9a959991766a95b76776c13 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 22:11:37 +0200
Subject: [PATCH 06/27] feat(stalker): add stalker portal related translations
---
src/assets/i18n/en.json | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index 98760d648..798c9d414 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -8,7 +8,7 @@
"FILE_UPLOAD": "Add via file upload",
"URL_UPLOAD": "Add via URL",
"TEXT_IMPORT": "Import as text",
- "XTREME_IMPORT": "Import xtreme code",
+ "XTREME_IMPORT": "Add Xtreme Code",
"STALKER_PORTAL_IMPORT": "Add Stalker Portal"
},
"PLAYLISTS": {
@@ -17,6 +17,7 @@
"ADDED_VIA_URL": "Added via URL upload. URL:",
"ADDED_VIA_FILE": "Added via file upload",
"XTREAM_PLAYLIST": "Xtream playlist",
+ "STALKER_PORTAL": "Stalker portal",
"CHANNELS": "Channels",
"ADDED": "Added",
"SHOW_DETAILS": "Show playlist details",
@@ -39,7 +40,8 @@
"EXPORT_PLAYLIST": "Export playlist as m3u",
"SERVER_URL": "Server URL",
"USERNAME": "Username",
- "PASSWORD": "Password"
+ "PASSWORD": "Password",
+ "MAC_ADDRESS": "Mac Address"
},
"REMOVE_DIALOG": {
"TITLE": "Remove playlist",
@@ -76,6 +78,13 @@
"ADD": "Add",
"TEST_CREDENTIALS": "Test credentials",
"URL_VALIDATION_ERROR": "Should be a valid url with protocol (e.g. http://example.com or https://example.com:4324)"
+ },
+ "STALKER_PORTAL": {
+ "TITLE": "Title",
+ "MAC_ADDRESS": "Mac Address",
+ "SERVER_URL": "Server URL",
+ "URL_VALIDATION_ERROR": "Should be a valid url with protocol (e.g. http://example.com/portal.php or https://example.com:4324/portal.php)",
+ "ADD": "Add"
}
},
"SETTINGS": {
From e06e0d558ac97e898225046ed2c7b2a88fe907b6 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 22:50:11 +0200
Subject: [PATCH 07/27] fix(xtream): reset search text after navigation
---
src/app/xtream/navigation-bar/navigation-bar.component.html | 2 +-
src/app/xtream/navigation-bar/navigation-bar.component.ts | 5 +++++
src/app/xtream/xtream-main-container.component.ts | 1 +
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.html b/src/app/xtream/navigation-bar/navigation-bar.component.html
index ea876fb6d..6671345cb 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.html
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.html
@@ -8,7 +8,7 @@
name="contentType"
aria-label="Content Type"
[value]="contentType"
- (change)="contentTypeChanged.emit($event.value)"
+ (change)="changeContentType($event.value)"
>
Date: Sun, 6 Aug 2023 22:52:16 +0200
Subject: [PATCH 08/27] fix(xtream): update changes after saving
---
src/app/services/playlists.service.ts | 15 +++++++++++++++
src/app/state/reducers.ts | 12 +++++++++---
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/src/app/services/playlists.service.ts b/src/app/services/playlists.service.ts
index c6fbda466..d00c9d721 100644
--- a/src/app/services/playlists.service.ts
+++ b/src/app/services/playlists.service.ts
@@ -80,6 +80,21 @@ export class PlaylistsService {
title: updatedPlaylist.title,
autoRefresh: updatedPlaylist.autoRefresh,
userAgent: updatedPlaylist.userAgent,
+ ...(updatedPlaylist.serverUrl !== null
+ ? { serverUrl: updatedPlaylist.serverUrl }
+ : {}),
+ ...(updatedPlaylist.portalUrl !== null
+ ? { portalUrl: updatedPlaylist.portalUrl }
+ : {}),
+ ...(updatedPlaylist.macAddress !== null
+ ? { macAddress: updatedPlaylist.macAddress }
+ : {}),
+ ...(updatedPlaylist.username !== null
+ ? { username: updatedPlaylist.username }
+ : {}),
+ ...(updatedPlaylist.password !== null
+ ? { password: updatedPlaylist.password }
+ : {}),
})
)
);
diff --git a/src/app/state/reducers.ts b/src/app/state/reducers.ts
index 9a5c9a5cd..dd8389be9 100644
--- a/src/app/state/reducers.ts
+++ b/src/app/state/reducers.ts
@@ -181,15 +181,21 @@ export const playlistReducer = createReducer(
title: action.playlist.title,
autoRefresh: action.playlist.autoRefresh || false,
userAgent: action.playlist.userAgent,
- ...(action.playlist.serverUrl
+ ...(action.playlist.serverUrl !== null
? { serverUrl: action.playlist.serverUrl }
: {}),
- ...(action.playlist.username
+ ...(action.playlist.username !== null
? { username: action.playlist.username }
: {}),
- ...(action.playlist.password
+ ...(action.playlist.password !== null
? { password: action.playlist.password }
: {}),
+ ...(action.playlist.macAddress !== null
+ ? { macAddress: action.playlist.macAddress }
+ : {}),
+ ...(action.playlist.portalUrl !== null
+ ? { portalUrl: action.playlist.portalUrl }
+ : {}),
},
},
state.playlists
From 204525f9ee5d00ca40f29c2eae067121b736be13 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 23:49:53 +0200
Subject: [PATCH 09/27] refactor(xtream): remove unused import
---
src/app/xtream/vod-details/vod-details.component.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/app/xtream/vod-details/vod-details.component.ts b/src/app/xtream/vod-details/vod-details.component.ts
index 5aa0b3f5a..f79aa4f04 100644
--- a/src/app/xtream/vod-details/vod-details.component.ts
+++ b/src/app/xtream/vod-details/vod-details.component.ts
@@ -1,4 +1,4 @@
-import { JsonPipe, NgIf } from '@angular/common';
+import { NgIf } from '@angular/common';
import {
Component,
EventEmitter,
@@ -18,7 +18,7 @@ import { PlaylistsService } from '../../services/playlists.service';
templateUrl: './vod-details.component.html',
styleUrls: ['../detail-view.scss'],
standalone: true,
- imports: [JsonPipe, MatButtonModule, NgIf, MatIconModule],
+ imports: [MatButtonModule, NgIf, MatIconModule],
})
export class VodDetailsComponent implements OnInit {
@Input({ required: true }) item: XtreamVodDetails;
From 53c3b3092c181f3173f39008eb3532e15bf5f6db Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 23:50:20 +0200
Subject: [PATCH 10/27] refactor(xtream): code style improvements
---
src/app/xtream/vod-details/vod-details.component.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/app/xtream/vod-details/vod-details.component.html b/src/app/xtream/vod-details/vod-details.component.html
index 2bbfb866f..11fbb533c 100644
--- a/src/app/xtream/vod-details/vod-details.component.html
+++ b/src/app/xtream/vod-details/vod-details.component.html
@@ -10,8 +10,8 @@
>
From fd001c26ced7e40896634ca6ff41854e4f0a2eed Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sun, 6 Aug 2023 23:52:38 +0200
Subject: [PATCH 11/27] feat(stalker): add import stalker portal component
---
src/app/app-routing.module.ts | 7 ++
src/app/home/home.component.html | 21 ++++--
src/app/home/home.module.ts | 2 +
.../stalker-portal-import.component.html | 54 +++++++++++++++
.../stalker-portal-import.component.ts | 69 +++++++++++++++++++
5 files changed, 146 insertions(+), 7 deletions(-)
create mode 100644 src/app/home/stalker-portal-import/stalker-portal-import.component.html
create mode 100644 src/app/home/stalker-portal-import/stalker-portal-import.component.ts
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index e7f084c48..135e5eb64 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -36,6 +36,13 @@ const routes: Routes = [
(c) => c.XtreamMainContainerComponent
),
},
+ {
+ path: 'portals/:id',
+ loadComponent: () =>
+ import('./stalker/stalker-main-container.component').then(
+ (c) => c.StalkerMainContainerComponent
+ ),
+ },
{
path: '**',
redirectTo: '',
diff --git a/src/app/home/home.component.html b/src/app/home/home.component.html
index 72da861a7..9d1690d05 100644
--- a/src/app/home/home.component.html
+++ b/src/app/home/home.component.html
@@ -46,9 +46,7 @@
-
+
@@ -59,14 +57,12 @@
-
+
- text_format
+ video_library
{{ 'HOME.TABS.XTREME_IMPORT' | translate }}
@@ -75,6 +71,17 @@
+
+
+ dashboard
+
+ {{ 'HOME.TABS.STALKER_PORTAL_IMPORT' | translate }}
+
+
+
+
+
+
diff --git a/src/app/home/home.module.ts b/src/app/home/home.module.ts
index f645965e6..585e654cb 100644
--- a/src/app/home/home.module.ts
+++ b/src/app/home/home.module.ts
@@ -5,6 +5,7 @@ import { DragDropFileUploadDirective } from './file-upload/drag-drop-file-upload
import { FileUploadComponent } from './file-upload/file-upload.component';
import { HomeComponent } from './home.component';
import { HomeRoutingModule } from './home.routing';
+import { StalkerPortalImportComponent } from './stalker-portal-import/stalker-portal-import.component';
import { TextImportComponent } from './text-import/text-import.component';
import { UrlUploadComponent } from './url-upload/url-upload.component';
import { XtreamCodeImportComponent } from './xtream-code-import/xtream-code-import.component';
@@ -15,6 +16,7 @@ import { XtreamCodeImportComponent } from './xtream-code-import/xtream-code-impo
HomeRoutingModule,
SharedModule,
XtreamCodeImportComponent,
+ StalkerPortalImportComponent,
],
declarations: [
DragDropFileUploadDirective,
diff --git a/src/app/home/stalker-portal-import/stalker-portal-import.component.html b/src/app/home/stalker-portal-import/stalker-portal-import.component.html
new file mode 100644
index 000000000..5336ca695
--- /dev/null
+++ b/src/app/home/stalker-portal-import/stalker-portal-import.component.html
@@ -0,0 +1,54 @@
+
diff --git a/src/app/home/stalker-portal-import/stalker-portal-import.component.ts b/src/app/home/stalker-portal-import/stalker-portal-import.component.ts
new file mode 100644
index 000000000..0a21fa798
--- /dev/null
+++ b/src/app/home/stalker-portal-import/stalker-portal-import.component.ts
@@ -0,0 +1,69 @@
+import { Component, inject } from '@angular/core';
+import {
+ FormControl,
+ FormGroup,
+ FormsModule,
+ ReactiveFormsModule,
+ Validators,
+} from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { Store } from '@ngrx/store';
+import { TranslateModule } from '@ngx-translate/core';
+import { v4 as uuid } from 'uuid';
+import { Playlist } from '../../../../shared/playlist.interface';
+import { DataService } from '../../services/data.service';
+import { addPlaylist } from '../../state/actions';
+
+@Component({
+ standalone: true,
+ imports: [
+ FormsModule,
+ ReactiveFormsModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatButtonModule,
+ TranslateModule,
+ ],
+ selector: 'app-stalker-portal-import',
+ templateUrl: './stalker-portal-import.component.html',
+ styles: [
+ `
+ :host {
+ display: flex;
+ margin: 10px;
+ justify-content: center;
+ }
+
+ form {
+ width: 100%;
+ }
+ `,
+ ],
+})
+export class StalkerPortalImportComponent {
+ URL_REGEX = /^(http|https|file):\/\/[^ "]+$/;
+
+ form = new FormGroup({
+ _id: new FormControl(uuid()),
+ title: new FormControl('', [Validators.required]),
+ macAddress: new FormControl(''),
+ password: new FormControl(''),
+ username: new FormControl(''),
+ portalUrl: new FormControl('', [
+ Validators.required,
+ Validators.pattern(this.URL_REGEX),
+ ]),
+ importDate: new FormControl(new Date().toISOString()),
+ });
+
+ dataService = inject(DataService);
+ store = inject(Store);
+
+ addPlaylist() {
+ this.store.dispatch(
+ addPlaylist({ playlist: this.form.value as Playlist })
+ );
+ }
+}
From 1ac733cfa8b7311e851520db8f053ab515566a51 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Mon, 7 Aug 2023 09:56:45 +0200
Subject: [PATCH 12/27] feat(stalker): add stalker related inputs to
playlist-info dialog
---
.../playlist-info/playlist-info.component.html | 14 +++++++++++++-
.../playlist-info/playlist-info.component.ts | 2 ++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/src/app/home/recent-playlists/playlist-info/playlist-info.component.html b/src/app/home/recent-playlists/playlist-info/playlist-info.component.html
index 24ae9072e..944161283 100644
--- a/src/app/home/recent-playlists/playlist-info/playlist-info.component.html
+++ b/src/app/home/recent-playlists/playlist-info/playlist-info.component.html
@@ -12,6 +12,18 @@
}}
+
+ {{
+ 'HOME.PLAYLISTS.INFO_DIALOG.SERVER_URL' | translate
+ }}
+
+
+
+ {{
+ 'HOME.PLAYLISTS.INFO_DIALOG.MAC_ADDRESS' | translate
+ }}
+
+
{{
'HOME.PLAYLISTS.INFO_DIALOG.SERVER_URL' | translate
@@ -89,7 +101,7 @@
mat-flat-button
color="accent"
(click)="exportPlaylist()"
- *ngIf="!playlist.serverUrl"
+ *ngIf="!playlist.serverUrl && !playlist.portalUrl"
>
{{ 'HOME.PLAYLISTS.INFO_DIALOG.EXPORT_PLAYLIST' | translate }}
diff --git a/src/app/home/recent-playlists/playlist-info/playlist-info.component.ts b/src/app/home/recent-playlists/playlist-info/playlist-info.component.ts
index 8f89a1b74..ae8901ad5 100644
--- a/src/app/home/recent-playlists/playlist-info/playlist-info.component.ts
+++ b/src/app/home/recent-playlists/playlist-info/playlist-info.component.ts
@@ -98,6 +98,8 @@ export class PlaylistInfoComponent {
serverUrl: new FormControl(this.playlist.serverUrl),
username: new FormControl(this.playlist.username),
password: new FormControl(this.playlist.password),
+ macAddress: new FormControl(this.playlist.macAddress),
+ portalUrl: new FormControl(this.playlist.portalUrl),
});
}
From 94decafda1ca184a1a3c4f2e37606e283613dd65 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Mon, 7 Aug 2023 10:00:01 +0200
Subject: [PATCH 13/27] refactor: support stalker portal in playlist-item cmp
---
.../playlist-item/playlist-item.component.html | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/app/home/recent-playlists/playlist-item/playlist-item.component.html b/src/app/home/recent-playlists/playlist-item/playlist-item.component.html
index 6933b5b7f..e2a785b91 100644
--- a/src/app/home/recent-playlists/playlist-item/playlist-item.component.html
+++ b/src/app/home/recent-playlists/playlist-item/playlist-item.component.html
@@ -14,7 +14,7 @@
folder
@@ -25,9 +25,18 @@
[matTooltip]="'HOME.PLAYLISTS.XTREAM_PLAYLIST' | translate"
>public
+ dashboard
{{ item.title || item.filename }}
-
+
{{ 'HOME.PLAYLISTS.CHANNELS' | translate }}: {{ item.count }}
3">
| {{ 'HOME.PLAYLISTS.ADDED' | translate }}:
@@ -35,7 +44,7 @@
| {{ 'HOME.PLAYLISTS.UPDATED' | translate }}:
- {{ item.updateDate | date : 'MMMM d, yyyy, HH:mm' }}
+ {{ item.updateDate | date: 'MMMM d, yyyy, HH:mm' }}
Xtream Code Playlist
+ >Xtream/Stalker Playlist
3">
| {{ 'HOME.PLAYLISTS.ADDED' | translate }}:
{{ item.importDate | date }}
From 9e24b1f7368c82d1b2a2d8227c4d9993d505293d Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Wed, 9 Aug 2023 22:53:48 +0200
Subject: [PATCH 14/27] feat: stalker portal support in the main process
---
electron/api.ts | 52 +++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 44 insertions(+), 8 deletions(-)
diff --git a/electron/api.ts b/electron/api.ts
index 4002108f8..c70bc57d9 100644
--- a/electron/api.ts
+++ b/electron/api.ts
@@ -32,6 +32,8 @@ import {
PLAYLIST_UPDATE_RESPONSE,
SET_MPV_PLAYER_PATH,
SET_VLC_PLAYER_PATH,
+ STALKER_REQUEST,
+ STALKER_RESPONSE,
XTREAM_REQUEST,
XTREAM_RESPONSE,
} from '../shared/ipc-commands';
@@ -318,17 +320,52 @@ export class Api {
this.workerWindow.webContents.send(EPG_FORCE_FETCH, arg)
);
- ipcMain.on(
- XTREAM_REQUEST,
- (event, arg: { url: string; params: Record }) => {
- const xtreamApiPath = '/player_api.php';
+ ipcMain
+ .on(
+ XTREAM_REQUEST,
+ (
+ event,
+ arg: { url: string; params: Record }
+ ) => {
+ const xtreamApiPath = '/player_api.php';
+ axios
+ .get(arg.url + xtreamApiPath, {
+ params: arg.params ?? {},
+ })
+ .then((result) => {
+ event.sender.send(XTREAM_RESPONSE, {
+ payload: result.data,
+ action: arg.params.action,
+ });
+ })
+ .catch((err) => {
+ event.sender.send(ERROR, {
+ message:
+ err.response?.statusText ??
+ 'Error: not found',
+ status: err.response?.status ?? 404,
+ });
+ });
+ }
+ )
+ .on(STALKER_REQUEST, (event, arg: any) => {
axios
- .get(arg.url + xtreamApiPath, {
+ .get(arg.url, {
params: arg.params ?? {},
+ headers: {
+ Cookie: `mac=${arg.macAddress as string}`,
+ ...(arg.params.token
+ ? {
+ Authorization: `Bearer ${
+ arg.params.token as string
+ }`,
+ }
+ : {}),
+ },
})
.then((result) => {
- event.sender.send(XTREAM_RESPONSE, {
+ event.sender.send(STALKER_RESPONSE, {
payload: result.data,
action: arg.params.action,
});
@@ -340,8 +377,7 @@ export class Api {
status: err.response?.status ?? 404,
});
});
- }
- );
+ });
}
createMpvInstance() {
From 40f781cbb8e5af49a40298895198e7a5d4d35032 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Wed, 9 Aug 2023 22:54:12 +0200
Subject: [PATCH 15/27] feat: stalker portal support for the pwa
---
src/app/services/pwa.service.ts | 41 +++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/src/app/services/pwa.service.ts b/src/app/services/pwa.service.ts
index ca7665e20..d9bbebf6a 100644
--- a/src/app/services/pwa.service.ts
+++ b/src/app/services/pwa.service.ts
@@ -10,6 +10,8 @@ import {
PLAYLIST_PARSE_BY_URL,
PLAYLIST_PARSE_RESPONSE,
PLAYLIST_UPDATE,
+ STALKER_REQUEST,
+ STALKER_RESPONSE,
XTREAM_REQUEST,
XTREAM_RESPONSE,
} from '../../../shared/ipc-commands';
@@ -71,6 +73,14 @@ export class PwaService extends DataService {
this.forwardXtreamRequest(
payload as { url: string; params: Record }
);
+ } else if (type === STALKER_REQUEST) {
+ this.forwardStalkerRequest(
+ payload as {
+ url: string;
+ macAddress: string;
+ params: Record;
+ }
+ );
}
}
@@ -145,13 +155,22 @@ export class PwaService extends DataService {
forwardXtreamRequest(payload: {
url: string;
params: Record;
+ macAddress?: string;
}) {
+ const headers = payload.macAddress
+ ? {
+ headers: {
+ Cookie: `mac=${payload.macAddress}`,
+ },
+ }
+ : {};
return this.http
.get(`${this.corsProxyUrl}/xtream`, {
params: {
url: payload.url,
...payload.params,
},
+ ...headers,
})
.subscribe((response) => {
window.postMessage({
@@ -162,6 +181,28 @@ export class PwaService extends DataService {
});
}
+ forwardStalkerRequest(payload: {
+ url: string;
+ params: Record;
+ macAddress: string;
+ }) {
+ return this.http
+ .get(`${this.corsProxyUrl}/stalker`, {
+ params: {
+ url: payload.url,
+ ...payload.params,
+ macAddress: payload.macAddress,
+ },
+ })
+ .subscribe((response) => {
+ window.postMessage({
+ type: STALKER_RESPONSE,
+ payload: (response as any).payload,
+ action: payload.params.action,
+ });
+ });
+ }
+
getPlaylistFromUrl(url: string) {
return this.http.get(`${this.corsProxyUrl}/parse`, {
params: { url },
From ff90a66c32fe6ffc8353322927e2ed5ca2898cc1 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Wed, 9 Aug 2023 22:57:15 +0200
Subject: [PATCH 16/27] refactor: fix navigation to stalker portal playlist
---
src/app/home/recent-playlists/recent-playlists.component.ts | 2 ++
src/app/state/effects.ts | 2 ++
2 files changed, 4 insertions(+)
diff --git a/src/app/home/recent-playlists/recent-playlists.component.ts b/src/app/home/recent-playlists/recent-playlists.component.ts
index 19d0ef55d..89d656624 100644
--- a/src/app/home/recent-playlists/recent-playlists.component.ts
+++ b/src/app/home/recent-playlists/recent-playlists.component.ts
@@ -169,6 +169,8 @@ export class RecentPlaylistsComponent implements OnDestroy {
getPlaylist(playlistMeta: PlaylistMeta): void {
if (playlistMeta.serverUrl) {
this.router.navigate(['xtreams', playlistMeta._id]);
+ } else if (playlistMeta.macAddress) {
+ this.router.navigate(['portals', playlistMeta._id]);
} else {
this.router.navigate(['playlists', playlistMeta._id]);
this.playlistClicked.emit(playlistMeta._id);
diff --git a/src/app/state/effects.ts b/src/app/state/effects.ts
index be251e84a..eea33d041 100644
--- a/src/app/state/effects.ts
+++ b/src/app/state/effects.ts
@@ -169,6 +169,8 @@ export class PlaylistEffects {
tap((playlist) => {
if (playlist.serverUrl) {
this.router.navigate(['/xtreams/', playlist._id]);
+ } else if (playlist.macAddress) {
+ this.router.navigate(['portals', playlist._id]);
} else {
this.router.navigate(['/playlists/', playlist._id]);
}
From 9044fe4b61ff3240400de3bca3674b0bd0696447 Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Wed, 9 Aug 2023 22:58:25 +0200
Subject: [PATCH 17/27] refactor: some improvements in interfaces
---
src/app/xtream/breadcrumb.interface.ts | 5 ++++-
src/app/xtream/xtream-main-container.component.ts | 10 +++++-----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/app/xtream/breadcrumb.interface.ts b/src/app/xtream/breadcrumb.interface.ts
index dfb2d38bf..f619a3c3a 100644
--- a/src/app/xtream/breadcrumb.interface.ts
+++ b/src/app/xtream/breadcrumb.interface.ts
@@ -1,7 +1,10 @@
+import { StalkerPortalActions } from '../../../shared/stalker-portal-actions.enum';
import { XtreamCodeActions } from '../../../shared/xtream-code-actions';
+export type PortalActions = StalkerPortalActions | XtreamCodeActions;
+
export interface Breadcrumb {
- action: XtreamCodeActions;
+ action: PortalActions;
title: string;
category_id?: string;
}
diff --git a/src/app/xtream/xtream-main-container.component.ts b/src/app/xtream/xtream-main-container.component.ts
index 1b9298bed..629b1d5bb 100644
--- a/src/app/xtream/xtream-main-container.component.ts
+++ b/src/app/xtream/xtream-main-container.component.ts
@@ -55,7 +55,7 @@ import {
import { PlaylistsService } from '../services/playlists.service';
import { Settings, VideoPlayer } from '../settings/settings.interface';
import { STORE_KEY } from '../shared/enums/store-keys.enum';
-import { Breadcrumb } from './breadcrumb.interface';
+import { Breadcrumb, PortalActions } from './breadcrumb.interface';
import { ContentTypeNavigationItem } from './content-type-navigation-item.interface';
import { PlayerDialogComponent } from './player-dialog/player-dialog.component';
import { PortalStore } from './portal.store';
@@ -164,15 +164,15 @@ export class XtreamMainContainerComponent implements OnInit {
effect(() => {
if (this.currentPlaylist()) {
this.getCategories(this.selectedContentType);
+ this.favorites$ = this.playlistService.getPortalFavorites(
+ this.currentPlaylist()._id
+ );
}
});
}
ngOnInit() {
this.setInitialBreadcrumb();
- this.favorites$ = this.playlistService.getPortalFavorites(
- this.currentPlaylist()._id
- );
this.commandsList.forEach((command) => {
if (this.dataService.isElectron) {
@@ -363,7 +363,7 @@ export class XtreamMainContainerComponent implements OnInit {
});
}
- getLayoutViewBasedOnAction(action: XtreamCodeActions) {
+ getLayoutViewBasedOnAction(action: PortalActions) {
let result: LayoutView = 'category';
switch (action) {
case XtreamCodeActions.GetLiveCategories:
From bb0e832b6b1da4d667e5ffb981b911f5e64e615a Mon Sep 17 00:00:00 2001
From: 4gray <4gray@users.noreply.github.com>
Date: Sat, 12 Aug 2023 17:30:03 +0200
Subject: [PATCH 18/27] refactor(portals): some improvements in nav-bar
---
.../navigation-bar.component.html | 12 ++++++----
.../navigation-bar.component.scss | 22 +++++++++++--------
.../navigation-bar.component.ts | 15 ++++++++++++-
3 files changed, 35 insertions(+), 14 deletions(-)
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.html b/src/app/xtream/navigation-bar/navigation-bar.component.html
index 6671345cb..1cbfe90e7 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.html
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.html
@@ -28,11 +28,15 @@
- {{ item.title }}
+ {{ item.title }}
+ chevron_right
+
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.scss b/src/app/xtream/navigation-bar/navigation-bar.component.scss
index ae09b0113..5acc450b9 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.scss
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.scss
@@ -16,25 +16,29 @@
#sub-panel {
background: white;
border-bottom: 1px solid #ccc;
- padding: 0 10px 5px;
+ padding: 0 1em;
display: flex;
justify-content: space-between;
align-items: center;
- height: 30px;
+ height: 40px;
.breadcrumbs {
- span {
- cursor: pointer;
+ display: flex;
+
+ div {
+ display: flex;
+ align-items: center;
&:not(:last-child)::after {
- content: '>';
- margin: 0 10px;
+ display: none;
}
- }
- span:hover {
- text-decoration: underline;
+ span:hover {
+ text-decoration: underline;
+ cursor: pointer;
+ }
}
+
}
.search {
diff --git a/src/app/xtream/navigation-bar/navigation-bar.component.ts b/src/app/xtream/navigation-bar/navigation-bar.component.ts
index ad7a570af..9c7477d88 100644
--- a/src/app/xtream/navigation-bar/navigation-bar.component.ts
+++ b/src/app/xtream/navigation-bar/navigation-bar.component.ts
@@ -5,6 +5,7 @@ import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatIconModule } from '@angular/material/icon';
import { RouterLink } from '@angular/router';
+import { Subject, debounceTime, distinctUntilChanged } from 'rxjs';
import { Breadcrumb } from '../breadcrumb.interface';
import { ContentTypeNavigationItem } from '../content-type-navigation-item.interface';
import { ContentType } from '../content-type.enum';
@@ -30,14 +31,25 @@ export class NavigationBarComponent {
@Input({ required: true }) contentType: ContentType;
@Input() searchVisible = true;
@Input() contentTypeNavigationItems: ContentTypeNavigationItem[];
+ @Input() clientSideSearch = true;
@Output() contentTypeChanged = new EventEmitter