Skip to content

Commit 7ee2cc4

Browse files
committed
feat(db): add API to delete all playlists and related rows
Add a new IPC handler_DELETE_ALL_PLAYLIST that removes all and related data from the SQLite database in a safe order that respects foreign key relationships. The handler deletes favorites and recently viewed entries first, then content, categories, and finally playlists. Errors are logged and propagated. Expose the new operation in the renderer preload API as dbDeleteAllPlaylists() to allow UI code to invoke the purge. This provides a single-call way to clear playlists and their dependent records for testing or user-driven reset.
1 parent ac39c2a commit 7ee2cc4

File tree

3 files changed

+67
-5
lines changed

3 files changed

+67
-5
lines changed

apps/electron-backend/src/app/api/main.preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,5 @@ contextBridge.exposeInMainWorld('electron', {
136136
ipcRenderer.invoke('DB_REMOVE_RECENT_ITEM', contentId, playlistId),
137137
dbGetContentByXtreamId: (xtreamId: number, playlistId: string) =>
138138
ipcRenderer.invoke('DB_GET_CONTENT_BY_XTREAM_ID', xtreamId, playlistId),
139+
dbDeleteAllPlaylists: () => ipcRenderer.invoke('DB_DELETE_ALL_PLAYLISTS'),
139140
});

apps/electron-backend/src/app/events/database.events.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,3 +985,31 @@ ipcMain.handle(
985985
}
986986
}
987987
);
988+
989+
/**
990+
* Delete all playlists and related data from SQLite
991+
*/
992+
ipcMain.handle('DB_DELETE_ALL_PLAYLISTS', async () => {
993+
try {
994+
const db = await getDatabase();
995+
996+
// Delete in order respecting foreign key constraints
997+
// First delete favorites and recently_viewed (they reference content)
998+
await db.delete(schema.favorites);
999+
await db.delete(schema.recentlyViewed);
1000+
1001+
// Then delete content (references categories)
1002+
await db.delete(schema.content);
1003+
1004+
// Then delete categories (references playlists)
1005+
await db.delete(schema.categories);
1006+
1007+
// Finally delete playlists
1008+
await db.delete(schema.playlists);
1009+
1010+
return { success: true };
1011+
} catch (error) {
1012+
console.error('Error deleting all playlists:', error);
1013+
throw error;
1014+
}
1015+
});

libs/m3u-state/src/lib/effects.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from 'rxjs';
1818
import { DataService, EpgService, PlaylistsService } from 'services';
1919
import {
20+
GLOBAL_FAVORITES_PLAYLIST_ID,
2021
OPEN_MPV_PLAYER,
2122
OPEN_VLC_PLAYER,
2223
Playlist,
@@ -71,6 +72,10 @@ export class PlaylistEffects {
7172
return this.actions$.pipe(
7273
ofType(PlaylistActions.setFavorites),
7374
combineLatestWith(this.store.select(selectActivePlaylistId)),
75+
filter(
76+
([, playlistId]) =>
77+
playlistId !== GLOBAL_FAVORITES_PLAYLIST_ID
78+
),
7479
switchMap(([action, playlistId]) =>
7580
this.playlistsService.setFavorites(
7681
playlistId,
@@ -207,9 +212,25 @@ export class PlaylistEffects {
207212
() => {
208213
return this.actions$.pipe(
209214
ofType(PlaylistActions.removePlaylist),
210-
switchMap((action) =>
211-
this.playlistsService.deletePlaylist(action.playlistId)
212-
)
215+
switchMap(async (action) => {
216+
// Delete from IndexedDB
217+
await firstValueFrom(
218+
this.playlistsService.deletePlaylist(action.playlistId)
219+
);
220+
// Also delete from SQLite if running in Electron
221+
if ((window as any).electron?.dbDeletePlaylist) {
222+
try {
223+
await (window as any).electron.dbDeletePlaylist(
224+
action.playlistId
225+
);
226+
} catch (error) {
227+
console.error(
228+
'Error deleting playlist from SQLite:',
229+
error
230+
);
231+
}
232+
}
233+
})
213234
);
214235
},
215236
{ dispatch: false }
@@ -350,8 +371,20 @@ export class PlaylistEffects {
350371
() => {
351372
return this.actions$.pipe(
352373
ofType(PlaylistActions.removeAllPlaylists),
353-
switchMap(() => this.playlistsService.removeAll()),
354-
tap(() => {
374+
switchMap(async () => {
375+
// Delete from IndexedDB
376+
await firstValueFrom(this.playlistsService.removeAll());
377+
// Also delete from SQLite if running in Electron
378+
if ((window as any).electron?.dbDeleteAllPlaylists) {
379+
try {
380+
await (window as any).electron.dbDeleteAllPlaylists();
381+
} catch (error) {
382+
console.error(
383+
'Error deleting playlists from SQLite:',
384+
error
385+
);
386+
}
387+
}
355388
this.snackBar.open(
356389
this.translate.instant('SETTINGS.PLAYLISTS_REMOVED'),
357390
undefined,

0 commit comments

Comments
 (0)