feat(database): implement database service for playlist management and operations

This commit is contained in:
4gray committed 2024-12-16 01:39:20 +01:00
1 parent 9cb326aa44
commit e710f472b4
3 files changed
+221

No files matched your search

+131
View File
@@ -0,0 +1,131 @@
import { Injectable } from '@angular/core';
import Database from '@tauri-apps/plugin-sql';
@Injectable({
providedIn: 'root',
})
export class DatabaseService {
private static db: Database | null = null;
async getConnection(): Promise<Database> {
if (!DatabaseService.db) {
DatabaseService.db = await Database.load('sqlite:database.db');
}
return DatabaseService.db;
}
/**
* Delete a playlist and all its related data
* @param playlistId ID of the playlist to delete
* @returns True if deletion was successful
*/
async deletePlaylist(playlistId: string): Promise<boolean> {
try {
const db = await this.getConnection();
// Start a transaction to ensure all related data is deleted
await db.execute('BEGIN TRANSACTION');
try {
// Delete from recently_viewed table (related to content which is related to playlist)
await db.execute(
`
DELETE FROM recently_viewed
WHERE content_id IN (
SELECT c.id
FROM content c
JOIN categories cat ON c.category_id = cat.id
WHERE cat.playlist_id = ?
)
`,
[playlistId]
);
// Delete content related to the playlist's categories
await db.execute(
`
DELETE FROM content
WHERE category_id IN (
SELECT id FROM categories WHERE playlist_id = ?
)
`,
[playlistId]
);
// Delete categories related to the playlist
await db.execute(
'DELETE FROM categories WHERE playlist_id = ?',
[playlistId]
);
// Finally, delete the playlist itself
await db.execute('DELETE FROM playlists WHERE id = ?', [
playlistId,
]);
// Commit the transaction
await db.execute('COMMIT');
return true;
} catch (error) {
// If any error occurs, rollback the transaction
await db.execute('ROLLBACK');
throw error;
}
} catch (error) {
console.error('Error deleting playlist:', error);
return false;
}
}
async updateXtreamPlaylist(playlist: any): Promise<boolean> {
try {
const db = await this.getConnection();
await db.execute('UPDATE playlists SET name = ? WHERE id = ?', [
playlist.name,
playlist.id,
]);
return true;
} catch (error) {
console.error('Error updating playlist:', error);
return false;
}
}
async updateXtreamPlaylistDetails(playlist: {
id: string;
title: string;
username?: string;
password?: string;
serverUrl?: string;
}): Promise<boolean> {
try {
const db = await this.getConnection();
const updateFields: string[] = ['name = ?'];
const params: any[] = [playlist.title];
if (playlist.username) {
updateFields.push('username = ?');
params.push(playlist.username);
}
if (playlist.password) {
updateFields.push('password = ?');
params.push(playlist.password);
}
if (playlist.serverUrl) {
updateFields.push('serverUrl = ?');
params.push(playlist.serverUrl);
}
params.push(playlist.id);
console.log(params);
const query = `UPDATE playlists SET ${updateFields.join(', ')} WHERE id = ?`;
await db.execute(query, params);
return true;
} catch (error) {
console.error('Error updating playlist details:', error);
return false;
}
}
}
+2
View File
@@ -49,6 +49,8 @@ export class TauriService extends DataService {
return invoke('open_in_mpv', {
url: (payload as any).url,
path: (payload as any).mpvPlayerPath || '',
title: (payload as any).title ?? '',
thumbnail: (payload as any).thumbnail ?? '',
}).catch((error) => {
window.postMessage({
type: ERROR,
@@ -0,0 +1,88 @@
import { Injectable } from '@angular/core';
import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
import { BehaviorSubject } from 'rxjs';
export interface MpvProcess {
id: number;
url: string;
start_time: number;
last_known_time: number | null;
thumbnail?: string;
title: string;
}
@Injectable({
providedIn: 'root',
})
export class MpvPlayerService {
private activeProcessesSubject = new BehaviorSubject<MpvProcess[]>([]);
public activeProcesses$ = this.activeProcessesSubject.asObservable();
constructor() {
this.initializeEventListeners();
this.loadActiveProcesses();
}
private async initializeEventListeners() {
// Listen for new processes
await listen('mpv-process-added', (event: any) => {
const newProcess = event.payload as MpvProcess;
if (newProcess) {
const currentProcesses = this.activeProcessesSubject.value;
this.activeProcessesSubject.next([
...currentProcesses,
newProcess,
]);
}
});
// Listen for removed processes
await listen('mpv-process-removed', (event: any) => {
const removedProcess = event.payload as MpvProcess;
if (removedProcess) {
const currentProcesses = this.activeProcessesSubject.value;
this.activeProcessesSubject.next(
currentProcesses.filter((p) => p.id !== removedProcess.id)
);
}
});
}
private async loadActiveProcesses() {
try {
const processes = await invoke<MpvProcess[]>(
'get_active_mpv_processes'
);
this.activeProcessesSubject.next(processes);
} catch (error) {
console.error('Failed to load active MPV processes:', error);
}
}
async openStream(
url: string,
title: string,
thumbnail?: string,
mpvPath: string = ''
): Promise<number> {
return await invoke<number>('open_in_mpv', {
url,
path: mpvPath,
title,
thumbnail,
});
}
async playStream(processId: number): Promise<void> {
await invoke('mpv_play', { processId });
}
async pauseStream(processId: number): Promise<void> {
await invoke('mpv_pause', { processId });
}
async closeStream(processId: number): Promise<void> {
await invoke('close_mpv_process', { processId });
}
}