mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
fix: refresh local playlist functionallity
This commit is contained in:
1 parent
b07bda2663
commit
a3a8f96eaa
6 files changed
+90
-84
No files matched your search
@@ -42,7 +42,6 @@ export class HomeComponent {
|
||||
{
|
||||
id: ERROR,
|
||||
execute: (error: { message: string; status: string }) => {
|
||||
//this.isLoading = false;
|
||||
this.showNotification('Error: ' + error.message);
|
||||
},
|
||||
},
|
||||
@@ -64,19 +63,19 @@ export class HomeComponent {
|
||||
*/
|
||||
setRendererListeners(): void {
|
||||
this.commandsList.forEach((command) => {
|
||||
if (this.dataService.isElectron) {
|
||||
/* if (this.dataService.isElectron) {
|
||||
this.dataService.listenOn(command.id, (event, response) =>
|
||||
this.ngZone.run(() => command.execute(response))
|
||||
);
|
||||
} else {
|
||||
const cb = (response) => {
|
||||
if (response.data.type === command.id) {
|
||||
command.execute(response.data);
|
||||
}
|
||||
};
|
||||
this.dataService.listenOn(command.id, cb);
|
||||
this.listeners.push(cb);
|
||||
}
|
||||
} else { */
|
||||
const cb = (response) => {
|
||||
if (response.data.type === command.id) {
|
||||
command.execute(response.data);
|
||||
}
|
||||
};
|
||||
this.dataService.listenOn(command.id, cb);
|
||||
this.listeners.push(cb);
|
||||
/* } */
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
Input,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
Output,
|
||||
ViewChild,
|
||||
@@ -24,7 +23,6 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { NgxSkeletonLoaderComponent } from 'ngx-skeleton-loader';
|
||||
import { BehaviorSubject, combineLatest, map } from 'rxjs';
|
||||
import { GLOBAL_FAVORITES_PLAYLIST_ID } from '../../../../shared/constants';
|
||||
import { IpcCommand } from '../../../../shared/ipc-command.class';
|
||||
import { Playlist } from '../../../../shared/playlist.interface';
|
||||
import { DataService } from '../../services/data.service';
|
||||
import { DatabaseService } from '../../services/database.service';
|
||||
@@ -118,36 +116,41 @@ export class RecentPlaylistsComponent implements OnDestroy {
|
||||
|
||||
/** IPC Renderer commands list with callbacks */
|
||||
commandsList = [
|
||||
new IpcCommand(
|
||||
PLAYLIST_UPDATE_RESPONSE,
|
||||
(response: { message: string; playlist: Playlist }) => {
|
||||
this.snackBar.open(response.message, null, { duration: 2000 });
|
||||
{
|
||||
id: PLAYLIST_UPDATE_RESPONSE,
|
||||
execute: (response: {
|
||||
payload: { message: string; playlist: Playlist };
|
||||
}) => {
|
||||
this.snackBar.open(response.payload.message, null, {
|
||||
duration: 2000,
|
||||
});
|
||||
this.store.dispatch(
|
||||
PlaylistActions.updatePlaylist({
|
||||
playlistId: response.playlist._id,
|
||||
playlist: response.playlist,
|
||||
playlistId: response.payload.playlist._id,
|
||||
playlist: response.payload.playlist,
|
||||
})
|
||||
);
|
||||
}
|
||||
),
|
||||
new IpcCommand(
|
||||
AUTO_UPDATE_PLAYLISTS_RESPONSE,
|
||||
(playlists: Playlist[]) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
id: AUTO_UPDATE_PLAYLISTS_RESPONSE,
|
||||
execute: (playlists: Playlist[]) => {
|
||||
this.store.dispatch(
|
||||
PlaylistActions.updateManyPlaylists({
|
||||
playlists,
|
||||
})
|
||||
);
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
listeners = [];
|
||||
|
||||
constructor(
|
||||
private readonly databaseService: DatabaseService,
|
||||
private readonly dialog: MatDialog,
|
||||
private readonly dialogService: DialogService,
|
||||
private readonly electronService: DataService,
|
||||
private readonly ngZone: NgZone,
|
||||
private readonly dataService: DataService,
|
||||
private readonly router: Router,
|
||||
private readonly snackBar: MatSnackBar,
|
||||
private readonly sortService: SortService,
|
||||
@@ -159,16 +162,15 @@ export class RecentPlaylistsComponent implements OnDestroy {
|
||||
this.setRendererListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set electrons main process listeners
|
||||
*/
|
||||
setRendererListeners(): void {
|
||||
this.commandsList.forEach((command) => {
|
||||
if (this.electronService.isElectron) {
|
||||
this.electronService.listenOn(command.id, (event, response) =>
|
||||
this.ngZone.run(() => command.callback(response))
|
||||
);
|
||||
}
|
||||
const cb = (response) => {
|
||||
if (response.data.type === command.id) {
|
||||
command.execute(response.data);
|
||||
}
|
||||
};
|
||||
this.dataService.listenOn(command.id, cb);
|
||||
this.listeners.push(cb);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -241,8 +243,8 @@ export class RecentPlaylistsComponent implements OnDestroy {
|
||||
* Sends an IPC event with the playlist details to the main process to trigger the refresh operation
|
||||
* @param item playlist to update
|
||||
*/
|
||||
refreshPlaylist(item: PlaylistMeta): void {
|
||||
this.electronService.sendIpcEvent(PLAYLIST_UPDATE, {
|
||||
refreshPlaylist(item: PlaylistMeta) {
|
||||
this.dataService.sendIpcEvent(PLAYLIST_UPDATE, {
|
||||
id: item._id,
|
||||
title: item.title,
|
||||
...(item.url ? { url: item.url } : { filePath: item.filePath }),
|
||||
@@ -250,22 +252,20 @@ export class RecentPlaylistsComponent implements OnDestroy {
|
||||
}
|
||||
|
||||
migratePlaylists() {
|
||||
this.electronService.sendIpcEvent(MIGRATE_PLAYLISTS);
|
||||
this.dataService.sendIpcEvent(MIGRATE_PLAYLISTS);
|
||||
}
|
||||
|
||||
deleteMigratedPlaylists() {
|
||||
this.electronService.sendIpcEvent(DELETE_ALL_PLAYLISTS);
|
||||
this.dataService.sendIpcEvent(DELETE_ALL_PLAYLISTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes command listeners on component destroy
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
if (this.electronService.isElectron) {
|
||||
this.commandsList.forEach((command) =>
|
||||
this.electronService.removeAllListeners(command.id)
|
||||
);
|
||||
}
|
||||
this.listeners.forEach((listener) => {
|
||||
window.removeEventListener('message', listener);
|
||||
});
|
||||
}
|
||||
|
||||
trackByFn(_index: number, item: PlaylistMeta) {
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
formControlName="playlistUrl"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<p *ngIf="!isElectron">
|
||||
{{ 'HOME.URL_UPLOAD.CORS_NOTE' | translate }}
|
||||
</p>
|
||||
@if (!isTauri) {
|
||||
<p>
|
||||
{{ 'HOME.URL_UPLOAD.CORS_NOTE' | translate }}
|
||||
</p>
|
||||
}
|
||||
<button
|
||||
class="add-button"
|
||||
mat-flat-button
|
||||
|
||||
@@ -1,43 +1,30 @@
|
||||
import { NgIf } from '@angular/common';
|
||||
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, inject, OnInit, Output } from '@angular/core';
|
||||
import {
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatButton } from '@angular/material/button';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { DataService } from '../../services/data.service';
|
||||
import { isTauri } from '@tauri-apps/api/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-url-upload',
|
||||
templateUrl: './url-upload.component.html',
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatCardModule,
|
||||
MatInputModule,
|
||||
NgIf,
|
||||
ReactiveFormsModule,
|
||||
TranslatePipe,
|
||||
],
|
||||
imports: [MatButton, MatInputModule, ReactiveFormsModule, TranslatePipe],
|
||||
})
|
||||
export class UrlUploadComponent implements OnInit {
|
||||
private readonly fb = inject(FormBuilder);
|
||||
|
||||
/** Emits url string to the parent component on form submit */
|
||||
@Output() urlAdded: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
form: FormGroup;
|
||||
isTauri = isTauri();
|
||||
|
||||
isElectron = this.dataService.isElectron;
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private dataService: DataService
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
ngOnInit() {
|
||||
const urlRegex = '(https?://.*?)';
|
||||
this.form = this.fb.group({
|
||||
playlistUrl: [
|
||||
|
||||
@@ -71,7 +71,7 @@ export const COMPONENT_OVERLAY_REF = new InjectionToken(
|
||||
ArtPlayerComponent,
|
||||
],
|
||||
templateUrl: './video-player.component.html',
|
||||
styleUrls: ['./video-player.component.scss']
|
||||
styleUrl: './video-player.component.scss',
|
||||
})
|
||||
export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||
/** Active selected channel */
|
||||
@@ -208,6 +208,7 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Opens a playlist provided as a url param
|
||||
* e.g. iptvnat.or?url=http://...
|
||||
* @pwaOnly
|
||||
*/
|
||||
getPlaylistUrlAsParam() {
|
||||
const URL_REGEX = /^(http|https|file):\/\/[^ "]+$/;
|
||||
@@ -221,9 +222,6 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set electrons main process listeners
|
||||
*/
|
||||
setRendererListeners(): void {
|
||||
this.commandsList.forEach((command) => {
|
||||
if (this.isTauri) {
|
||||
@@ -252,20 +250,14 @@ export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||
player: settings.player || VideoPlayer.VideoJs,
|
||||
showCaptions: settings.showCaptions || false,
|
||||
};
|
||||
// Don't override volume from settings storage anymore
|
||||
// as we're using localStorage for volume persistence
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.isTauri) {
|
||||
this.dataService.removeAllListeners(PLAYLIST_PARSE_RESPONSE);
|
||||
} else {
|
||||
this.listeners.forEach((listener) =>
|
||||
window.removeEventListener('message', listener)
|
||||
);
|
||||
}
|
||||
this.listeners.forEach((listener) =>
|
||||
window.removeEventListener('message', listener)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { readTextFile } from '@tauri-apps/plugin-fs';
|
||||
import { fetch } from '@tauri-apps/plugin-http';
|
||||
import { parse } from 'iptv-playlist-parser';
|
||||
import {
|
||||
@@ -8,6 +9,8 @@ import {
|
||||
ERROR,
|
||||
PLAYLIST_PARSE_BY_URL,
|
||||
PLAYLIST_PARSE_RESPONSE,
|
||||
PLAYLIST_UPDATE,
|
||||
PLAYLIST_UPDATE_RESPONSE,
|
||||
XTREAM_RESPONSE,
|
||||
} from '../../../shared/ipc-commands';
|
||||
import { Playlist } from '../../../shared/playlist.interface';
|
||||
@@ -31,8 +34,31 @@ export class TauriService extends DataService {
|
||||
async sendIpcEvent(type: string, payload?: unknown) {
|
||||
if (type === PLAYLIST_PARSE_BY_URL) {
|
||||
this.fetchFromUrl(payload);
|
||||
} else if (type === 'PLAYLIST_UPDATE') {
|
||||
console.log('PLAYLIST_UPDATE');
|
||||
} else if (type === PLAYLIST_UPDATE) {
|
||||
const data = payload as {
|
||||
id: string;
|
||||
filePath: string;
|
||||
title: string;
|
||||
};
|
||||
const playlist = await readTextFile(data.filePath);
|
||||
const parsedPlaylist = parse(playlist);
|
||||
const playlistObject = createPlaylistObject(
|
||||
data.title,
|
||||
parsedPlaylist,
|
||||
data.filePath,
|
||||
'FILE'
|
||||
);
|
||||
|
||||
window.postMessage({
|
||||
type: PLAYLIST_UPDATE_RESPONSE,
|
||||
payload: {
|
||||
message: 'Success! The playlist was successfully updated',
|
||||
playlist: {
|
||||
...playlistObject,
|
||||
_id: data.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
} else if (type === 'XTREAM_REQUEST') {
|
||||
return await this.forwardXtreamRequest(
|
||||
payload as { url: string; params: Record<string, string> }
|
||||
|
||||
Reference in new issue
Block a user