Changes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Play, Pause, Volume2, Music2, SkipBack, SkipForward, Loader2 } from 'lucide-react';
|
||||
import { useSettings } from '@/contexts/SettingsContext';
|
||||
import { useMusic } from '@/contexts/MusicContext';
|
||||
@@ -8,6 +8,7 @@ import { useState } from 'react';
|
||||
|
||||
const MusicPlayer = () => {
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { playSound, soundEnabled } = useSettings();
|
||||
const {
|
||||
isPlaying,
|
||||
@@ -29,6 +30,25 @@ const MusicPlayer = () => {
|
||||
}
|
||||
}, [isExpanded, fetchStations]);
|
||||
|
||||
// Close on click outside (for mobile)
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
|
||||
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
|
||||
setIsExpanded(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (isExpanded) {
|
||||
document.addEventListener('mousedown', handleClickOutside);
|
||||
document.addEventListener('touchstart', handleClickOutside);
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside);
|
||||
document.removeEventListener('touchstart', handleClickOutside);
|
||||
};
|
||||
}, [isExpanded]);
|
||||
|
||||
const handleButtonClick = (action: () => void) => {
|
||||
if (soundEnabled) {
|
||||
playSound('click');
|
||||
@@ -36,8 +56,13 @@ const MusicPlayer = () => {
|
||||
action();
|
||||
};
|
||||
|
||||
const handleToggleExpand = () => {
|
||||
setIsExpanded(!isExpanded);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="fixed bottom-4 left-4 z-50"
|
||||
onMouseEnter={() => setIsExpanded(true)}
|
||||
onMouseLeave={() => setIsExpanded(false)}
|
||||
@@ -156,6 +181,11 @@ const MusicPlayer = () => {
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="p-3 bg-background/90 border border-primary box-glow cursor-pointer"
|
||||
onClick={handleToggleExpand}
|
||||
onTouchEnd={(e) => {
|
||||
e.preventDefault();
|
||||
handleToggleExpand();
|
||||
}}
|
||||
>
|
||||
<Music2 className="w-5 h-5 text-primary text-glow" />
|
||||
{isPlaying && (
|
||||
|
||||
@@ -258,49 +258,6 @@ export function Oscilloscope() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Audio Input Row */}
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
|
||||
<div className="flex-1 w-full sm:w-auto">
|
||||
<AudioUploader
|
||||
onFileSelect={handleFileSelect}
|
||||
isLoading={isLoading}
|
||||
fileName={fileName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Microphone Toggle */}
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
onClick={toggleMic}
|
||||
variant={isMicActive ? "default" : "outline"}
|
||||
className={`flex items-center gap-2 font-crt ${
|
||||
isMicActive
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: 'border-primary/50 hover:bg-primary/10'
|
||||
}`}
|
||||
>
|
||||
{isMicActive ? <MicOff size={16} /> : <Mic size={16} />}
|
||||
{isMicActive ? 'STOP MIC' : 'USE MICROPHONE'}
|
||||
</Button>
|
||||
|
||||
{isMicActive && (
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-sm text-muted-foreground font-mono-crt">
|
||||
Real-time input active
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setShowMicCalibration(!showMicCalibration)}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="font-mono-crt text-xs"
|
||||
>
|
||||
Calibrate
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Content: Display + Controls Side by Side */}
|
||||
<div className="grid grid-cols-1 xl:grid-cols-[1fr_320px] gap-6">
|
||||
{/* Oscilloscope Display */}
|
||||
@@ -386,6 +343,49 @@ export function Oscilloscope() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Audio Input Row - Now at bottom */}
|
||||
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
|
||||
<div className="flex-1 w-full sm:w-auto">
|
||||
<AudioUploader
|
||||
onFileSelect={handleFileSelect}
|
||||
isLoading={isLoading}
|
||||
fileName={fileName}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Microphone Toggle */}
|
||||
<div className="flex items-center gap-4">
|
||||
<Button
|
||||
onClick={toggleMic}
|
||||
variant={isMicActive ? "default" : "outline"}
|
||||
className={`flex items-center gap-2 font-crt ${
|
||||
isMicActive
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: 'border-primary/50 hover:bg-primary/10'
|
||||
}`}
|
||||
>
|
||||
{isMicActive ? <MicOff size={16} /> : <Mic size={16} />}
|
||||
{isMicActive ? 'STOP MIC' : 'USE MICROPHONE'}
|
||||
</Button>
|
||||
|
||||
{isMicActive && (
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-sm text-muted-foreground font-mono-crt">
|
||||
Real-time input active
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => setShowMicCalibration(!showMicCalibration)}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="font-mono-crt text-xs"
|
||||
>
|
||||
Calibrate
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Microphone Calibration */}
|
||||
{showMicCalibration && isMicActive && (
|
||||
|
||||
Reference in New Issue
Block a user