feat: add listening history page with grouped track display and clear history functionality

- Implemented HistoryPage component to display user's listening history.
- Tracks are grouped by date and displayed with play and add to queue options.
- Added clear history functionality with confirmation dialog.
- Created AlertDialog component for consistent alert dialog UI.
This commit is contained in:
2025-06-23 20:00:56 -05:00
parent 507951a478
commit 779ed06e35
8 changed files with 994 additions and 53 deletions

View File

@@ -37,6 +37,8 @@ interface AudioPlayerContextProps {
toggleShuffle: () => void;
shuffleAllAlbums: () => Promise<void>;
playArtist: (artistId: string) => Promise<void>;
playedTracks: Track[];
clearHistory: () => void;
}
const AudioPlayerContext = createContext<AudioPlayerContextProps | undefined>(undefined);
@@ -534,6 +536,27 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
}
}, [api, songToTrack, toast, shuffle, playTrack]);
const clearHistory = useCallback(() => {
setPlayedTracks([]);
localStorage.removeItem('navidrome-playedTracks');
}, []);
// Persist played tracks to localStorage
useEffect(() => {
localStorage.setItem('navidrome-playedTracks', JSON.stringify(playedTracks));
}, [playedTracks]);
// Load played tracks from localStorage on mount
useEffect(() => {
const savedPlayedTracks = localStorage.getItem('navidrome-playedTracks');
if (savedPlayedTracks) {
try {
setPlayedTracks(JSON.parse(savedPlayedTracks));
} catch (error) {
console.error('Failed to parse saved played tracks:', error);
}
}
}, []);
const contextValue = useMemo(() => ({
currentTrack,
playTrack,
@@ -552,7 +575,9 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
shuffle,
toggleShuffle,
shuffleAllAlbums,
playArtist
playArtist,
playedTracks,
clearHistory
}), [
currentTrack,
queue,
@@ -571,7 +596,9 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
shuffle,
toggleShuffle,
shuffleAllAlbums,
playArtist
playArtist,
playedTracks,
clearHistory
]);
return (

View File

@@ -285,16 +285,15 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
{/* Overlay for better contrast */}
<div className="absolute inset-0 bg-black/50" />
<div className="relative h-full w-full flex flex-col">
<div className="relative h-full w-full flex flex-col">
{/* Header */}
<div className="flex items-center justify-between p-4 lg:p-6 flex-shrink-0">
<h2 className="text-lg lg:text-xl font-semibold text-white"></h2>
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
{onOpenQueue && (
<button
onClick={onOpenQueue}
className="text-white hover:bg-white/20 p-2 rounded-full transition-colors"
className="text-white hover:bg-white/20 p-2 rounded-full transition-colors flex items-center justify-center w-10 h-10"
title="Open Queue"
>
<FaListUl className="w-5 h-5" />
@@ -302,7 +301,8 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
)}
<button
onClick={onClose}
className="text-white hover:bg-white/20 p-2 rounded-full transition-colors"
className="text-white hover:bg-white/20 p-2 rounded-full transition-colors flex items-center justify-center w-10 h-10"
title="Close Player"
>
<FaXmark className="w-5 h-5" />
</button>