feat: Remove Player tab and use persistent player across app

- Remove Player tab from Music Storage page
- Update play buttons to use persistent player instead of embedded player
- Add persistent player to Music Storage page for consistent experience
- Convert MusicFile objects to Song objects for persistent player compatibility
- Ensure music playback works seamlessly across both main view and Music Storage
- Create unified music playback experience throughout the application

Now users have a consistent music player experience across all pages
with the floating persistent player at the bottom of the screen.
This commit is contained in:
Geert Rademakes 2025-08-06 15:28:20 +02:00
parent a3d1b4d211
commit 1f235d8fa8

View File

@ -24,8 +24,9 @@ import {
} from '@chakra-ui/react';
import { FiPlay, FiTrash2, FiMusic, FiRefreshCw } from 'react-icons/fi';
import { MusicUpload } from '../components/MusicUpload';
import { MusicPlayer } from '../components/MusicPlayer';
import { SongMatching } from '../components/SongMatching';
import { PersistentMusicPlayer } from '../components/PersistentMusicPlayer';
import type { Song } from '../types/interfaces';
interface MusicFile {
_id: string;
@ -42,7 +43,7 @@ interface MusicFile {
export const MusicStorage: React.FC = () => {
const [musicFiles, setMusicFiles] = useState<MusicFile[]>([]);
const [selectedFile, setSelectedFile] = useState<MusicFile | null>(null);
const [currentPlayingSong, setCurrentPlayingSong] = useState<Song | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [isSyncing, setIsSyncing] = useState(false);
const toast = useToast();
@ -131,8 +132,8 @@ export const MusicStorage: React.FC = () => {
if (response.ok) {
setMusicFiles(prev => prev.filter(file => file._id !== fileId));
if (selectedFile?._id === fileId) {
setSelectedFile(null);
if (currentPlayingSong?.s3File?.musicFileId === fileId) {
setCurrentPlayingSong(null);
}
toast({
title: 'File Deleted',
@ -156,6 +157,44 @@ export const MusicStorage: React.FC = () => {
}
};
// Handle playing a music file from the Music Storage page
const handlePlayMusicFile = async (musicFile: MusicFile) => {
try {
// Create a Song object from the music file for the persistent player
const song: Song = {
id: musicFile._id,
title: musicFile.title || musicFile.originalName,
artist: musicFile.artist || 'Unknown Artist',
album: musicFile.album || '',
totalTime: musicFile.duration?.toString() || '0',
location: '',
s3File: {
musicFileId: musicFile._id,
s3Key: '', // This will be fetched by the persistent player
s3Url: '',
streamingUrl: '',
hasS3File: true,
},
};
setCurrentPlayingSong(song);
} catch (error) {
console.error('Error playing music file:', error);
toast({
title: 'Error',
description: 'Failed to play music file',
status: 'error',
duration: 3000,
isClosable: true,
});
}
};
// Handle closing the music player
const handleCloseMusicPlayer = () => {
setCurrentPlayingSong(null);
};
const formatFileSize = (bytes: number): string => {
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
if (bytes === 0) return '0 Bytes';
@ -208,9 +247,6 @@ export const MusicStorage: React.FC = () => {
<Tab color="gray.300" _selected={{ bg: "gray.700", color: "white", borderColor: "gray.600" }}>
Song Matching
</Tab>
<Tab color="gray.300" _selected={{ bg: "gray.700", color: "white", borderColor: "gray.600" }}>
Player
</Tab>
</TabList>
<TabPanels flex={1} overflow="hidden">
@ -324,7 +360,7 @@ export const MusicStorage: React.FC = () => {
icon={<FiPlay />}
size="sm"
colorScheme="blue"
onClick={() => setSelectedFile(file)}
onClick={() => handlePlayMusicFile(file)}
_hover={{ bg: "blue.700" }}
/>
<IconButton
@ -349,42 +385,14 @@ export const MusicStorage: React.FC = () => {
<TabPanel bg="gray.900" height="100%" overflowY="auto">
<SongMatching />
</TabPanel>
{/* Player Tab */}
<TabPanel bg="gray.900" height="100%" overflowY="auto">
<VStack spacing={4} align="stretch">
<Heading size="md" color="white">Music Player</Heading>
{selectedFile ? (
<MusicPlayer
musicFile={selectedFile}
onEnded={() => {
// Auto-play next song or stop
const currentIndex = musicFiles.findIndex(f => f._id === selectedFile._id);
const nextFile = musicFiles[currentIndex + 1];
if (nextFile) {
setSelectedFile(nextFile);
}
}}
/>
) : (
<Box
p={8}
textAlign="center"
border="2px dashed"
borderColor="gray.600"
borderRadius="lg"
color="gray.500"
bg="gray.800"
>
<FiMusic size={48} style={{ margin: '0 auto 16px' }} />
<Text>Select a music file from the library to start playing</Text>
</Box>
)}
</VStack>
</TabPanel>
</TabPanels>
</Tabs>
</VStack>
{/* Persistent Music Player */}
<PersistentMusicPlayer
currentSong={currentPlayingSong}
onClose={handleCloseMusicPlayer}
/>
</Box>
);
};