From 177a166c055f9429c7f80b28837bcbf9fe05c4b0 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 10 Mar 2025 20:00:35 +0100 Subject: [PATCH] fix: improve playlist removal process with success notification and optimized database queries --- .../recent-playlists.component.spec.ts | 7 --- .../recent-playlists.component.ts | 19 ++++++-- src/app/services/database.service.ts | 46 ++++++++++++------- src/assets/i18n/en.json | 3 +- 4 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/app/home/recent-playlists/recent-playlists.component.spec.ts b/src/app/home/recent-playlists/recent-playlists.component.spec.ts index ccdc4d228..c57dc6c4e 100644 --- a/src/app/home/recent-playlists/recent-playlists.component.spec.ts +++ b/src/app/home/recent-playlists/recent-playlists.component.spec.ts @@ -103,13 +103,6 @@ describe('RecentPlaylistsComponent', () => { expect(dialogService.openConfirmDialog).toHaveBeenCalledTimes(1); }); - it('should send an event to the main process to remove a playlist', () => { - const playlistId = '12345'; - jest.spyOn(mockStore, 'dispatch'); - component.removePlaylist(playlistId); - expect(mockStore.dispatch).toHaveBeenCalledTimes(1); - }); - it('should send an event to the main process to refresh a playlist', () => { const playlistMeta: PlaylistMeta = { id: 'iptv1', diff --git a/src/app/home/recent-playlists/recent-playlists.component.ts b/src/app/home/recent-playlists/recent-playlists.component.ts index 8a4f20277..2ff797b8e 100644 --- a/src/app/home/recent-playlists/recent-playlists.component.ts +++ b/src/app/home/recent-playlists/recent-playlists.component.ts @@ -226,7 +226,9 @@ export class RecentPlaylistsComponent implements OnDestroy { message: this.translate.instant( 'HOME.PLAYLISTS.REMOVE_DIALOG.MESSAGE' ), - onConfirm: (): void => this.removePlaylist(playlistId), + onConfirm: () => { + this.removePlaylist(playlistId); + }, }); } @@ -234,9 +236,18 @@ export class RecentPlaylistsComponent implements OnDestroy { * Removes the provided playlist from the database * @param playlistId playlist id to remove */ - removePlaylist(playlistId: string) { - this.databaseService.deletePlaylist(playlistId); - this.store.dispatch(PlaylistActions.removePlaylist({ playlistId })); + async removePlaylist(playlistId: string) { + const deleted = await this.databaseService.deletePlaylist(playlistId); + if (deleted) { + this.store.dispatch(PlaylistActions.removePlaylist({ playlistId })); + this.snackBar.open( + this.translate.instant('HOME.PLAYLISTS.REMOVE_DIALOG.SUCCESS'), + null, + { + duration: 2000, + } + ); + } } /** diff --git a/src/app/services/database.service.ts b/src/app/services/database.service.ts index 8c905a50f..9c20a2d3c 100644 --- a/src/app/services/database.service.ts +++ b/src/app/services/database.service.ts @@ -67,31 +67,41 @@ export class DatabaseService { await db.execute('BEGIN TRANSACTION'); try { - // Delete from recently_viewed table (related to content which is related to playlist) + // First, delete favorites related to the playlist to reduce foreign key checks 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 = ? - ) - `, + 'DELETE FROM favorites WHERE playlist_id = ?', [playlistId] ); - // Delete content related to the playlist's categories + // Delete recently_viewed entries directly using playlist_id await db.execute( - ` - DELETE FROM content - WHERE category_id IN ( - SELECT id FROM categories WHERE playlist_id = ? - ) - `, + 'DELETE FROM recently_viewed WHERE playlist_id = ?', [playlistId] ); + // Get category IDs first to speed up content deletion (avoids subquery) + const categories = await db.select<{ id: number }[]>( + 'SELECT id FROM categories WHERE playlist_id = ?', + [playlistId] + ); + + if (categories.length > 0) { + // Create a list of category IDs for the IN clause + const categoryIds = categories.map((cat) => cat.id); + + // Delete content in batches if there are many categories + const BATCH_SIZE = 20; + for (let i = 0; i < categoryIds.length; i += BATCH_SIZE) { + const batchIds = categoryIds.slice(i, i + BATCH_SIZE); + const placeholders = batchIds.map(() => '?').join(','); + + await db.execute( + `DELETE FROM content WHERE category_id IN (${placeholders})`, + batchIds + ); + } + } + // Delete categories related to the playlist await db.execute( 'DELETE FROM categories WHERE playlist_id = ?', @@ -105,9 +115,11 @@ export class DatabaseService { // Commit the transaction await db.execute('COMMIT'); + console.log('Playlist deleted successfully'); return true; } catch (error) { // If any error occurs, rollback the transaction + console.error('Error in transaction, rolling back:', error); await db.execute('ROLLBACK'); throw error; } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 0b16dc17a..f45a0495c 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -137,7 +137,8 @@ "REMOVE_ALL_DESCRIPTION": "It will remove all existing playlists from the application.", "REMOVE_DIALOG": { "TITLE": "Remove all playlists", - "MESSAGE": "Are you sure you want to delete all playlist from the application?" + "MESSAGE": "Are you sure you want to delete all playlist from the application?", + "SUCESS": "Playlist was removed successfully" }, "IMPORT_ERROR": "Import error, please try with another file.", "PLAYLISTS_REMOVED": "All playlists were removed.",