You've already forked Atomcms-edit
236 lines
7.4 KiB
PHP
Executable File
236 lines
7.4 KiB
PHP
Executable File
@props(['classes' => ''])
|
||
|
||
@php
|
||
$style = cache()->remember('radio_style_value', 300, fn() => \App\Models\Miscellaneous\WebsiteSetting::where('key', 'radio_style')->value('value')) ?? 'dark';
|
||
$bgColor = match($style) {
|
||
'light' => 'bg-white/90',
|
||
'blue' => 'bg-blue-900/90',
|
||
default => 'bg-black/90',
|
||
};
|
||
$textColor = match($style) {
|
||
'light' => 'text-gray-900',
|
||
default => 'text-white',
|
||
};
|
||
$accentColor = match($style) {
|
||
'light' => 'text-blue-600',
|
||
'blue' => 'text-yellow-400',
|
||
default => 'text-[var(--color-primary)]',
|
||
};
|
||
@endphp
|
||
|
||
<div class="fixed bottom-4 right-4 z-50 flex flex-col gap-2 {{ $classes }}">
|
||
<div id="radio-player" class="{{ $bgColor }} backdrop-blur-sm rounded-lg p-3 {{ $textColor }} shadow-lg w-72 sm:w-96">
|
||
<div class="flex items-center justify-between">
|
||
<div class="flex items-center gap-3">
|
||
<div id="radio-status" class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div>
|
||
<div class="flex flex-col">
|
||
<span class="text-xs font-semibold {{ $accentColor }}">Radio</span>
|
||
<span id="current-dj" class="text-xs font-medium">Laden...</span>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<button id="radio-toggle" onclick="toggleRadio()" class="{{ $accentColor }} hover:opacity-80 transition">
|
||
<span id="play-icon">▶</span>
|
||
<span id="pause-icon" class="hidden">⏸</span>
|
||
</button>
|
||
<input type="range" id="volume-control" min="0" max="100" value="50" class="w-16 h-1 rounded cursor-pointer accent-{{ $accentColor }}" onchange="changeVolume(this.value)">
|
||
</div>
|
||
</div>
|
||
|
||
<div id="now-playing" class="mt-2 text-xs text-center py-1 px-2 bg-black/20 rounded">
|
||
<span id="song-title">Laden...</span>
|
||
</div>
|
||
|
||
<div class="mt-2 flex items-center justify-between text-xs">
|
||
<span id="listeners" class="flex items-center gap-1">
|
||
<span>👥</span>
|
||
<span id="listeners-count">--</span>
|
||
</span>
|
||
<button onclick="toggleShouts()" class="{{ $accentColor }} hover:underline">
|
||
🔊 Shouts
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="shouts-panel" class="hidden {{ $bgColor }} backdrop-blur-sm rounded-lg p-3 {{ $textColor }} shadow-lg w-80 sm:w-full max-h-64 overflow-y-auto">
|
||
<div class="flex justify-between items-center mb-2">
|
||
<span class="text-xs font-semibold {{ $accentColor }}">Live Shouts</span>
|
||
<button onclick="toggleShouts()" class="text-gray-400 hover:text-white text-xs">×</button>
|
||
</div>
|
||
<div id="shouts-list" class="space-y-2">
|
||
<p class="text-xs text-gray-400">Shouts laden...</p>
|
||
</div>
|
||
</div>
|
||
|
||
<input type="hidden" id="radio-stream-url" value="">
|
||
<audio id="radio-audio" preload="none"></audio>
|
||
</div>
|
||
|
||
<script>
|
||
let isPlaying = false;
|
||
let shoutsPanelOpen = false;
|
||
|
||
function toggleRadio() {
|
||
const audio = document.getElementById('radio-audio');
|
||
const playIcon = document.getElementById('play-icon');
|
||
const pauseIcon = document.getElementById('pause-icon');
|
||
const radioStatus = document.getElementById('radio-status');
|
||
|
||
if (isPlaying) {
|
||
audio.pause();
|
||
playIcon.classList.remove('hidden');
|
||
pauseIcon.classList.add('hidden');
|
||
radioStatus.classList.remove('bg-green-500', 'animate-pulse');
|
||
radioStatus.classList.add('bg-gray-500');
|
||
isPlaying = false;
|
||
} else {
|
||
fetch('/api/radio/config')
|
||
.then(r => r.json())
|
||
.then(config => {
|
||
if (config.stream_url) {
|
||
audio.src = config.stream_url;
|
||
audio.play().then(() => {
|
||
playIcon.classList.add('hidden');
|
||
pauseIcon.classList.remove('hidden');
|
||
radioStatus.classList.add('bg-green-500', 'animate-pulse');
|
||
radioStatus.classList.remove('bg-gray-500');
|
||
isPlaying = true;
|
||
}).catch(e => {
|
||
console.error('Audio play failed:', e);
|
||
alert('Kan radio niet afspelen. Controleer je browser instellingen en probeer het opnieuw.');
|
||
});
|
||
} else {
|
||
alert('Geen stream URL beschikbaar. Radio is mogelijk offline.');
|
||
}
|
||
})
|
||
.catch(e => {
|
||
console.error('Failed to fetch radio config:', e);
|
||
alert('Kan radio configuratie niet laden. Probeer het later opnieuw.');
|
||
});
|
||
}
|
||
}
|
||
|
||
function changeVolume(value) {
|
||
const audio = document.getElementById('radio-audio');
|
||
audio.volume = value / 100;
|
||
}
|
||
|
||
function toggleShouts() {
|
||
const panel = document.getElementById('shouts-panel');
|
||
shoutsPanelOpen = !shoutsPanelOpen;
|
||
panel.classList.toggle('hidden', !shoutsPanelOpen);
|
||
if (shoutsPanelOpen) {
|
||
loadShouts();
|
||
}
|
||
}
|
||
|
||
function loadShouts() {
|
||
fetch('/api/radio/shouts')
|
||
.then(response => {
|
||
if (!response.ok) {
|
||
throw new Error('Shouts niet beschikbaar');
|
||
}
|
||
return response.json();
|
||
})
|
||
.then(data => {
|
||
const shoutsList = document.getElementById('shouts-list');
|
||
if (data.error) {
|
||
shoutsList.innerHTML = `<p class="text-xs text-red-400">${data.error}</p>`;
|
||
} else if (data.shouts && data.shouts.length > 0) {
|
||
shoutsList.innerHTML = data.shouts.map(shout => `
|
||
<div class="text-xs border-b border-gray-700 pb-1 mb-1">
|
||
<span class="font-semibold ${shout.username === 'Anoniem' ? 'text-gray-400' : '{{ $accentColor }}'}">${shout.username}:</span>
|
||
<span class="text-gray-300 ml-1">${shout.message}</span>
|
||
<span class="text-gray-500 text-xs block">${shout.created_at}</span>
|
||
</div>
|
||
`).join('');
|
||
} else {
|
||
shoutsList.innerHTML = '<p class="text-xs text-gray-400">Nog geen shouts... Wees de eerste!</p>';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Shouts load error:', error);
|
||
document.getElementById('shouts-list').innerHTML = '<p class="text-xs text-red-400">Fout bij laden van shouts...</p>';
|
||
});
|
||
}
|
||
|
||
function getCurrentDJ() {
|
||
fetch('/api/radio/current-dj')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const djElement = document.getElementById('current-dj');
|
||
if (data.error) {
|
||
djElement.textContent = 'Error: ' + data.error;
|
||
} else if (data.dj) {
|
||
const djName = (typeof data.dj === 'object' && data.dj !== null)
|
||
? (data.dj.username || data.dj.show_name || 'DJ')
|
||
: data.dj;
|
||
djElement.textContent = djName;
|
||
} else {
|
||
djElement.textContent = 'Geen DJ actief';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('DJ info error:', error);
|
||
document.getElementById('current-dj').textContent = '--';
|
||
});
|
||
}
|
||
|
||
function getNowPlaying() {
|
||
fetch('/api/radio/now-playing')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const songElement = document.getElementById('song-title');
|
||
if (data.error) {
|
||
songElement.textContent = 'Error: ' + data.error;
|
||
} else if (data.song) {
|
||
songElement.textContent = data.song + (data.artist ? ' - ' + data.artist : '');
|
||
} else if (data.artist && data.title) {
|
||
songElement.textContent = data.artist + ' - ' + data.title;
|
||
} else if (typeof data.now_playing === 'object' && data.now_playing !== null) {
|
||
const np = data.now_playing;
|
||
if (np.song) {
|
||
songElement.textContent = np.song + (np.artist ? ' - ' + np.artist : '');
|
||
} else if (np.artist && np.title) {
|
||
songElement.textContent = np.artist + ' - ' + np.title;
|
||
} else {
|
||
songElement.textContent = 'Live radio';
|
||
}
|
||
} else {
|
||
songElement.textContent = 'Live radio';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Now playing error:', error);
|
||
document.getElementById('song-title').textContent = 'Niet beschikbaar';
|
||
});
|
||
}
|
||
|
||
function getListeners() {
|
||
fetch('/api/radio/listeners')
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
const countElement = document.getElementById('listeners-count');
|
||
if (data.error) {
|
||
countElement.textContent = 'Error';
|
||
} else {
|
||
countElement.textContent = data.count ? data.count.toLocaleString() : '0';
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('Listeners error:', error);
|
||
document.getElementById('listeners-count').textContent = '--';
|
||
});
|
||
}
|
||
|
||
setInterval(getListeners, 30000);
|
||
setInterval(getNowPlaying, 30000);
|
||
setInterval(getCurrentDJ, 30000);
|
||
if (shoutsPanelOpen) {
|
||
setInterval(loadShouts, 15000);
|
||
}
|
||
getCurrentDJ();
|
||
getNowPlaying();
|
||
getListeners();
|
||
</script>
|