Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -634,6 +634,7 @@ export const AudioPlayer: React.FC = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
|
data-testid="play-pause-button"
|
||||||
aria-label={isPlaying ? 'Pause' : 'Play'}
|
aria-label={isPlaying ? 'Pause' : 'Play'}
|
||||||
>
|
>
|
||||||
{isPlaying ? <FaPause className="w-5 h-5" /> : <FaPlay className="w-5 h-5" />}
|
{isPlaying ? <FaPause className="w-5 h-5" /> : <FaPlay className="w-5 h-5" />}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
toggleCurrentTrackStar,
|
toggleCurrentTrackStar,
|
||||||
queue
|
queue
|
||||||
} = useAudioPlayer();
|
} = useAudioPlayer();
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [progress, setProgress] = useState(0);
|
const [progress, setProgress] = useState(0);
|
||||||
@@ -62,6 +63,16 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
const [activeTab, setActiveTab] = useState<MobileTab>('player');
|
const [activeTab, setActiveTab] = useState<MobileTab>('player');
|
||||||
const lyricsRef = useRef<HTMLDivElement>(null);
|
const lyricsRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Debug logging for component changes
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('🔍 FullScreenPlayer state changed:', {
|
||||||
|
isOpen,
|
||||||
|
currentTrack,
|
||||||
|
currentTrackKeys: currentTrack ? Object.keys(currentTrack) : 'null',
|
||||||
|
queueLength: queue?.length || 0
|
||||||
|
});
|
||||||
|
}, [isOpen, currentTrack, queue?.length]);
|
||||||
|
|
||||||
// Load lyrics when track changes
|
// Load lyrics when track changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadLyrics = async () => {
|
const loadLyrics = async () => {
|
||||||
@@ -85,7 +96,7 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
setLyrics([]);
|
setLyrics([]);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load lyrics:', error);
|
console.log('Failed to load lyrics:', error);
|
||||||
setLyrics([]);
|
setLyrics([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -101,9 +112,9 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
}
|
}
|
||||||
}, [lyrics, currentTime, currentLyricIndex]);
|
}, [lyrics, currentTime, currentLyricIndex]);
|
||||||
|
|
||||||
// Auto-scroll lyrics using lyricsRef - Simplified for iOS compatibility
|
// Auto-scroll lyrics using lyricsRef - Disabled on mobile to prevent iOS audio issues
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Only auto-scroll if lyrics are visible and we're not on mobile to avoid iOS audio issues
|
// Only auto-scroll on desktop to avoid iOS audio interference
|
||||||
const shouldScroll = !isMobile && showLyrics && lyrics.length > 0;
|
const shouldScroll = !isMobile && showLyrics && lyrics.length > 0;
|
||||||
|
|
||||||
if (currentLyricIndex >= 0 && shouldScroll && lyricsRef.current) {
|
if (currentLyricIndex >= 0 && shouldScroll && lyricsRef.current) {
|
||||||
@@ -156,34 +167,52 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
|
|
||||||
return () => clearTimeout(resetTimeout);
|
return () => clearTimeout(resetTimeout);
|
||||||
}
|
}
|
||||||
}, [currentTrack?.id, showLyrics, currentTrack, isMobile, lyrics.length]);
|
}, [currentTrack?.id, showLyrics, isMobile, lyrics.length]);
|
||||||
|
|
||||||
// Sync with main audio player (improved responsiveness)
|
// Sync with main audio player (improved responsiveness)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const syncWithMainPlayer = () => {
|
const syncWithMainPlayer = () => {
|
||||||
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
|
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
|
||||||
if (mainAudio && currentTrack) {
|
|
||||||
// Console log audio information for debugging
|
console.log('=== FULLSCREEN PLAYER AUDIO DEBUG ===');
|
||||||
console.log('=== FULLSCREEN PLAYER AUDIO DEBUG ===');
|
console.log('currentTrack from context:', currentTrack);
|
||||||
|
console.log('currentTrack keys:', currentTrack ? Object.keys(currentTrack) : 'null');
|
||||||
|
if (currentTrack) {
|
||||||
|
console.log('currentTrack.url:', currentTrack.url);
|
||||||
|
console.log('currentTrack.id:', currentTrack.id);
|
||||||
|
console.log('currentTrack.name:', currentTrack.name);
|
||||||
|
console.log('currentTrack.artist:', currentTrack.artist);
|
||||||
|
}
|
||||||
|
console.log('Audio element found:', !!mainAudio);
|
||||||
|
|
||||||
|
if (mainAudio) {
|
||||||
console.log('Audio element src:', mainAudio.src);
|
console.log('Audio element src:', mainAudio.src);
|
||||||
console.log('Audio element currentSrc:', mainAudio.currentSrc);
|
console.log('Audio element currentSrc:', mainAudio.currentSrc);
|
||||||
console.log('Current track:', {
|
|
||||||
id: currentTrack.id,
|
|
||||||
name: currentTrack.name,
|
|
||||||
url: currentTrack.url,
|
|
||||||
artist: currentTrack.artist,
|
|
||||||
album: currentTrack.album
|
|
||||||
});
|
|
||||||
console.log('Audio state:', {
|
console.log('Audio state:', {
|
||||||
currentTime: mainAudio.currentTime,
|
currentTime: mainAudio.currentTime,
|
||||||
duration: mainAudio.duration,
|
duration: mainAudio.duration,
|
||||||
paused: mainAudio.paused,
|
paused: mainAudio.paused,
|
||||||
ended: mainAudio.ended,
|
ended: mainAudio.ended,
|
||||||
readyState: mainAudio.readyState,
|
readyState: mainAudio.readyState,
|
||||||
networkState: mainAudio.networkState
|
networkState: mainAudio.networkState,
|
||||||
|
error: mainAudio.error
|
||||||
});
|
});
|
||||||
console.log('==========================================');
|
|
||||||
|
|
||||||
|
// Check if audio source matches current track
|
||||||
|
if (currentTrack) {
|
||||||
|
const audioSourceMatches = mainAudio.src === currentTrack.url || mainAudio.currentSrc === currentTrack.url;
|
||||||
|
console.log('Audio source matches current track URL:', audioSourceMatches);
|
||||||
|
if (!audioSourceMatches) {
|
||||||
|
console.log('⚠️ Audio source mismatch!');
|
||||||
|
console.log('Expected:', currentTrack.url);
|
||||||
|
console.log('Audio src:', mainAudio.src);
|
||||||
|
console.log('Audio currentSrc:', mainAudio.currentSrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('==========================================');
|
||||||
|
|
||||||
|
if (mainAudio && currentTrack) {
|
||||||
const newCurrentTime = mainAudio.currentTime;
|
const newCurrentTime = mainAudio.currentTime;
|
||||||
const newDuration = mainAudio.duration || 0;
|
const newDuration = mainAudio.duration || 0;
|
||||||
const newIsPlaying = !mainAudio.paused;
|
const newIsPlaying = !mainAudio.paused;
|
||||||
@@ -245,36 +274,96 @@ export const FullScreenPlayer: React.FC<FullScreenPlayerProps> = ({ isOpen, onCl
|
|||||||
setDominantColor(`rgb(${r}, ${g}, ${b})`);
|
setDominantColor(`rgb(${r}, ${g}, ${b})`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to extract color:', error);
|
console.log('Failed to extract color:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
img.src = currentTrack.coverArt;
|
img.src = currentTrack.coverArt;
|
||||||
}, [currentTrack]);
|
}, [currentTrack]);
|
||||||
|
|
||||||
const togglePlayPause = () => {
|
const togglePlayPause = () => {
|
||||||
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
|
console.log('🎵 FullScreenPlayer Toggle Play/Pause clicked');
|
||||||
if (!mainAudio) {
|
|
||||||
console.log('❌ No audio element found');
|
// Find the main audio player's play/pause button and click it
|
||||||
return;
|
// This ensures we use the same logic as the main player
|
||||||
}
|
const mainPlayButton = document.querySelector('[data-testid="play-pause-button"]') as HTMLButtonElement;
|
||||||
|
|
||||||
console.log('🎵 Toggle Play/Pause clicked');
|
if (mainPlayButton) {
|
||||||
console.log('Audio src before toggle:', mainAudio.src);
|
console.log('✅ Found main play button, triggering click');
|
||||||
console.log('Audio currentSrc before toggle:', mainAudio.currentSrc);
|
mainPlayButton.click();
|
||||||
console.log('Audio paused state before toggle:', mainAudio.paused);
|
|
||||||
console.log('Audio currentTime before toggle:', mainAudio.currentTime);
|
|
||||||
console.log('Audio duration before toggle:', mainAudio.duration);
|
|
||||||
|
|
||||||
if (isPlaying) {
|
|
||||||
console.log('⏸️ Pausing audio');
|
|
||||||
mainAudio.pause();
|
|
||||||
} else {
|
} else {
|
||||||
console.log('▶️ Playing audio');
|
console.log('❌ Main play button not found, falling back to direct audio control');
|
||||||
mainAudio.play().then(() => {
|
|
||||||
console.log('✅ Audio play() succeeded');
|
// Fallback to direct audio control if button not found
|
||||||
}).catch((error) => {
|
const mainAudio = document.querySelector('audio') as HTMLAudioElement;
|
||||||
console.error('❌ Audio play() failed:', error);
|
if (!mainAudio) {
|
||||||
});
|
console.log('❌ No audio element found');
|
||||||
|
|
||||||
|
// Try to find ALL audio elements for debugging
|
||||||
|
const allAudio = document.querySelectorAll('audio');
|
||||||
|
console.log('🔍 Found audio elements:', allAudio.length);
|
||||||
|
allAudio.forEach((audio, index) => {
|
||||||
|
console.log(`Audio ${index}:`, {
|
||||||
|
src: audio.src,
|
||||||
|
currentSrc: audio.currentSrc,
|
||||||
|
paused: audio.paused,
|
||||||
|
hidden: audio.hidden,
|
||||||
|
style: audio.style.display
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔍 Detailed audio element state:');
|
||||||
|
console.log('- Audio src:', mainAudio.src);
|
||||||
|
console.log('- Audio currentSrc:', mainAudio.currentSrc);
|
||||||
|
console.log('- Audio paused:', mainAudio.paused);
|
||||||
|
console.log('- Audio currentTime:', mainAudio.currentTime);
|
||||||
|
console.log('- Audio duration:', mainAudio.duration);
|
||||||
|
console.log('- Audio readyState:', mainAudio.readyState, '(0=HAVE_NOTHING, 1=HAVE_METADATA, 2=HAVE_CURRENT_DATA, 3=HAVE_FUTURE_DATA, 4=HAVE_ENOUGH_DATA)');
|
||||||
|
console.log('- Audio networkState:', mainAudio.networkState, '(0=EMPTY, 1=IDLE, 2=LOADING, 3=NO_SOURCE)');
|
||||||
|
console.log('- Audio error:', mainAudio.error);
|
||||||
|
console.log('- Audio ended:', mainAudio.ended);
|
||||||
|
console.log('- Audio seeking:', mainAudio.seeking);
|
||||||
|
console.log('- Audio volume:', mainAudio.volume);
|
||||||
|
console.log('- Audio muted:', mainAudio.muted);
|
||||||
|
console.log('- Audio autoplay:', mainAudio.autoplay);
|
||||||
|
console.log('- Audio loop:', mainAudio.loop);
|
||||||
|
console.log('- Audio preload:', mainAudio.preload);
|
||||||
|
console.log('- Audio crossOrigin:', mainAudio.crossOrigin);
|
||||||
|
|
||||||
|
if (isPlaying) {
|
||||||
|
console.log('⏸️ Attempting to pause audio');
|
||||||
|
try {
|
||||||
|
mainAudio.pause();
|
||||||
|
console.log('✅ Audio pause() succeeded');
|
||||||
|
} catch (error) {
|
||||||
|
console.log('❌ Audio pause() failed:', error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('▶️ Attempting to play audio');
|
||||||
|
|
||||||
|
// Check if audio has a valid source
|
||||||
|
if (!mainAudio.src && !mainAudio.currentSrc) {
|
||||||
|
console.log('❌ Audio has no source set!');
|
||||||
|
console.log('currentTrack:', currentTrack);
|
||||||
|
if (currentTrack) {
|
||||||
|
console.log('Setting audio source to:', currentTrack.url);
|
||||||
|
mainAudio.src = currentTrack.url;
|
||||||
|
mainAudio.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mainAudio.play().then(() => {
|
||||||
|
console.log('✅ Audio play() succeeded');
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log('❌ Audio play() failed:', error);
|
||||||
|
console.log('Error details:', {
|
||||||
|
name: error.name,
|
||||||
|
message: error.message,
|
||||||
|
code: error.code
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export const metadata = {
|
|||||||
{ url: '/icon-512.png', sizes: '512x512', type: 'image/png' },
|
{ url: '/icon-512.png', sizes: '512x512', type: 'image/png' },
|
||||||
],
|
],
|
||||||
apple: [
|
apple: [
|
||||||
{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' },
|
{ url: '/apple-touch-icon-precomposed.png', sizes: '180x180', type: 'image/png' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
BIN
public/apple-touch-icon-precomposed.png
Normal file
BIN
public/apple-touch-icon-precomposed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Reference in New Issue
Block a user