diff --git a/src/App.tsx b/src/App.tsx
index 8ae4a8b..01afe18 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,6 +5,7 @@ import TopPlayed from './features/TopPlayed/Top100';
import { FirebaseProvider } from './firebase/FirebaseProvider';
import { ErrorBoundary } from './components/common';
import { AuthInitializer } from './components/Auth';
+import { SongInfoProvider } from './components/common/SongInfoProvider';
function App() {
return (
@@ -12,22 +13,24 @@ function App() {
-
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
-
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
diff --git a/src/components/common/SongInfoProvider.tsx b/src/components/common/SongInfoProvider.tsx
new file mode 100644
index 0000000..8980faf
--- /dev/null
+++ b/src/components/common/SongInfoProvider.tsx
@@ -0,0 +1,48 @@
+import React, { useState, useCallback } from 'react';
+import type { ReactNode } from 'react';
+import SongInfo from './SongInfo';
+import { SongInfoContext, type SongInfoContextType } from '../../contexts/SongInfoContext';
+import type { Song } from '../../types';
+
+interface SongInfoProviderProps {
+ children: ReactNode;
+}
+
+export const SongInfoProvider: React.FC = ({ children }) => {
+ const [selectedSong, setSelectedSong] = useState(null);
+ const [isOpen, setIsOpen] = useState(false);
+
+ const openSongInfo = useCallback((song: Song) => {
+ setSelectedSong(song);
+ setIsOpen(true);
+ }, []);
+
+ const closeSongInfo = useCallback(() => {
+ setIsOpen(false);
+ setSelectedSong(null);
+ }, []);
+
+ const contextValue: SongInfoContextType = {
+ openSongInfo,
+ closeSongInfo,
+ isOpen,
+ selectedSong,
+ };
+
+ return (
+
+ {children}
+
+ {/* Song Info Modal */}
+ {selectedSong && (
+
+ )}
+
+ );
+};
+
+
\ No newline at end of file
diff --git a/src/components/common/SongItem.tsx b/src/components/common/SongItem.tsx
index 9ad7494..c50dbff 100644
--- a/src/components/common/SongItem.tsx
+++ b/src/components/common/SongItem.tsx
@@ -3,6 +3,9 @@ import { IonItem, IonLabel } from '@ionic/react';
import ActionButton from './ActionButton';
import { useAppSelector } from '../../redux';
import { selectQueue, selectFavorites } from '../../redux';
+import { useSongOperations } from '../../hooks/useSongOperations';
+import { useToast } from '../../hooks/useToast';
+import { useSongInfo } from '../../hooks/useSongInfoContext';
import { debugLog } from '../../utils/logger';
import type { SongItemProps, QueueItem, Song } from '../../types';
import { ActionButtonVariant, ActionButtonSize, ActionButtonIconSlot } from '../../types';
@@ -92,11 +95,11 @@ export const SongActionButtons: React.FC<{
showRemoveButton?: boolean;
showDeleteButton?: boolean;
showFavoriteButton?: boolean;
+ onDeleteItem?: () => void;
onAddToQueue?: () => void;
onRemoveFromQueue?: () => void;
onToggleFavorite?: () => void;
- onDeleteItem?: () => void;
- onSelectSinger?: () => void;
+ onShowSongInfo?: () => void;
}> = ({
isAdmin,
isInQueue,
@@ -106,20 +109,20 @@ export const SongActionButtons: React.FC<{
showRemoveButton = false,
showDeleteButton = false,
showFavoriteButton = false,
+ onDeleteItem,
onAddToQueue,
onRemoveFromQueue,
onToggleFavorite,
- onDeleteItem,
- onSelectSinger
+ onShowSongInfo
}) => {
const buttons = [];
// Info button
- if (showInfoButton && onSelectSinger) {
+ if (showInfoButton && onShowSongInfo) {
buttons.push(
{})}
+ onClick={onAddToQueue}
variant={ActionButtonVariant.PRIMARY}
size={ActionButtonSize.SMALL}
icon={Icons.ADD}
@@ -171,11 +174,11 @@ export const SongActionButtons: React.FC<{
}
// Toggle Favorite button
- if (showFavoriteButton) {
+ if (showFavoriteButton && onToggleFavorite) {
buttons.push(
{})}
+ onClick={onToggleFavorite}
variant={isInFavorites ? ActionButtonVariant.DANGER : ActionButtonVariant.SECONDARY}
size={ActionButtonSize.SMALL}
icon={isInFavorites ? Icons.HEART : Icons.HEART_OUTLINE}
@@ -195,11 +198,7 @@ export const SongActionButtons: React.FC<{
const SongItem: React.FC = ({
song,
context,
- onAddToQueue,
- onRemoveFromQueue,
- onToggleFavorite,
onDeleteItem,
- onSelectSinger,
isAdmin = false,
className = '',
showActions = true,
@@ -215,10 +214,20 @@ const SongItem: React.FC = ({
const queue = useAppSelector(selectQueue);
const favorites = useAppSelector(selectFavorites);
+ // Get song operations and hooks
+ const { addToQueue, removeFromQueue, toggleFavorite } = useSongOperations();
+ const { showSuccess, showError } = useToast();
+ const { openSongInfo } = useSongInfo();
+
// Check if song is in queue or favorites based on path
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);
+ // Find queue item key for removal (only needed for queue context)
+ const queueItemKey = context === 'queue'
+ ? (Object.entries(queue) as [string, QueueItem][]).find(([, item]) => item.song.path === song.path)?.[0]
+ : null;
+
// Debug logging for favorites
debugLog('SongItem render:', {
songTitle: song.title,
@@ -239,6 +248,40 @@ const SongItem: React.FC = ({
const shouldShowDeleteButton = showDeleteButton !== undefined ? showDeleteButton : context === 'history' && isAdmin;
const shouldShowFavoriteButton = showFavoriteButton !== undefined ? showFavoriteButton : false; // Disabled for all contexts
+ // Handle song operations internally
+ const handleAddToQueue = async () => {
+ try {
+ await addToQueue(song);
+ showSuccess('Song added to queue');
+ } catch {
+ showError('Failed to add song to queue');
+ }
+ };
+
+ const handleRemoveFromQueue = async () => {
+ if (!queueItemKey) return;
+
+ try {
+ await removeFromQueue(queueItemKey);
+ showSuccess('Song removed from queue');
+ } catch {
+ showError('Failed to remove song from queue');
+ }
+ };
+
+ const handleToggleFavorite = async () => {
+ try {
+ await toggleFavorite(song);
+ showSuccess(isInFavorites ? 'Removed from favorites' : 'Added to favorites');
+ } catch {
+ showError('Failed to update favorites');
+ }
+ };
+
+ const handleSelectSinger = () => {
+ openSongInfo(song);
+ };
+
return (
= ({
showRemoveButton={shouldShowRemoveButton}
showDeleteButton={shouldShowDeleteButton}
showFavoriteButton={shouldShowFavoriteButton}
- onAddToQueue={onAddToQueue}
- onRemoveFromQueue={onRemoveFromQueue}
- onToggleFavorite={onToggleFavorite}
onDeleteItem={onDeleteItem}
- onSelectSinger={onSelectSinger}
+ onAddToQueue={context === 'queue' ? handleRemoveFromQueue : handleAddToQueue}
+ onRemoveFromQueue={context === 'queue' ? handleRemoveFromQueue : onDeleteItem}
+ onToggleFavorite={context === 'favorites' ? onDeleteItem : handleToggleFavorite}
+ onShowSongInfo={handleSelectSinger}
/>
)}
diff --git a/src/contexts/SongInfoContext.tsx b/src/contexts/SongInfoContext.tsx
new file mode 100644
index 0000000..d23785d
--- /dev/null
+++ b/src/contexts/SongInfoContext.tsx
@@ -0,0 +1,11 @@
+import { createContext } from 'react';
+import type { Song } from '../types';
+
+export interface SongInfoContextType {
+ openSongInfo: (song: Song) => void;
+ closeSongInfo: () => void;
+ isOpen: boolean;
+ selectedSong: Song | null;
+}
+
+export const SongInfoContext = createContext(null);
\ No newline at end of file
diff --git a/src/features/Artists/Artists.tsx b/src/features/Artists/Artists.tsx
index a8f8beb..d4f377b 100644
--- a/src/features/Artists/Artists.tsx
+++ b/src/features/Artists/Artists.tsx
@@ -1,14 +1,14 @@
import React, { useState } from 'react';
import { IonSearchbar, IonModal, IonHeader, IonToolbar, IonTitle, IonContent, IonItem } from '@ionic/react';
import { list } from 'ionicons/icons';
-import { InfiniteScrollList, SongItem, ListItem, NumberDisplay, SongInfo, ActionButton } from '../../components/common';
+import { InfiniteScrollList, SongItem, ListItem, NumberDisplay, ActionButton } from '../../components/common';
import { ActionButtonVariant, ActionButtonSize, ActionButtonIconSlot } from '../../types';
import { Icons } from '../../constants';
import { useArtists } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectSongs } from '../../redux';
import { debugLog } from '../../utils/logger';
-import type { Song } from '../../types';
+
const Artists: React.FC = () => {
const {
@@ -19,15 +19,11 @@ const Artists: React.FC = () => {
handleSearchChange,
getSongsByArtist,
getSongCountByArtist,
- handleAddToQueue,
} = useArtists();
const songs = useAppSelector(selectSongs);
const songsCount = Object.keys(songs).length;
const [selectedArtist, setSelectedArtist] = useState(null);
- const [selectedSong, setSelectedSong] = useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
-
// Debug logging
debugLog('Artists component - artists count:', artists.length);
debugLog('Artists component - selected artist:', selectedArtist);
@@ -42,16 +38,6 @@ const Artists: React.FC = () => {
setSelectedArtist(null);
};
- const handleSongInfo = (song: Song) => {
- setSelectedSong(song);
- setIsSongInfoOpen(true);
- };
-
- const handleCloseSongInfo = () => {
- setIsSongInfoOpen(false);
- setSelectedSong(null);
- };
-
const selectedArtistSongs = selectedArtist ? getSongsByArtist(selectedArtist) : [];
// Render artist item for InfiniteScrollList
@@ -156,8 +142,6 @@ const Artists: React.FC = () => {
handleAddToQueue(song)}
- onSelectSinger={() => handleSongInfo(song)}
showAddButton={true}
showInfoButton={true}
showFavoriteButton={false}
@@ -173,14 +157,6 @@ const Artists: React.FC = () => {
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
diff --git a/src/features/Favorites/Favorites.tsx b/src/features/Favorites/Favorites.tsx
index f1909c6..22bd2da 100644
--- a/src/features/Favorites/Favorites.tsx
+++ b/src/features/Favorites/Favorites.tsx
@@ -1,5 +1,5 @@
-import React, { useState } from 'react';
-import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
+import React from 'react';
+import { InfiniteScrollList, SongItem } from '../../components/common';
import { useFavorites } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectFavorites } from '../../redux';
@@ -14,9 +14,6 @@ const Favorites: React.FC = () => {
handleToggleFavorite,
} = useFavorites();
- const [selectedSong, setSelectedSong] = useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
-
const favorites = useAppSelector(selectFavorites);
const favoritesCount = Object.keys(favorites).length;
@@ -24,16 +21,6 @@ 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 (
<>
@@ -48,7 +35,6 @@ const Favorites: React.FC = () => {
showInfoButton={true}
showAddButton={false}
showDeleteButton={true}
- onSelectSinger={() => handleSongInfo(song)}
onDeleteItem={() => handleToggleFavorite(song)}
/>
)}
@@ -58,14 +44,6 @@ const Favorites: React.FC = () => {
loadingMessage="Please wait while favorites data is being loaded"
/>
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
};
diff --git a/src/features/History/History.tsx b/src/features/History/History.tsx
index abcc322..f52a091 100644
--- a/src/features/History/History.tsx
+++ b/src/features/History/History.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { IonChip, IonIcon } from '@ionic/react';
import { time } from 'ionicons/icons';
-import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
+import { InfiniteScrollList, SongItem } from '../../components/common';
import { useHistory } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectHistory, selectIsAdmin } from '../../redux';
@@ -14,30 +14,16 @@ const History: React.FC = () => {
historyItems,
hasMore,
loadMore,
- handleAddToQueue,
handleDeleteFromHistory,
} = useHistory();
const history = useAppSelector(selectHistory);
const isAdmin = useAppSelector(selectIsAdmin);
const historyCount = Object.keys(history).length;
- const [selectedSong, setSelectedSong] = React.useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false);
-
// Debug logging
debugLog('History component - history count:', historyCount);
debugLog('History component - history items:', historyItems);
- const handleSongInfo = (song: Song) => {
- setSelectedSong(song);
- setIsSongInfoOpen(true);
- };
-
- const handleCloseSongInfo = () => {
- setIsSongInfoOpen(false);
- setSelectedSong(null);
- };
-
// Render extra content for history items (play date)
const renderExtraContent = (item: Song) => {
if (item.date) {
@@ -64,8 +50,6 @@ const History: React.FC = () => {
handleAddToQueue(song)}
- onSelectSinger={() => handleSongInfo(song)}
onDeleteItem={() => handleDeleteFromHistory(song)}
isAdmin={isAdmin}
showAddButton={true}
@@ -83,14 +67,6 @@ const History: React.FC = () => {
loadingMessage="Please wait while history data is being loaded"
/>
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
};
diff --git a/src/features/NewSongs/NewSongs.tsx b/src/features/NewSongs/NewSongs.tsx
index f6799ea..59a7332 100644
--- a/src/features/NewSongs/NewSongs.tsx
+++ b/src/features/NewSongs/NewSongs.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
+import { InfiniteScrollList, SongItem } from '../../components/common';
import { useNewSongs } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectNewSongsArray } from '../../redux';
@@ -11,28 +11,15 @@ const NewSongs: React.FC = () => {
newSongsItems,
hasMore,
loadMore,
- handleAddToQueue,
} = useNewSongs();
const newSongsArray = useAppSelector(selectNewSongsArray);
const newSongsCount = newSongsArray.length;
- const [selectedSong, setSelectedSong] = React.useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false);
// Debug logging
debugLog('NewSongs component - new songs count:', newSongsCount);
debugLog('NewSongs component - new songs items:', newSongsItems);
- const handleSongInfo = (song: Song) => {
- setSelectedSong(song);
- setIsSongInfoOpen(true);
- };
-
- const handleCloseSongInfo = () => {
- setIsSongInfoOpen(false);
- setSelectedSong(null);
- };
-
return (
<>
@@ -44,8 +31,6 @@ const NewSongs: React.FC = () => {
handleAddToQueue(song)}
- onSelectSinger={() => handleSongInfo(song)}
showAddButton={true}
showInfoButton={true}
showFavoriteButton={false}
@@ -57,14 +42,6 @@ const NewSongs: React.FC = () => {
loadingMessage="Please wait while new songs data is being loaded"
/>
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
};
diff --git a/src/features/Search/Search.tsx b/src/features/Search/Search.tsx
index 710af78..654080d 100644
--- a/src/features/Search/Search.tsx
+++ b/src/features/Search/Search.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { IonSearchbar } from '@ionic/react';
-import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
-import { useSearch, useSongInfo } from '../../hooks';
+import { InfiniteScrollList, SongItem } from '../../components/common';
+import { useSearch } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectIsAdmin, selectSongs } from '../../redux';
import { debugLog } from '../../utils/logger';
@@ -12,12 +12,9 @@ const Search: React.FC = () => {
searchTerm,
searchResults,
handleSearchChange,
- handleAddToQueue,
loadMore,
} = useSearch();
- const { isOpen, selectedSong, openSongInfo, closeSongInfo } = useSongInfo();
-
const isAdmin = useAppSelector(selectIsAdmin);
const songs = useAppSelector(selectSongs);
const songsCount = Object.keys(songs).length;
@@ -63,8 +60,6 @@ const Search: React.FC = () => {
handleAddToQueue(song)}
- onSelectSinger={() => openSongInfo(song)}
isAdmin={isAdmin}
showAddButton={true}
showInfoButton={true}
@@ -86,14 +81,6 @@ const Search: React.FC = () => {
)}
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
};
diff --git a/src/features/SongLists/SongLists.tsx b/src/features/SongLists/SongLists.tsx
index f859d82..f1a5547 100644
--- a/src/features/SongLists/SongLists.tsx
+++ b/src/features/SongLists/SongLists.tsx
@@ -1,7 +1,7 @@
import React, { useState, useMemo, useCallback } from 'react';
import { IonItem, IonModal, IonHeader, IonToolbar, IonTitle, IonChip, IonContent, IonList, IonAccordionGroup, IonAccordion } from '@ionic/react';
import { list } from 'ionicons/icons';
-import { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay, SongInfo, ActionButton } from '../../components/common';
+import { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay, ActionButton } from '../../components/common';
import { ActionButtonVariant, ActionButtonSize, ActionButtonIconSlot } from '../../types';
import { Icons } from '../../constants';
import { useSongLists } from '../../hooks';
@@ -17,15 +17,13 @@ const SongLists: React.FC = () => {
hasMore,
loadMore,
checkSongAvailability,
- handleAddToQueue,
} = useSongLists();
const songListData = useAppSelector(selectSongList);
const songListCount = Object.keys(songListData).length;
const [selectedSongList, setSelectedSongList] = useState(null);
const [expandedSongKey, setExpandedSongKey] = useState(null);
- const [selectedSong, setSelectedSong] = useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
+
@@ -43,15 +41,7 @@ const SongLists: React.FC = () => {
setExpandedSongKey(expandedSongKey === songKey ? null : songKey);
}, [expandedSongKey]);
- const handleSongInfo = useCallback((song: Song) => {
- setSelectedSong(song);
- setIsSongInfoOpen(true);
- }, []);
- const handleCloseSongInfo = useCallback(() => {
- setIsSongInfoOpen(false);
- setSelectedSong(null);
- }, []);
const finalSelectedList = selectedSongList
? allSongLists.find(list => list.key === selectedSongList)
@@ -152,8 +142,6 @@ const SongLists: React.FC = () => {
key={song.key || `${song.title}-${song.artist}-${sidx}`}
song={song}
context="search"
- onAddToQueue={() => handleAddToQueue(song)}
- onSelectSinger={() => handleSongInfo(song)}
showAddButton={true}
showInfoButton={true}
showFavoriteButton={false}
@@ -195,14 +183,6 @@ const SongLists: React.FC = () => {
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
diff --git a/src/features/TopPlayed/Top100.tsx b/src/features/TopPlayed/Top100.tsx
index 8fed00b..526e196 100644
--- a/src/features/TopPlayed/Top100.tsx
+++ b/src/features/TopPlayed/Top100.tsx
@@ -4,14 +4,13 @@ import { list } from 'ionicons/icons';
import { useTopPlayed } from '../../hooks';
import { useAppSelector } from '../../redux';
import { selectTopPlayed, selectSongsArray } from '../../redux';
-import { InfiniteScrollList, SongItem, ListItem, SongInfo, ActionButton } from '../../components/common';
+import { InfiniteScrollList, SongItem, ListItem, ActionButton } from '../../components/common';
import { filterSongs } from '../../utils/dataProcessing';
import { debugLog } from '../../utils/logger';
-import { useSongOperations } from '../../hooks';
-import { useToast } from '../../hooks';
+
import { ActionButtonVariant, ActionButtonSize, ActionButtonIconSlot } from '../../types';
import { Icons } from '../../constants';
-import type { TopPlayed, Song } from '../../types';
+import type { TopPlayed } from '../../types';
const Top100: React.FC = () => {
debugLog('Top100 component - RENDERING START');
@@ -26,11 +25,8 @@ const Top100: React.FC = () => {
const topPlayed = useAppSelector(selectTopPlayed);
const topPlayedCount = Object.keys(topPlayed).length;
const allSongs = useAppSelector(selectSongsArray);
- const { addToQueue } = useSongOperations();
- const { showSuccess, showError } = useToast();
const [selectedTopPlayed, setSelectedTopPlayed] = useState(null);
- const [selectedSong, setSelectedSong] = useState(null);
- const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
+
debugLog('Top100 component - Redux data:', { topPlayedCount, topPlayedItems: topPlayedItems.length });
@@ -42,15 +38,7 @@ const Top100: React.FC = () => {
setSelectedTopPlayed(null);
}, []);
- const handleSongInfo = useCallback((song: Song) => {
- setSelectedSong(song);
- setIsSongInfoOpen(true);
- }, []);
- const handleCloseSongInfo = useCallback(() => {
- setIsSongInfoOpen(false);
- setSelectedSong(null);
- }, []);
// Find songs that match the selected top played item
const selectedSongs = useMemo(() => {
@@ -75,15 +63,6 @@ const Top100: React.FC = () => {
return filteredSongs;
}, [selectedTopPlayed, allSongs]);
- const handleAddToQueue = useCallback(async (song: Song) => {
- try {
- await addToQueue(song);
- showSuccess('Song added to queue');
- } catch {
- showError('Failed to add song to queue');
- }
- }, [addToQueue, showSuccess, showError]);
-
// Use real Firebase data from the hook
@@ -161,8 +140,6 @@ const Top100: React.FC = () => {
key={song.key || `${song.title}-${song.artist}`}
song={song}
context="search"
- onAddToQueue={() => handleAddToQueue(song)}
- onSelectSinger={() => handleSongInfo(song)}
showAddButton={true}
showInfoButton={true}
showFavoriteButton={false}
@@ -172,14 +149,6 @@ const Top100: React.FC = () => {
- {/* Song Info Modal */}
- {selectedSong && (
-
- )}
>
);
};
diff --git a/src/hooks/useSongInfoContext.ts b/src/hooks/useSongInfoContext.ts
new file mode 100644
index 0000000..c20ccc9
--- /dev/null
+++ b/src/hooks/useSongInfoContext.ts
@@ -0,0 +1,10 @@
+import { useContext } from 'react';
+import { SongInfoContext, type SongInfoContextType } from '../contexts/SongInfoContext';
+
+export const useSongInfo = (): SongInfoContextType => {
+ const context = useContext(SongInfoContext);
+ if (context === null) {
+ throw new Error('useSongInfo must be used within a SongInfoProvider');
+ }
+ return context;
+};
\ No newline at end of file
diff --git a/src/types/index.ts b/src/types/index.ts
index c06938d..de9d17b 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -165,11 +165,7 @@ export interface ActionButtonProps {
export interface SongItemProps {
song: Song;
context: 'search' | 'queue' | 'favorites' | 'history' | 'songlists' | 'top100' | 'new';
- onAddToQueue?: () => void;
- onRemoveFromQueue?: () => void;
- onToggleFavorite?: () => void;
onDeleteItem?: () => void;
- onSelectSinger?: () => void;
isAdmin?: boolean;
className?: string;
showActions?: boolean;