diff --git a/src/pages/PlaylistEditPage.tsx b/src/pages/PlaylistEditPage.tsx index 9a6618d..04455d2 100644 --- a/src/pages/PlaylistEditPage.tsx +++ b/src/pages/PlaylistEditPage.tsx @@ -560,14 +560,32 @@ export function PlaylistEditPage() { await playlistsService.addSoundToPlaylist(playlistId, soundId, position) toast.success('Sound added to playlist') - // Refresh playlist sounds - await fetchSounds() - - // Remove the added sound from available sounds - setAvailableSounds(prev => prev.filter(s => s.id !== soundId)) - - // Refresh playlist data to update counts - await fetchPlaylist() + // Find the sound in available sounds to get its data + const soundToAdd = availableSounds.find(s => s.id === soundId) + if (soundToAdd) { + // Optimistically update the state without refetching + const newPlaylistSound = { + ...soundToAdd, + // Add any missing properties that PlaylistSound has but Sound doesn't + } + setSounds(prev => [...prev, newPlaylistSound]) + + // Remove from available sounds + setAvailableSounds(prev => prev.filter(s => s.id !== soundId)) + + // Only update the playlist counter optimistically (avoid full refetch) + if (playlist) { + setPlaylist(prev => prev ? { + ...prev, + sound_count: (prev.sound_count || 0) + 1, + total_duration: (prev.total_duration || 0) + (soundToAdd.duration || 0) + } : null) + } + } else { + // Fallback to refresh if we can't find the sound data + await fetchSounds() + await fetchPlaylist() + } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to add sound to playlist' toast.error(errorMessage) @@ -576,33 +594,53 @@ export function PlaylistEditPage() { const handleRemoveSound = async (soundId: number) => { try { - // Find the sound being removed to check if it's EXT type + // Find the sound being removed const removedSound = sounds.find(s => s.id === soundId) + if (!removedSound) return await playlistsService.removeSoundFromPlaylist(playlistId, soundId) + + // Optimistically update the sounds list (backend reorders automatically) setSounds(prev => prev.filter(sound => sound.id !== soundId)) toast.success('Sound removed from playlist') // If it's an EXT sound and we're in add mode, add it back to available sounds - if (isAddMode && removedSound && removedSound.type === 'EXT') { - // Get the full sound data from the API to add back to available sounds - try { - const allExtSounds = await soundsService.getSoundsByType('EXT') - const soundToAddBack = allExtSounds.find(s => s.id === soundId) - if (soundToAddBack) { - setAvailableSounds(prev => [...prev, soundToAddBack].sort((a, b) => a.name.localeCompare(b.name))) - } - } catch { - // If we can't fetch the sound data, just refresh the available sounds - await fetchAvailableSounds() + if (isAddMode && removedSound.type === 'EXT') { + // Convert PlaylistSound back to Sound format for available list + const soundToAddBack = { + id: removedSound.id, + name: removedSound.name, + filename: removedSound.filename, + duration: removedSound.duration, + size: removedSound.size, + hash: removedSound.hash, + type: removedSound.type, + play_count: removedSound.play_count, + is_normalized: removedSound.is_normalized, + normalized_filename: removedSound.normalized_filename, + normalized_duration: removedSound.normalized_duration, + normalized_size: removedSound.normalized_size, + normalized_hash: removedSound.normalized_hash, + created_at: removedSound.created_at, + updated_at: removedSound.updated_at } + setAvailableSounds(prev => [...prev, soundToAddBack].sort((a, b) => a.name.localeCompare(b.name))) } - // Refresh playlist data to update counts - await fetchPlaylist() + // Optimistically update playlist stats + if (playlist) { + setPlaylist(prev => prev ? { + ...prev, + sound_count: Math.max(0, (prev.sound_count || 0) - 1), + total_duration: Math.max(0, (prev.total_duration || 0) - (removedSound.duration || 0)) + } : null) + } } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Failed to remove sound' toast.error(errorMessage) + // On error, refresh to get correct state + await fetchSounds() + await fetchPlaylist() } }