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:
parent
a3d1b4d211
commit
1f235d8fa8
@ -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>
|
||||
);
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user