diff --git a/src/components/QRCode.tsx b/src/components/QRCode.tsx index eeefcdd7..cd6bf105 100644 --- a/src/components/QRCode.tsx +++ b/src/components/QRCode.tsx @@ -73,7 +73,7 @@ export const QRCodeComponent = forwardRef +
= ({ }) => { const audioRef = useRef(null); const [isLoading, setIsLoading] = useState(true); + const [hasError, setHasError] = useState(false); + + // Reset state when source changes + useEffect(() => { + setIsLoading(true); + setHasError(false); + }, [src]); // When the audio can start playing, hide the loader. useEffect(() => { const audio = audioRef.current; if (!audio) return; - const handleCanPlay = () => setIsLoading(false); + const handleCanPlay = () => { + setIsLoading(false); + setHasError(false); + }; const handleStalled = () => setIsLoading(true); + const handleError = () => { + setIsLoading(false); + setHasError(true); + }; + audio.addEventListener('canplay', handleCanPlay); audio.addEventListener('stalled', handleStalled); + audio.addEventListener('error', handleError); // Cleanup listeners on unmount. return () => { audio.removeEventListener('canplay', handleCanPlay); audio.removeEventListener('stalled', handleStalled); + audio.removeEventListener('error', handleError); }; }, [src]); // Auto‑play if requested. useEffect(() => { if (autoPlay && audioRef.current) { - // eslint‑disable-next-line @typescript-eslint/no-floating-promises + // Reset autoplay correctly on source change + audioRef.current.load(); + // eslint-disable-next-line @typescript-eslint/no-floating-promises audioRef.current.play().catch(() => { // Fail silently – the user may need to interact first. }); @@ -57,7 +76,7 @@ export const AudioPlayer: React.FC = ({
{/* Loading animation – visible only while isLoading is true */} - {isLoading && ( + {isLoading && !hasError && ( = ({
)} + {hasError && ( + + Failed to load audio + + )} {/* Native audio element – always present but hidden behind the loader */} @@ -94,7 +124,7 @@ export const AudioPlayer: React.FC = ({ src={src} controls={controls} className="w-full" - style={{ opacity: isLoading ? 0 : 1, transition: 'opacity 0.2s' }} + style={{ opacity: isLoading || hasError ? 0 : 1, transition: 'opacity 0.2s' }} />
);