diff --git a/public/js/pages/MoviesPage.js b/public/js/pages/MoviesPage.js index 37b44b4..f1ac2ce 100644 --- a/public/js/pages/MoviesPage.js +++ b/public/js/pages/MoviesPage.js @@ -27,9 +27,9 @@ class MoviesPage { init() { // Source change handler - this.sourceSelect?.addEventListener('change', () => { - this.loadCategories(); - this.loadMovies(); + this.sourceSelect?.addEventListener('change', async () => { + await this.loadCategories(); + await this.loadMovies(); }); // Category change handler diff --git a/public/js/pages/SeriesPage.js b/public/js/pages/SeriesPage.js index 7f01299..ef3dfd4 100644 --- a/public/js/pages/SeriesPage.js +++ b/public/js/pages/SeriesPage.js @@ -31,9 +31,9 @@ class SeriesPage { init() { // Source change handler - this.sourceSelect?.addEventListener('change', () => { - this.loadCategories(); - this.loadSeries(); + this.sourceSelect?.addEventListener('change', async () => { + await this.loadCategories(); + await this.loadSeries(); }); // Category change handler diff --git a/server/services/syncService.js b/server/services/syncService.js index e909c2c..71eae00 100644 --- a/server/services/syncService.js +++ b/server/services/syncService.js @@ -252,10 +252,15 @@ class SyncService { /** * Batch save streams (channels, vod, series) + * Also purges stale entries that no longer exist in the source */ async saveStreams(sourceId, type, items) { if (!items || items.length === 0) return; const db = getDb(); + + // Collect all IDs we're syncing + const syncedIds = new Set(); + const stmt = db.prepare(` INSERT INTO playlist_items ( id, source_id, item_id, type, name, category_id, @@ -302,6 +307,7 @@ class SyncService { } const id = `${sourceId}:${itemId}`; + syncedIds.add(id); stmt.run( id, @@ -329,6 +335,32 @@ class SyncService { await new Promise(resolve => setImmediate(resolve)); } + // Purge stale entries that no longer exist in the source + // Use temp table approach to avoid SQL parameter limits with large playlists + if (syncedIds.size > 0) { + db.exec('CREATE TEMP TABLE IF NOT EXISTS synced_ids (id TEXT PRIMARY KEY)'); + db.exec('DELETE FROM synced_ids'); + + const insertTemp = db.prepare('INSERT OR IGNORE INTO synced_ids (id) VALUES (?)'); + const insertTempBatch = db.transaction((ids) => { + for (const id of ids) { + insertTemp.run(id); + } + }); + insertTempBatch([...syncedIds]); + + const deleteStmt = db.prepare(` + DELETE FROM playlist_items + WHERE source_id = ? AND type = ? + AND id NOT IN (SELECT id FROM synced_ids) + `); + const deleted = deleteStmt.run(sourceId, type); + + if (deleted.changes > 0) { + console.log(`[Sync] Purged ${deleted.changes} stale ${type} items`); + } + } + console.log(`[Sync] Saved ${items.length} ${type} items`); }