feat: show last played songs in web ui

This commit is contained in:
Felipe M 2025-05-13 12:49:59 +02:00
parent 7f16452a99
commit bcc1bce743
Signed by: fmartingr
GPG key ID: CCFBC5637D4000A8
6 changed files with 206 additions and 7 deletions

View file

@ -149,9 +149,10 @@ func (s *Server) handleStatic(w http.ResponseWriter, r *http.Request) {
// StatusResponse contains the jukebox status
type StatusResponse struct {
IsPlaying bool `json:"isPlaying"`
CurrentSong *subsonic.Song `json:"currentSong"`
UpdateTime string `json:"updateTime"`
IsPlaying bool `json:"isPlaying"`
CurrentSong *subsonic.Song `json:"currentSong"`
SongHistory []*subsonic.Song `json:"songHistory"`
UpdateTime string `json:"updateTime"`
}
// handleStatus returns the current jukebox status as JSON
@ -165,11 +166,13 @@ func (s *Server) handleStatus(w http.ResponseWriter, r *http.Request) {
// getStatus returns the current status
func (s *Server) getStatus() StatusResponse {
currentSong := s.jukebox.GetCurrentSong()
songHistory := s.jukebox.GetSongHistory()
isPlaying := s.bot.IsPlaying()
return StatusResponse{
IsPlaying: isPlaying,
CurrentSong: currentSong,
SongHistory: songHistory,
UpdateTime: time.Now().Format(time.RFC3339),
}
}

View file

@ -5,6 +5,8 @@ const statusText = document.getElementById('status-text');
const nowPlaying = document.getElementById('now-playing');
const notPlaying = document.getElementById('not-playing');
const lastUpdate = document.getElementById('last-update');
const songHistory = document.getElementById('song-history');
const historyList = document.getElementById('history-list');
// Song info elements
const coverArt = document.getElementById('cover-art');
@ -75,6 +77,15 @@ function updateUI(data) {
updateSongInfo(data.currentSong);
}
// Update song history if available
if (data.songHistory && data.songHistory.length > 0) {
updateSongHistory(data.songHistory, data.currentSong);
songHistory.classList.remove('hidden');
} else {
// No history available
songHistory.classList.add('hidden');
}
// Update last update time
if (data.updateTime) {
const updateDate = new Date(data.updateTime);
@ -122,4 +133,67 @@ function updateSongInfo(song) {
function formatDate(date) {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
}
// Update the song history list
function updateSongHistory(songs, currentSong) {
// Clear the current list
historyList.innerHTML = '';
// Show history even when nothing is playing
// Start from the first song
const startIndex = 0;
// If no songs are available after filtering current one, show a message
if (songs.length === 0) {
const li = document.createElement('li');
li.className = 'history-item history-empty';
li.textContent = 'No song history available yet';
historyList.appendChild(li);
return;
}
// Add each song to the history list
for (let i = startIndex; i < songs.length; i++) {
const song = songs[i];
if (!song) continue;
// Skip if this song is the same as the currently playing song
if (currentSong && song.id === currentSong.id) continue;
const li = document.createElement('li');
li.className = 'history-item';
// Create cover art
const img = document.createElement('img');
if (song.coverArt) {
img.src = `/cover/${song.coverArt}`;
} else {
img.src = DEFAULT_COVER_ART;
}
img.alt = 'Cover';
img.className = 'history-cover';
// Create song details
const details = document.createElement('div');
details.className = 'history-details';
const title = document.createElement('div');
title.className = 'history-title';
title.textContent = song.title || 'Unknown Title';
const artist = document.createElement('div');
artist.className = 'history-artist';
artist.textContent = song.artist || 'Unknown Artist';
// Assemble the elements
details.appendChild(title);
details.appendChild(artist);
li.appendChild(img);
li.appendChild(details);
historyList.appendChild(li);
}
}

View file

@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Discord Jukebox Status</title>
<link rel="stylesheet" href="/static/styles.css">
<meta http-equiv="refresh" content="900"> <!-- Refresh page every 15 minutes to prevent memory issues -->
</head>
<body>
<div class="container">
@ -35,6 +36,15 @@
</div>
</div>
<div id="song-history" class="hidden">
<h2>Recently Played</h2>
<div class="history-container">
<ul id="history-list" class="history-list">
<!-- Song history will be populated here by JavaScript -->
</ul>
</div>
</div>
<div id="not-playing" class="hidden">
<div class="message">
<h2>No Song Playing</h2>

View file

@ -128,6 +128,65 @@ h3 {
margin-right: 15px;
}
/* Song History Section */
#song-history {
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
margin-top: 20px;
margin-bottom: 20px;
}
.history-container {
max-height: 300px;
overflow-y: auto;
}
.history-list {
list-style-type: none;
padding: 0;
margin: 0;
}
.history-empty {
text-align: center;
color: #666;
font-style: italic;
padding: 20px 0;
}
.history-item {
padding: 10px;
margin-bottom: 10px;
background-color: white;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
}
.history-cover {
width: 50px;
height: 50px;
border-radius: 4px;
margin-right: 15px;
object-fit: cover;
}
.history-details {
flex: 1;
}
.history-title {
font-weight: bold;
margin-bottom: 3px;
}
.history-artist {
color: #666;
font-size: 0.9em;
}
/* Not Playing Section */
#not-playing {
text-align: center;
@ -190,4 +249,18 @@ footer {
#cover-art {
max-width: 150px;
}
.history-item {
padding: 8px;
}
.history-cover {
width: 40px;
height: 40px;
margin-right: 10px;
}
.history-title, .history-artist {
font-size: 0.9em;
}
}