refactor: refine global player visibility and active signal labels

This commit is contained in:
Carlos (Almeira) 2026-03-30 08:55:51 -05:00
parent 031e8f4523
commit 86b2e704e9
3 changed files with 25 additions and 10 deletions

View File

@ -42,7 +42,7 @@ export default async function RootLayout({
<GlobalTopBanner />
{children}
</div>
<GlobalPlayer />
<GlobalPlayer initialConfig={entity} />
</body>
</html>
);

View File

@ -7,10 +7,10 @@ import { StreamOverlays } from './StreamOverlays';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';
export const GlobalPlayer = () => {
export const GlobalPlayer = ({ initialConfig }: { initialConfig?: any }) => {
const {
audioUrl, isAudioPlaying, audioVolume, toggleAudio, setAudioVolume,
isVideoActive, videoUrl, videoType, setVideoActive
audioUrl, isAudioPlaying, audioVolume, toggleAudio, setAudioUrl, setAudioVolume,
isVideoActive, videoUrl, videoType, setVideoActive, setVideoUrl, setVideoType
} = usePlayerStore();
const audioRef = useRef<HTMLAudioElement>(null);
@ -19,6 +19,21 @@ export const GlobalPlayer = () => {
const [isMuted, setIsMuted] = useState(false);
const [lastVolume, setLastVolume] = useState(audioVolume);
const [isExpanded, setIsExpanded] = useState(false);
const [hasHydrated, setHasHydrated] = useState(false);
// Sync from Layout Config on First Load
useEffect(() => {
if (initialConfig) {
if (initialConfig.radio_url && audioUrl === '') {
setAudioUrl(initialConfig.radio_url);
}
if (initialConfig.tv_url && videoUrl === '') {
setVideoUrl(initialConfig.tv_url);
setVideoType(initialConfig.tv_url.includes('youtube.com') || initialConfig.tv_url.includes('youtu.be') ? 'youtube' : 'm3u8');
}
}
setHasHydrated(true);
}, [initialConfig, setAudioUrl, setVideoUrl, setVideoType]);
// Sync Audio State
useEffect(() => {
@ -130,7 +145,7 @@ export const GlobalPlayer = () => {
<div className={`fixed bottom-6 left-6 z-[60] flex items-center gap-3 transition-opacity duration-500 ${isVideoActive ? 'opacity-0 pointer-events-none' : 'opacity-100'}`}>
{/* ESTADO COLAPSADO */}
{!isExpanded && (audioUrl || videoUrl) && (
{!isExpanded && (audioUrl !== '' || videoUrl !== '') && (
<button
onClick={() => setIsExpanded(true)}
className="group relative h-14 px-5 bg-red-600 hover:bg-red-500 text-white rounded-full flex items-center justify-center gap-3 shadow-[0_0_20px_rgba(220,38,38,0.4)] transition-all animate-in zoom-in slide-in-from-bottom-5"
@ -169,10 +184,10 @@ export const GlobalPlayer = () => {
<div className="flex flex-col pr-3">
<div className="flex items-center gap-2">
<span className={`text-[10px] font-black uppercase tracking-[0.2em] transition-colors ${isAudioPlaying ? 'text-cyan-400' : 'text-slate-500'}`}>
{isAudioPlaying ? 'Señal Activa' : 'Radio Offline'}
<span className={`text-[10px] font-black uppercase tracking-[0.2em] transition-colors ${isAudioPlaying ? 'text-cyan-400' : 'text-rose-400'}`}>
{isAudioPlaying ? 'Al Aire' : 'Señal en Vivo'}
</span>
{isAudioPlaying && <div className="w-1.5 h-1.5 bg-red-500 rounded-full animate-pulse shadow-[0_0_8px_rgba(239,68,68,0.5)]"></div>}
<div className={`w-1.5 h-1.5 rounded-full ${isAudioPlaying ? 'bg-red-500 animate-pulse shadow-[0_0_8px_rgba(239,68,68,0.5)]' : 'bg-rose-500'}`}></div>
</div>
<h4 className="text-xs font-bold text-white tracking-wider font-outfit truncate max-w-[100px]">ALMEIRA RADIO</h4>
</div>

View File

@ -35,11 +35,11 @@ export const usePlayerStore = create<PlayerState>()(
persist(
(set) => ({
// Default values
audioUrl: 'https://radio.almeira.com.co/listen/almeira/radio.mp3',
audioUrl: '',
isAudioPlaying: false,
audioVolume: 0.8,
videoUrl: 'https://tv.almeira.com.co/hls/stream.m3u8',
videoUrl: '',
isVideoActive: false,
videoVolume: 0.5,
videoType: 'm3u8',