asteroid/template/player-content.ctml

229 lines
8.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<title data-text="title">Asteroid Radio - Web Player</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/asteroid/static/asteroid.css">
<script src="/asteroid/static/js/auth-ui.js"></script>
<script>
// Simple Now Playing updater
function updateNowPlaying() {
fetch('/api/asteroid/partial/now-playing')
.then(response => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('text/html')) {
return response.text();
}
return '';
})
.then(data => {
const nowPlayingDiv = document.getElementById('now-playing');
if (nowPlayingDiv) {
nowPlayingDiv.innerHTML = data;
}
})
.catch(error => console.log('Could not fetch now playing:', error));
}
// Update on load and every 10 seconds
document.addEventListener('DOMContentLoaded', function() {
setTimeout(updateNowPlaying, 200);
setInterval(updateNowPlaying, 10000);
});
</script>
<script>
// Handle logout without navigation
function handleLogout() {
fetch('/asteroid/logout', {
method: 'GET',
redirect: 'manual'
})
.then(() => {
// Reload the current page content to show logged-out state
fetch(window.location.href)
.then(response => response.text())
.then(html => {
document.open();
document.write(html);
document.close();
});
})
.catch(error => {
console.error('Logout failed:', error);
});
}
// Load content via AJAX to prevent audio interruption
function loadInFrame(link) {
const url = link.href;
console.log('Loading via AJAX:', url);
// Clear all intervals to prevent old page scripts from running
const highestId = window.setTimeout(() => {}, 0);
for (let i = 0; i < highestId; i++) {
window.clearInterval(i);
window.clearTimeout(i);
}
fetch(url)
.then(response => response.text())
.then(html => {
// Replace entire document content
document.open();
document.write(html);
document.close();
// Execute scripts in the new content
const scripts = document.querySelectorAll('script');
scripts.forEach(oldScript => {
const newScript = document.createElement('script');
if (oldScript.src) {
newScript.src = oldScript.src;
} else {
newScript.textContent = oldScript.textContent;
}
oldScript.parentNode.replaceChild(newScript, oldScript);
});
// Re-initialize spectrum analyzer after navigation
if (window.initializeSpectrumAnalyzer) {
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
}
// Update browser history
if (window.history && window.history.pushState) {
window.history.pushState({}, '', url);
}
})
.catch(error => {
console.error('Failed to load content:', error);
// Fallback to normal navigation
return true;
});
// Prevent default navigation
return false;
}
</script>
</head>
<body>
<div class="container">
<h1 style="display: flex; align-items: center; justify-content: center; gap: 15px;">
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
<span>WEB PLAYER</span>
<img src="/asteroid/static/asteroid.png" alt="Asteroid" style="height: 50px; width: auto;">
</h1>
<nav class="nav">
<a href="/asteroid/content" target="content-frame" onclick="return loadInFrame(this)">Home</a>
<a href="/asteroid/profile-content" target="content-frame" data-show-if-logged-in onclick="return loadInFrame(this)">Profile</a>
<a href="/asteroid/admin-content" target="content-frame" data-show-if-admin onclick="return loadInFrame(this)">Admin</a>
<a href="/asteroid/login-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Login</a>
<a href="/asteroid/register-content" target="content-frame" data-show-if-logged-out onclick="return loadInFrame(this)">Register</a>
<a href="/asteroid/logout" data-show-if-logged-in class="btn-logout" onclick="handleLogout(); return false;">Logout</a>
</nav>
</div>
<!-- Live Stream Section - Note about persistent player -->
<div class="player-section">
<h2 style="color: #00ff00;">
<span class="live-stream-indicator" style="font-size: 1rem;">🟢 </span>
Live Radio Stream
</h2>
<p><em>The live stream player is now in the persistent bar at the bottom of the page. It will continue playing as you navigate between pages!</em></p>
</div>
<div id="now-playing" class="now-playing"></div>
<!-- Track Browser -->
<div class="player-section">
<h2>Personal Track Library</h2>
<div class="track-browser">
<input type="text" id="search-tracks" placeholder="Search tracks..." class="search-input">
<select id="library-tracks-per-page" class="sort-select" onchange="changeLibraryTracksPerPage()" style="margin: 10px 0px;">
<option value="10">10 per page</option>
<option value="20" selected>20 per page</option>
<option value="50">50 per page</option>
</select>
<div id="track-list" class="track-list">
<div class="loading">Loading tracks...</div>
</div>
<!-- Pagination Controls -->
<div id="library-pagination-controls" style="display: none; margin-top: 20px; text-align: center;">
<button onclick="libraryGoToPage(1)" class="btn btn-secondary">« First</button>
<button onclick="libraryPreviousPage()" class="btn btn-secondary"> Prev</button>
<span id="library-page-info" style="margin: 0 15px; font-weight: bold;">Page 1 of 1</span>
<button onclick="libraryNextPage()" class="btn btn-secondary">Next </button>
<button onclick="libraryGoToLastPage()" class="btn btn-secondary">Last »</button>
</div>
</div>
</div>
<!-- Audio Player Widget -->
<div class="player-section">
<h2>Audio Player</h2>
<div class="audio-player">
<div class="now-playing">
<div class="track-art">🎵</div>
<div class="track-details">
<div class="track-title" id="current-title">No track selected</div>
<div class="track-artist" id="current-artist">Unknown Artist</div>
<div class="track-album" id="current-album">Unknown Album</div>
</div>
</div>
<audio id="audio-player" controls preload="none" style="width: 100%; margin: 20px 0; display: none;">
Your browser does not support the audio element.
</audio>
<div class="player-controls">
<button id="prev-btn" class="btn btn-secondary">⏮️ Previous</button>
<button id="play-pause-btn" class="btn btn-primary">▶️ Play</button>
<button id="next-btn" class="btn btn-secondary">⏭️ Next</button>
<button id="shuffle-btn" class="btn btn-info">🔀 Shuffle</button>
<button id="repeat-btn" class="btn btn-warning">🔁 Repeat</button>
</div>
<div class="player-info">
<div class="time-display">
<span id="current-time">0:00</span> / <span id="total-time">0:00</span>
</div>
<div class="volume-control">
<label for="volume-slider">🔊</label>
<input type="range" id="volume-slider" min="0" max="100" value="50" class="volume-slider">
</div>
</div>
</div>
</div>
<!-- Playlist Management -->
<div class="player-section">
<h2>Playlists</h2>
<div class="playlist-controls">
<input type="text" id="new-playlist-name" placeholder="New playlist name..." class="playlist-input">
<button id="create-playlist" class="btn btn-success"> Create Playlist</button>
</div>
<div class="playlist-list">
<div id="playlists-container">
<div class="no-playlists">No playlists created yet.</div>
</div>
</div>
</div>
<!-- Queue -->
<div class="player-section">
<h2>Play Queue</h2>
<div class="queue-controls">
<button id="clear-queue" class="btn btn-danger">🗑️ Clear Queue</button>
<button id="save-queue" class="btn btn-info">💾 Save as Playlist</button>
</div>
<div id="play-queue" class="play-queue">
<div class="empty-queue">Queue is empty</div>
</div>
</div>
</div>
</body>
</html>