diff --git a/src/components/common/SongInfo.tsx b/src/components/common/SongInfo.tsx index 114634f..9a5a116 100644 --- a/src/components/common/SongInfo.tsx +++ b/src/components/common/SongInfo.tsx @@ -7,14 +7,14 @@ import { add, heart, heartOutline, ban, checkmark, close, people } from 'ionicons/icons'; import { useAppSelector } from '../../redux'; -import { selectIsAdmin, selectFavorites, selectSongs } from '../../redux'; +import { selectIsAdmin, selectFavorites, selectSongs, selectQueue } from '../../redux'; import { useSongOperations } from '../../hooks/useSongOperations'; import { useDisabledSongs } from '../../hooks/useDisabledSongs'; import { useSelectSinger } from '../../hooks/useSelectSinger'; import { useToast } from '../../hooks/useToast'; import SelectSinger from './SelectSinger'; import { SongInfoDisplay } from './SongItem'; -import type { Song } from '../../types'; +import type { Song, QueueItem } from '../../types'; interface SongInfoProps { isOpen: boolean; @@ -26,6 +26,7 @@ const SongInfo: React.FC = ({ isOpen, onClose, song }) => { const isAdmin = useAppSelector(selectIsAdmin); const favorites = useAppSelector(selectFavorites); const allSongs = useAppSelector(selectSongs); + const queue = useAppSelector(selectQueue); const { toggleFavorite } = useSongOperations(); const { isSongDisabled, addDisabledSong, removeDisabledSong } = useDisabledSongs(); const { showSuccess, showError } = useToast(); @@ -40,6 +41,7 @@ const SongInfo: React.FC = ({ isOpen, onClose, song }) => { const isInFavorites = (Object.values(favorites) as Song[]).some(favSong => favSong.path === song.path); const isDisabled = isSongDisabled(song); + const isInQueue = (Object.values(queue) as QueueItem[]).some(queueItem => queueItem.song && queueItem.song.path === song.path); const artistSongs = (Object.values(allSongs) as Song[]).filter(s => s.artist.toLowerCase() === song.artist.toLowerCase() && s.path !== song.path @@ -110,16 +112,18 @@ const SongInfo: React.FC = ({ isOpen, onClose, song }) => { {/* Action Buttons */}
{/* Queue Song Button */} - - - Queue Song - + {!isInQueue && ( + + + Queue Song + + )} {/* Artist Songs Button */} = ({ const isInQueue = (Object.values(queue) as QueueItem[]).some(item => item.song.path === song.path); const isInFavorites = (Object.values(favorites) as Song[]).some(favSong => favSong.path === song.path); + // Debug logging for favorites + console.log('SongItem render:', { + songTitle: song.title, + songPath: song.path, + favoritesCount: Object.keys(favorites).length, + isInFavorites, + favorites: (Object.values(favorites) as Song[]).map(f => f.path) + }); + // Default values based on context if not explicitly provided const shouldShowPath = showPath !== undefined ? showPath : context !== 'queue'; const shouldShowCount = showCount !== undefined ? showCount : context === 'queue'; diff --git a/src/features/Favorites/Favorites.tsx b/src/features/Favorites/Favorites.tsx index 543a85f..81ede57 100644 --- a/src/features/Favorites/Favorites.tsx +++ b/src/features/Favorites/Favorites.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { InfiniteScrollList, SongItem } from '../../components/common'; +import React, { useState } from 'react'; +import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common'; import { useFavorites } from '../../hooks'; import { useAppSelector } from '../../redux'; import { selectFavorites } from '../../redux'; @@ -11,10 +11,12 @@ const Favorites: React.FC = () => { favoritesItems, hasMore, loadMore, - handleAddToQueue, handleToggleFavorite, } = useFavorites(); + const [selectedSong, setSelectedSong] = useState(null); + const [isSongInfoOpen, setIsSongInfoOpen] = useState(false); + const favorites = useAppSelector(selectFavorites); const favoritesCount = Object.keys(favorites).length; @@ -22,6 +24,16 @@ const Favorites: React.FC = () => { debugLog('Favorites component - favorites count:', favoritesCount); debugLog('Favorites component - favorites items:', favoritesItems); + const handleSongInfo = (song: Song) => { + setSelectedSong(song); + setIsSongInfoOpen(true); + }; + + const handleCloseSongInfo = () => { + setIsSongInfoOpen(false); + setSelectedSong(null); + }; + return ( <> @@ -33,8 +45,10 @@ const Favorites: React.FC = () => { handleAddToQueue(song)} - onToggleFavorite={() => handleToggleFavorite(song)} + showInfoButton={true} + showAddButton={false} + onSelectSinger={() => handleSongInfo(song)} + onDelete={() => handleToggleFavorite(song)} /> )} emptyTitle="No favorites yet" @@ -42,6 +56,15 @@ const Favorites: React.FC = () => { loadingTitle="Loading favorites..." loadingMessage="Please wait while favorites data is being loaded" /> + + {/* Song Info Modal */} + {selectedSong && ( + + )} ); }; diff --git a/src/hooks/useDisabledSongs.ts b/src/hooks/useDisabledSongs.ts index d5499f0..9710add 100644 --- a/src/hooks/useDisabledSongs.ts +++ b/src/hooks/useDisabledSongs.ts @@ -2,7 +2,6 @@ import { useState, useEffect, useCallback } from 'react'; import { disabledSongsService } from '../firebase/services'; import { useAppSelector } from '../redux'; import { selectControllerName } from '../redux'; -import { debugLog } from '../utils/logger'; import { useToast } from './useToast'; import type { Song, DisabledSong } from '../types'; @@ -39,8 +38,21 @@ export const useDisabledSongs = () => { const unsubscribe = disabledSongsService.subscribeToDisabledSongs( controllerName, (songs) => { - setDisabledSongs(songs); - setDisabledSongPaths(new Set(Object.keys(songs).map(key => decodeURIComponent(key)))); + // Only update if the data has actually changed + setDisabledSongs(prevSongs => { + if (JSON.stringify(prevSongs) !== JSON.stringify(songs)) { + return songs; + } + return prevSongs; + }); + + setDisabledSongPaths(prevPaths => { + const newPaths = new Set(Object.values(songs).map((song: DisabledSong) => song.path)); + if (JSON.stringify(Array.from(prevPaths)) !== JSON.stringify(Array.from(newPaths))) { + return newPaths; + } + return prevPaths; + }); } ); @@ -49,7 +61,8 @@ export const useDisabledSongs = () => { // Check if a song is disabled const isSongDisabled = useCallback((song: Song): boolean => { - return disabledSongPaths.has(song.path); + const isDisabled = disabledSongPaths.has(song.path); + return isDisabled; }, [disabledSongPaths]); // Add a song to disabled list @@ -67,7 +80,6 @@ export const useDisabledSongs = () => { } try { - debugLog('Adding disabled song:', { controllerName, song }); await disabledSongsService.addDisabledSong(controllerName, song); showSuccess('Song marked as disabled'); } catch (error) { diff --git a/src/hooks/useSongOperations.ts b/src/hooks/useSongOperations.ts index c12d894..0c4ac43 100644 --- a/src/hooks/useSongOperations.ts +++ b/src/hooks/useSongOperations.ts @@ -3,6 +3,8 @@ import { useAppSelector } from '../redux'; import { selectControllerName, selectCurrentSinger, selectQueueObject } from '../redux'; import { queueService, favoritesService } from '../firebase/services'; import type { Song, QueueItem } from '../types'; +import { ref, get } from 'firebase/database'; +import { database } from '../firebase/config'; export const useSongOperations = () => { const controllerName = useAppSelector(selectControllerName); @@ -57,15 +59,34 @@ export const useSongOperations = () => { } try { - if (song.favorite) { + console.log('toggleFavorite called for song:', song.title, song.path); + + // Check if the song is currently in favorites by looking it up + const favoritesRef = ref(database, `controllers/${controllerName}/favorites`); + const snapshot = await get(favoritesRef); + const favorites = snapshot.exists() ? snapshot.val() : {}; + + console.log('Current favorites:', favorites); + + // Find if this song is already in favorites by matching the path + const existingFavoriteKey = Object.keys(favorites).find(key => { + const favoriteSong = favorites[key]; + return favoriteSong && favoriteSong.path === song.path; + }); + + console.log('Existing favorite key:', existingFavoriteKey); + + if (existingFavoriteKey) { // Remove from favorites - if (song.key) { - await favoritesService.removeFromFavorites(controllerName, song.key); - } + console.log('Removing from favorites'); + await favoritesService.removeFromFavorites(controllerName, existingFavoriteKey); } else { // Add to favorites + console.log('Adding to favorites'); await favoritesService.addToFavorites(controllerName, song); } + + console.log('toggleFavorite completed'); } catch (error) { console.error('Failed to toggle favorite:', error); throw error;