Signed-off-by: mbrucedogs <mbrucedogs@gmail.com>

This commit is contained in:
mbrucedogs 2025-07-20 14:16:24 -05:00
parent e556b4949d
commit 8626251f33
5 changed files with 116 additions and 9 deletions

View File

@ -1,11 +1,12 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { IonSearchbar, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonContent, IonItem } from '@ionic/react'; import { IonSearchbar, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonContent, IonItem } from '@ionic/react';
import { close, list } from 'ionicons/icons'; import { close, list } from 'ionicons/icons';
import { InfiniteScrollList, SongItem, ListItem, NumberDisplay } from '../../components/common'; import { InfiniteScrollList, SongItem, ListItem, NumberDisplay, SongInfo } from '../../components/common';
import { useArtists } from '../../hooks'; import { useArtists } from '../../hooks';
import { useAppSelector } from '../../redux'; import { useAppSelector } from '../../redux';
import { selectSongs } from '../../redux'; import { selectSongs } from '../../redux';
import { debugLog } from '../../utils/logger'; import { debugLog } from '../../utils/logger';
import type { Song } from '../../types';
const Artists: React.FC = () => { const Artists: React.FC = () => {
const { const {
@ -22,6 +23,8 @@ const Artists: React.FC = () => {
const songs = useAppSelector(selectSongs); const songs = useAppSelector(selectSongs);
const songsCount = Object.keys(songs).length; const songsCount = Object.keys(songs).length;
const [selectedArtist, setSelectedArtist] = useState<string | null>(null); const [selectedArtist, setSelectedArtist] = useState<string | null>(null);
const [selectedSong, setSelectedSong] = useState<Song | null>(null);
const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
// Debug logging // Debug logging
debugLog('Artists component - artists count:', artists.length); debugLog('Artists component - artists count:', artists.length);
@ -37,6 +40,16 @@ const Artists: React.FC = () => {
setSelectedArtist(null); setSelectedArtist(null);
}; };
const handleSongInfo = (song: Song) => {
setSelectedSong(song);
setIsSongInfoOpen(true);
};
const handleCloseSongInfo = () => {
setIsSongInfoOpen(false);
setSelectedSong(null);
};
const selectedArtistSongs = selectedArtist ? getSongsByArtist(selectedArtist) : []; const selectedArtistSongs = selectedArtist ? getSongsByArtist(selectedArtist) : [];
// Render artist item for InfiniteScrollList // Render artist item for InfiniteScrollList
@ -135,7 +148,7 @@ const Artists: React.FC = () => {
song={song} song={song}
context="search" context="search"
onAddToQueue={() => handleAddToQueue(song)} onAddToQueue={() => handleAddToQueue(song)}
onSelectSinger={() => {}} // Info button functionality onSelectSinger={() => handleSongInfo(song)}
showAddButton={true} showAddButton={true}
showInfoButton={true} showInfoButton={true}
showFavoriteButton={false} showFavoriteButton={false}
@ -150,6 +163,15 @@ const Artists: React.FC = () => {
</div> </div>
</IonContent> </IonContent>
</IonModal> </IonModal>
{/* Song Info Modal */}
{selectedSong && (
<SongInfo
isOpen={isSongInfoOpen}
onClose={handleCloseSongInfo}
song={selectedSong}
/>
)}
</div> </div>
</> </>
); );

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { IonChip, IonIcon } from '@ionic/react'; import { IonChip, IonIcon } from '@ionic/react';
import { time } from 'ionicons/icons'; import { time } from 'ionicons/icons';
import { InfiniteScrollList, SongItem } from '../../components/common'; import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
import { useHistory } from '../../hooks'; import { useHistory } from '../../hooks';
import { useAppSelector } from '../../redux'; import { useAppSelector } from '../../redux';
import { selectHistory, selectIsAdmin } from '../../redux'; import { selectHistory, selectIsAdmin } from '../../redux';
@ -21,11 +21,23 @@ const History: React.FC = () => {
const history = useAppSelector(selectHistory); const history = useAppSelector(selectHistory);
const isAdmin = useAppSelector(selectIsAdmin); const isAdmin = useAppSelector(selectIsAdmin);
const historyCount = Object.keys(history).length; const historyCount = Object.keys(history).length;
const [selectedSong, setSelectedSong] = React.useState<Song | null>(null);
const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false);
// Debug logging // Debug logging
debugLog('History component - history count:', historyCount); debugLog('History component - history count:', historyCount);
debugLog('History component - history items:', historyItems); 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) // Render extra content for history items (play date)
const renderExtraContent = (item: Song) => { const renderExtraContent = (item: Song) => {
if (item.date) { if (item.date) {
@ -53,7 +65,7 @@ const History: React.FC = () => {
song={song} song={song}
context="history" context="history"
onAddToQueue={() => handleAddToQueue(song)} onAddToQueue={() => handleAddToQueue(song)}
onSelectSinger={() => {}} // Info button functionality onSelectSinger={() => handleSongInfo(song)}
onDeleteItem={() => handleDeleteFromHistory(song)} onDeleteItem={() => handleDeleteFromHistory(song)}
isAdmin={isAdmin} isAdmin={isAdmin}
showAddButton={true} showAddButton={true}
@ -70,6 +82,15 @@ const History: React.FC = () => {
loadingTitle="Loading history..." loadingTitle="Loading history..."
loadingMessage="Please wait while history data is being loaded" loadingMessage="Please wait while history data is being loaded"
/> />
{/* Song Info Modal */}
{selectedSong && (
<SongInfo
isOpen={isSongInfoOpen}
onClose={handleCloseSongInfo}
song={selectedSong}
/>
)}
</> </>
); );
}; };

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { InfiniteScrollList, SongItem } from '../../components/common'; import { InfiniteScrollList, SongItem, SongInfo } from '../../components/common';
import { useNewSongs } from '../../hooks'; import { useNewSongs } from '../../hooks';
import { useAppSelector } from '../../redux'; import { useAppSelector } from '../../redux';
import { selectNewSongsArray } from '../../redux'; import { selectNewSongsArray } from '../../redux';
@ -16,11 +16,23 @@ const NewSongs: React.FC = () => {
const newSongsArray = useAppSelector(selectNewSongsArray); const newSongsArray = useAppSelector(selectNewSongsArray);
const newSongsCount = newSongsArray.length; const newSongsCount = newSongsArray.length;
const [selectedSong, setSelectedSong] = React.useState<Song | null>(null);
const [isSongInfoOpen, setIsSongInfoOpen] = React.useState(false);
// Debug logging // Debug logging
debugLog('NewSongs component - new songs count:', newSongsCount); debugLog('NewSongs component - new songs count:', newSongsCount);
debugLog('NewSongs component - new songs items:', newSongsItems); debugLog('NewSongs component - new songs items:', newSongsItems);
const handleSongInfo = (song: Song) => {
setSelectedSong(song);
setIsSongInfoOpen(true);
};
const handleCloseSongInfo = () => {
setIsSongInfoOpen(false);
setSelectedSong(null);
};
return ( return (
<> <>
<InfiniteScrollList<Song> <InfiniteScrollList<Song>
@ -33,6 +45,7 @@ const NewSongs: React.FC = () => {
song={song} song={song}
context="search" context="search"
onAddToQueue={() => handleAddToQueue(song)} onAddToQueue={() => handleAddToQueue(song)}
onSelectSinger={() => handleSongInfo(song)}
showAddButton={true} showAddButton={true}
showInfoButton={true} showInfoButton={true}
showFavoriteButton={false} showFavoriteButton={false}
@ -43,6 +56,15 @@ const NewSongs: React.FC = () => {
loadingTitle="Loading new songs..." loadingTitle="Loading new songs..."
loadingMessage="Please wait while new songs data is being loaded" loadingMessage="Please wait while new songs data is being loaded"
/> />
{/* Song Info Modal */}
{selectedSong && (
<SongInfo
isOpen={isSongInfoOpen}
onClose={handleCloseSongInfo}
song={selectedSong}
/>
)}
</> </>
); );
}; };

View File

@ -1,7 +1,7 @@
import React, { useState, useMemo, useCallback } from 'react'; import React, { useState, useMemo, useCallback } from 'react';
import { IonItem, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonChip, IonContent, IonList, IonAccordionGroup, IonAccordion } from '@ionic/react'; import { IonItem, IonModal, IonHeader, IonToolbar, IonTitle, IonButton, IonIcon, IonChip, IonContent, IonList, IonAccordionGroup, IonAccordion } from '@ionic/react';
import { close, list } from 'ionicons/icons'; import { close, list } from 'ionicons/icons';
import { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay } from '../../components/common'; import { InfiniteScrollList, SongItem, ListItem, TwoLineDisplay, NumberDisplay, SongInfo } from '../../components/common';
import { useSongLists } from '../../hooks'; import { useSongLists } from '../../hooks';
import { useAppSelector } from '../../redux'; import { useAppSelector } from '../../redux';
import { selectSongList } from '../../redux'; import { selectSongList } from '../../redux';
@ -22,6 +22,8 @@ const SongLists: React.FC = () => {
const songListCount = Object.keys(songListData).length; const songListCount = Object.keys(songListData).length;
const [selectedSongList, setSelectedSongList] = useState<string | null>(null); const [selectedSongList, setSelectedSongList] = useState<string | null>(null);
const [expandedSongKey, setExpandedSongKey] = useState<string | null>(null); const [expandedSongKey, setExpandedSongKey] = useState<string | null>(null);
const [selectedSong, setSelectedSong] = useState<Song | null>(null);
const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
@ -39,6 +41,16 @@ const SongLists: React.FC = () => {
setExpandedSongKey(expandedSongKey === songKey ? null : songKey); setExpandedSongKey(expandedSongKey === songKey ? null : songKey);
}, [expandedSongKey]); }, [expandedSongKey]);
const handleSongInfo = useCallback((song: Song) => {
setSelectedSong(song);
setIsSongInfoOpen(true);
}, []);
const handleCloseSongInfo = useCallback(() => {
setIsSongInfoOpen(false);
setSelectedSong(null);
}, []);
const finalSelectedList = selectedSongList const finalSelectedList = selectedSongList
? allSongLists.find(list => list.key === selectedSongList) ? allSongLists.find(list => list.key === selectedSongList)
: null; : null;
@ -132,7 +144,7 @@ const SongLists: React.FC = () => {
song={song} song={song}
context="search" context="search"
onAddToQueue={() => handleAddToQueue(song)} onAddToQueue={() => handleAddToQueue(song)}
onSelectSinger={() => {}} // Info button functionality onSelectSinger={() => handleSongInfo(song)}
showAddButton={true} showAddButton={true}
showInfoButton={true} showInfoButton={true}
showFavoriteButton={false} showFavoriteButton={false}
@ -173,6 +185,15 @@ const SongLists: React.FC = () => {
</IonAccordionGroup> </IonAccordionGroup>
</IonContent> </IonContent>
</IonModal> </IonModal>
{/* Song Info Modal */}
{selectedSong && (
<SongInfo
isOpen={isSongInfoOpen}
onClose={handleCloseSongInfo}
song={selectedSong}
/>
)}
</div> </div>
</> </>
); );

View File

@ -4,7 +4,7 @@ import { close, list } from 'ionicons/icons';
import { useTopPlayed } from '../../hooks'; import { useTopPlayed } from '../../hooks';
import { useAppSelector } from '../../redux'; import { useAppSelector } from '../../redux';
import { selectTopPlayed, selectSongsArray } from '../../redux'; import { selectTopPlayed, selectSongsArray } from '../../redux';
import { InfiniteScrollList, SongItem, ListItem } from '../../components/common'; import { InfiniteScrollList, SongItem, ListItem, SongInfo } from '../../components/common';
import { filterSongs } from '../../utils/dataProcessing'; import { filterSongs } from '../../utils/dataProcessing';
import { debugLog } from '../../utils/logger'; import { debugLog } from '../../utils/logger';
import { useSongOperations } from '../../hooks'; import { useSongOperations } from '../../hooks';
@ -27,6 +27,8 @@ const Top100: React.FC = () => {
const { addToQueue } = useSongOperations(); const { addToQueue } = useSongOperations();
const { showSuccess, showError } = useToast(); const { showSuccess, showError } = useToast();
const [selectedTopPlayed, setSelectedTopPlayed] = useState<TopPlayed | null>(null); const [selectedTopPlayed, setSelectedTopPlayed] = useState<TopPlayed | null>(null);
const [selectedSong, setSelectedSong] = useState<Song | null>(null);
const [isSongInfoOpen, setIsSongInfoOpen] = useState(false);
debugLog('Top100 component - Redux data:', { topPlayedCount, topPlayedItems: topPlayedItems.length }); debugLog('Top100 component - Redux data:', { topPlayedCount, topPlayedItems: topPlayedItems.length });
@ -38,6 +40,16 @@ const Top100: React.FC = () => {
setSelectedTopPlayed(null); 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 // Find songs that match the selected top played item
const selectedSongs = useMemo(() => { const selectedSongs = useMemo(() => {
if (!selectedTopPlayed) return []; if (!selectedTopPlayed) return [];
@ -141,7 +153,7 @@ const Top100: React.FC = () => {
song={song} song={song}
context="search" context="search"
onAddToQueue={() => handleAddToQueue(song)} onAddToQueue={() => handleAddToQueue(song)}
onSelectSinger={() => {}} // Info button functionality onSelectSinger={() => handleSongInfo(song)}
showAddButton={true} showAddButton={true}
showInfoButton={true} showInfoButton={true}
showFavoriteButton={false} showFavoriteButton={false}
@ -150,6 +162,15 @@ const Top100: React.FC = () => {
</IonList> </IonList>
</IonContent> </IonContent>
</IonModal> </IonModal>
{/* Song Info Modal */}
{selectedSong && (
<SongInfo
isOpen={isSongInfoOpen}
onClose={handleCloseSongInfo}
song={selectedSong}
/>
)}
</> </>
); );
}; };