You've already forked Atomcms-edit
194 lines
7.6 KiB
PHP
Executable File
194 lines
7.6 KiB
PHP
Executable File
<div x-data="radioPlayer()" x-init="initPlayer()"
|
|
class="radio-player-widget"
|
|
:class="{ 'radio-player-visible': isVisible, 'radio-player-hidden': !isVisible }"
|
|
x-show="showWidget"
|
|
style="display: none;">
|
|
|
|
<!-- Toggle Button -->
|
|
<button
|
|
x-show="!isExpanded"
|
|
@click="toggleExpand()"
|
|
class="fixed bottom-4 right-4 z-50 w-14 h-14 rounded-full bg-gradient-to-r from-amber-500 to-amber-600 text-white shadow-lg hover:shadow-amber-500/30 flex items-center justify-center transition-all hover:scale-110"
|
|
>
|
|
<svg class="w-6 h-6 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<!-- Expanded Player -->
|
|
<div
|
|
x-show="isExpanded"
|
|
class="fixed bottom-4 right-4 z-50 w-96 rounded-2xl shadow-2xl overflow-hidden bg-gray-900"
|
|
>
|
|
<!-- Header -->
|
|
<div class="bg-gradient-to-r from-amber-500 to-amber-600 p-4 flex items-center justify-between">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-2 h-2 bg-white rounded-full animate-pulse"></div>
|
|
<span class="text-white font-semibold">RADIO</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span x-text="listenerCount" class="text-white/80 text-sm">--</span>
|
|
<span class="text-white/60 text-xs">luisteraars</span>
|
|
<button @click="toggleExpand()" class="text-white/80 hover:text-white">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="p-4 text-white">
|
|
<!-- DJ Info -->
|
|
<div x-show="currentDJ" class="flex items-center gap-4 mb-4">
|
|
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-amber-400 to-amber-600 flex items-center justify-center overflow-hidden">
|
|
<img x-bind:src="djAvatar" x-bind:alt="djName" class="w-full h-full object-cover">
|
|
</div>
|
|
<div>
|
|
<p class="text-xs text-amber-400">PRESENTATOR</p>
|
|
<p x-text="djName" class="font-semibold">--</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Now Playing -->
|
|
<div class="bg-gray-800 rounded-lg p-3 mb-4">
|
|
<p class="text-xs text-gray-400 mb-1">NU DRAAIT</p>
|
|
<p x-text="trackTitle" class="font-medium truncate">Radio</p>
|
|
<p x-show="trackArtist" x-text="trackArtist" class="text-sm text-gray-400 truncate"></p>
|
|
</div>
|
|
|
|
<!-- Controls -->
|
|
<div class="flex items-center justify-between gap-4">
|
|
<button @click="togglePlay()" class="w-14 h-14 rounded-full bg-amber-500 hover:bg-amber-400 flex items-center justify-center transition shadow-lg">
|
|
<svg x-show="!isPlaying" class="w-6 h-6 ml-1" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M8 5v14l11-7z"/>
|
|
</svg>
|
|
<svg x-show="isPlaying" class="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
|
|
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
|
|
</svg>
|
|
</button>
|
|
|
|
<div class="flex-1 flex items-center gap-2">
|
|
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072M18.364 5.636a9 9 0 010 12.728"/>
|
|
</svg>
|
|
<input type="range" x-model="volume" min="0" max="100" class="flex-1 h-1 bg-gray-700 rounded-lg appearance-none cursor-pointer">
|
|
</div>
|
|
|
|
<a href="/community/radio" class="text-amber-400 hover:text-amber-300">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
|
|
<audio x-ref="audioPlayer" preload="none">
|
|
<source x-bind:src="streamUrl" type="audio/mpeg">
|
|
</audio>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function radioPlayer() {
|
|
return {
|
|
showWidget: false,
|
|
showOnRadioPage: false,
|
|
showGlobal: false,
|
|
isVisible: true,
|
|
isExpanded: false,
|
|
isPlaying: false,
|
|
streamUrl: '',
|
|
volume: 80,
|
|
listenerCount: '--',
|
|
trackTitle: 'Radio',
|
|
trackArtist: '',
|
|
currentDJ: null,
|
|
djName: '--',
|
|
djAvatar: '',
|
|
|
|
initPlayer() {
|
|
this.checkVisibility();
|
|
this.loadSettings();
|
|
setInterval(() => this.updateListeners(), 30000);
|
|
setInterval(() => this.updateNowPlaying(), 15000);
|
|
this.updateVisibilityByUrl();
|
|
},
|
|
|
|
checkVisibility() {
|
|
if (!this.showWidget) {
|
|
this.showWidget = false;
|
|
return;
|
|
}
|
|
if (this.showGlobal) {
|
|
this.showWidget = true;
|
|
} else if (this.showOnRadioPage) {
|
|
this.updateVisibilityByUrl();
|
|
} else {
|
|
this.showWidget = false;
|
|
}
|
|
},
|
|
|
|
updateVisibilityByUrl() {
|
|
const path = window.location.pathname;
|
|
this.showWidget = path === '/community/radio' || path.startsWith('/community/radio');
|
|
},
|
|
|
|
loadSettings() {
|
|
fetch('/api/radio/config')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if (data.enabled && data.stream_url && data.widget_enabled) {
|
|
this.streamUrl = data.streamUrl || data.stream_url;
|
|
this.showGlobal = data.widget_show_globally || false;
|
|
this.checkVisibility();
|
|
} else {
|
|
this.showWidget = false;
|
|
}
|
|
})
|
|
.catch(() => {
|
|
this.showWidget = false;
|
|
});
|
|
},
|
|
|
|
toggleExpand() {
|
|
this.isExpanded = !this.isExpanded;
|
|
},
|
|
|
|
togglePlay() {
|
|
const audio = this.$refs.audioPlayer;
|
|
if (this.isPlaying) {
|
|
audio.pause();
|
|
this.isPlaying = false;
|
|
} else {
|
|
audio.play().catch(() => {});
|
|
this.isPlaying = true;
|
|
}
|
|
},
|
|
|
|
updateListeners() {
|
|
fetch('/api/radio/listeners')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
this.listenerCount = data.count.toLocaleString();
|
|
})
|
|
.catch(() => {
|
|
this.listenerCount = '--';
|
|
});
|
|
},
|
|
|
|
updateNowPlaying() {
|
|
fetch('/api/radio/now-playing')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
if (data.title) {
|
|
this.trackTitle = data.title;
|
|
this.trackArtist = data.artist || '';
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
}
|
|
}
|
|
}
|
|
</script>
|