You've already forked Atomcms-edit
Initial commit
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
@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>
|
||||
Reference in New Issue
Block a user