From b61530f27951fc92d6e3bef2b610a88498042be7 Mon Sep 17 00:00:00 2001 From: 4gray Date: Wed, 15 Oct 2025 23:31:08 +0200 Subject: [PATCH] feat(preloadtauri): add external player IPC and playlist auto-update MPV/VLC launch and playlist auto-update from the Electron preload and migrate Tauri invoke calls to use the exposed window.electron API. - Add openInMpv, openInVlc and autoUpdatePlaylists to the preload API, forwarding parameters to ipcRenderer for native handling. - Replace tauri invoke('open_in_mpv') and invoke('open_in_vlc') calls with window.electron.openInMpv / openInVlc in tauri.service to use the unified Electron IPC surface. - Replace file-based AUTO_UPDATE_PLAYLISTS handling with a call to window.electron.autoUpdatePlaylists and remove legacy file parsing code (now commented) so the main process owns playlist refresh logic. - Import shared AUTO_UPDATE_PLAYLISTS/Playlist types into preload. This centralizes native player launching and playlist updates through the preload IPC bridge, simplifying web service code and moving file I/O to the native/main layer for better security and separation of concerns. --- .../src/app/api/main.preload.ts | 37 ++++++++++++++++ apps/web/src/app/services/tauri.service.ts | 42 +++++++++---------- global.d.ts | 17 ++++++++ 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/apps/electron-backend/src/app/api/main.preload.ts b/apps/electron-backend/src/app/api/main.preload.ts index f29b265b8..609821456 100644 --- a/apps/electron-backend/src/app/api/main.preload.ts +++ b/apps/electron-backend/src/app/api/main.preload.ts @@ -1,4 +1,5 @@ import { contextBridge, ipcRenderer } from 'electron'; +import { AUTO_UPDATE_PLAYLISTS, Playlist } from 'shared-interfaces'; contextBridge.exposeInMainWorld('electron', { getAppVersion: () => ipcRenderer.invoke('get-app-version'), @@ -10,4 +11,40 @@ contextBridge.exposeInMainWorld('electron', { openPlaylistFromFile: () => ipcRenderer.invoke('open-playlist-from-file'), setUserAgent: (userAgent: string, referer?: string) => ipcRenderer.send('set-user-agent', userAgent, referer), + openInMpv: ( + url: string, + path: string, + title: string, + userAgent: string, + referer?: string, + origin?: string + ) => + ipcRenderer.send( + 'open-in-mpv', + url, + path, + title, + userAgent, + referer, + origin + ), + openInVlc: ( + url: string, + path: string, + title: string, + userAgent: string, + referer?: string, + origin?: string + ) => + ipcRenderer.send( + 'open-in-vlc', + url, + path, + title, + userAgent, + referer, + origin + ), + autoUpdatePlaylists: (playlists: Playlist[]) => + ipcRenderer.send(AUTO_UPDATE_PLAYLISTS, playlists), }); diff --git a/apps/web/src/app/services/tauri.service.ts b/apps/web/src/app/services/tauri.service.ts index bf32e047f..aa68375c3 100644 --- a/apps/web/src/app/services/tauri.service.ts +++ b/apps/web/src/app/services/tauri.service.ts @@ -1,12 +1,8 @@ import { inject, Injectable } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Params } from '@angular/router'; -import { invoke } from '@tauri-apps/api/core'; import { listen } from '@tauri-apps/api/event'; -import { readTextFile } from '@tauri-apps/plugin-fs'; import { fetch } from '@tauri-apps/plugin-http'; -import { parse } from 'iptv-playlist-parser'; -import { createPlaylistObject } from 'm3u-utils'; import { DataService } from 'services'; import { AUTO_UPDATE_PLAYLISTS, @@ -81,15 +77,15 @@ export class TauriService extends DataService { } else if (type === 'OPEN_MPV_PLAYER') { const data = payload as any; try { - return await invoke('open_in_mpv', { - url: data.url, - path: data.mpvPlayerPath || '', - title: data.title ?? '', - thumbnail: data.thumbnail ?? '', - userAgent: data['user-agent'] ?? undefined, - referer: data.referer ?? undefined, - origin: data.origin ?? undefined, - }); + return await window.electron.openInMpv( + data.url, + data.mpvPlayerPath || '', + data.title ?? '', + data['user-agent'] ?? undefined, + data.referer ?? undefined, + data.origin ?? undefined + ); + /* thumbnail: data.thumbnail ?? '', */ } catch (error) { this.snackBar.open(`Error launching MPV: ${error}`, 'Close', { duration: 5000, @@ -100,13 +96,13 @@ export class TauriService extends DataService { } else if (type === 'OPEN_VLC_PLAYER') { const data = payload as any; try { - return await invoke('open_in_vlc', { - url: data.url, - path: data.vlcPlayerPath || '', - userAgent: data['user-agent'] ?? undefined, - referer: data.referer ?? undefined, - origin: data.origin ?? undefined, - }); + return await window.electron.openInVlc( + data.url, + data.vlcPlayerPath || '', + data['user-agent'] ?? undefined, + data.referer ?? undefined, + data.origin ?? undefined + ); } catch (error) { this.snackBar.open(`Error launching VLC: ${error}`, 'Close', { duration: 5000, @@ -120,10 +116,9 @@ export class TauriService extends DataService { payload, }); } else if (type === AUTO_UPDATE_PLAYLISTS) { - const playlists = []; const data = payload as Playlist[]; - - for await (const item of data) { + const playlists = await window.electron.autoUpdatePlaylists(data); + /* for await (const item of data) { if (item.filePath) { const playlist = await readTextFile(item.filePath); const parsedPlaylist = parse(playlist); @@ -136,6 +131,7 @@ export class TauriService extends DataService { playlists.push({ ...playlistObject, _id: item._id }); } } + */ window.postMessage({ type: AUTO_UPDATE_PLAYLISTS_RESPONSE, payload: { diff --git a/global.d.ts b/global.d.ts index a0bdc8889..9c97149f3 100644 --- a/global.d.ts +++ b/global.d.ts @@ -22,6 +22,23 @@ declare global { ) => Promise; openPlaylistFromFile: () => Promise; setUserAgent: (userAgent: string, referer?: string) => void; + openInMpv: ( + url: string, + path: string, + title: string, + userAgent: string, + referer?: string, + origin?: string + ) => any; + openInVlc: ( + url: string, + path: string, + title: string, + userAgent: string, + referer?: string, + origin?: string + ) => any; + autoUpdatePlaylists: (playlists: Playlist[]) => any; }; process: NodeJS.Process; require: NodeRequire;