feat(web): refresh the current view after deleting a song or playlist
Deletes left the removed item visible because the list loaders are cached (getPlaylists ~3 min): deletePlaylist navigated to a still-cached list, and deleteSong only reloaded playlists. Add refreshCurrentView() — drops the API cache and re-runs the active nav entry's loader (playlists, playlist/album/artist detail, starred, home, …). deleteSong calls it after the delete+rescan delay; deletePlaylist invalidates getPlaylists before navigating. Bump SW cache to ns-v46. Also record the post-1.2 work in the 1.2 changelog (importer Enter, search single-song + radio, NowPlaying order, official-audio artist-metadata match, JP-katakana album artist fix, year back-fill, delete refresh). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
966b318d9e
commit
d98978a6c7
5 files changed
+36
-8
No files matched your search
+4
-6
@@ -2,7 +2,7 @@ import { S } from '../state.js';
|
||||
import { esc, formatDur, toast } from '../utils.js';
|
||||
import { api, coverUrl, fetchRomajiIndex, romajiLookup, getRomajiOverrides, invalidateRomajiIndex, invalidateApiCache } from '../api.js';
|
||||
// Circular — safe (only used inside function bodies)
|
||||
import { loadPlaylists, loadPlaylistDetail } from '../views/views.js';
|
||||
import { loadPlaylists, loadPlaylistDetail, refreshCurrentView } from '../views/views.js';
|
||||
import { showConfirm } from './modals.js';
|
||||
|
||||
// ─── SONG INFO MODAL ───
|
||||
@@ -312,11 +312,9 @@ export async function deleteSong() {
|
||||
if (!r.ok) throw new Error(d.error || `HTTP ${r.status}`);
|
||||
toast(`🗑 "${s.title}" gelöscht`);
|
||||
closeInfoModal();
|
||||
setTimeout(() => {
|
||||
loadPlaylists();
|
||||
if (document.getElementById('page-playlist-detail')?.classList.contains('active') && S._currentPlaylist)
|
||||
loadPlaylistDetail(S._currentPlaylist);
|
||||
}, 3000);
|
||||
// Backend delete + Navidrome rescan takes a moment; then refresh whatever view is open (album,
|
||||
// artist, playlist, starred, …) so the removed song disappears without a manual reload.
|
||||
setTimeout(() => refreshCurrentView(), 3000);
|
||||
} catch (e) {
|
||||
status.textContent = '❌ Fehler: ' + e.message;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
import { S } from '../state.js';
|
||||
import { esc, toast } from '../utils.js';
|
||||
import { api, coverUrl, ndAuth } from '../api.js';
|
||||
import { api, coverUrl, ndAuth, invalidateApiCache } from '../api.js';
|
||||
// Circular — safe (only used inside function bodies)
|
||||
import { playQueue, dlSongLocal, nativeInsertAt, renderQueue } from '../player/player.js';
|
||||
import { navigate, loadPlaylists, loadPlaylistDetail } from '../views/views.js';
|
||||
@@ -235,6 +235,7 @@ export async function deletePlaylist() {
|
||||
await api('deletePlaylist', `&id=${pl.id}`);
|
||||
closeEditPlModal();
|
||||
toast(`🗑 "${pl.name}" gelöscht`);
|
||||
invalidateApiCache('getPlaylists'); // drop the 3-min cache so the list reloads without the deleted playlist
|
||||
navigate('playlists');
|
||||
} catch(e) { toast('Fehler beim Löschen: ' + e.message); }
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { loadHomeData, loadAlbumRow, loadArtists, loadAlbums, loadGenreDetail }
|
||||
import { loadArtistDetail, loadArtistAllSongs, loadAlbumDetail, loadItunesAlbumDetail, loadPartialAlbumDetail } from './detail.js';
|
||||
import { loadPlaylists, loadPlaylistDetail, loadStarred, loadRandom } from './playlists.js';
|
||||
import { loadNewReleases, loadRecommendations } from './discover.js';
|
||||
import { invalidateApiCache } from '../api.js';
|
||||
|
||||
// ─── NAVIGATION HISTORY ───
|
||||
export function _navSave() {
|
||||
@@ -36,6 +37,27 @@ export function closeHeaderSearch() {
|
||||
clearTimeout(S._headerSearchTimer);
|
||||
}
|
||||
|
||||
// Force-refresh the active view after a mutating action (delete a song / playlist, etc.): drop the
|
||||
// cached API responses so the reload is fresh, then re-run the current nav entry's loader.
|
||||
export function refreshCurrentView() {
|
||||
invalidateApiCache();
|
||||
const entry = S._navStack[S._navCursor];
|
||||
if (!entry) return;
|
||||
const { page, data } = entry;
|
||||
switch (page) {
|
||||
case 'home': loadHomeData(true); break;
|
||||
case 'albums': loadAlbums(); break;
|
||||
case 'artists': loadArtists(); break;
|
||||
case 'starred': loadStarred(); break;
|
||||
case 'random': loadRandom(); break;
|
||||
case 'playlists': loadPlaylists(); break;
|
||||
case 'playlist-detail': if (data) loadPlaylistDetail(data); break;
|
||||
case 'album-detail': if (data) loadAlbumDetail(data); break;
|
||||
case 'artist-detail': if (data) loadArtistDetail(data); break;
|
||||
case 'genre-detail': if (data) loadGenreDetail(data); break;
|
||||
}
|
||||
}
|
||||
|
||||
export function navigate(page, data=null) {
|
||||
closeHeaderSearch();
|
||||
document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
|
||||
|
||||
Reference in new issue
Block a user