improvements

This commit is contained in:
Julien Maille 2025-12-26 23:14:47 +01:00
parent d296652995
commit aeea0038f3
6 changed files with 39 additions and 8 deletions

View file

@ -32,7 +32,10 @@
<div id="queue-modal">
<div id="queue-modal-header">
<h3>Queue</h3>
<button id="close-queue-btn">&times;</button>
<div style="display: flex; gap: 0.5rem; align-items: center;">
<button id="clear-queue-btn" class="btn-secondary">Clear All</button>
<button id="close-queue-btn">&times;</button>
</div>
</div>
<div id="queue-list"></div>
</div>

View file

@ -250,9 +250,14 @@ function initializeSmoothSliders(audioPlayer, player) {
progressBar.addEventListener('click', e => {
if (!isSeeking) {
seek(progressBar, e, position => {
if (!isNaN(audioPlayer.duration)) {
if (!isNaN(audioPlayer.duration) && audioPlayer.duration > 0 && audioPlayer.duration !== Infinity) {
audioPlayer.currentTime = position * audioPlayer.duration;
player.updateMediaSessionPositionState();
} else if (player.currentTrack && player.currentTrack.duration) {
const targetTime = position * player.currentTrack.duration;
const progressFill = document.querySelector('.progress-fill');
if (progressFill) progressFill.style.width = `${position * 100}%`;
player.playTrackFromQueue(targetTime);
}
});
}
@ -310,7 +315,7 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
// Update all instances of this item's like button on the page
const id = type === 'playlist' ? item.uuid : item.id;
const selector = type === 'track'
? `.track-item[data-track-id="${id}"] .like-btn`
? `[data-track-id="${id}"] .like-btn`
: `.card[data-${type}-id="${id}"] .like-btn, .card[data-playlist-id="${id}"] .like-btn`;
// Also check header buttons

View file

@ -52,6 +52,8 @@ export class Player {
if (coverEl) coverEl.src = this.api.getCoverUrl(track.album?.cover, '1280');
if (titleEl) titleEl.textContent = trackTitle;
if (artistEl) artistEl.textContent = trackArtists;
const totalDurationEl = document.getElementById('total-duration');
if (totalDurationEl) totalDurationEl.textContent = formatTime(track.duration);
document.title = `${trackTitle}${track.artist?.name || 'Unknown'}`;
this.updatePlayingTrackIndicator();
@ -154,7 +156,7 @@ export class Player {
}
}
async playTrackFromQueue() {
async playTrackFromQueue(startTime = 0) {
const currentQueue = this.shuffleActive ? this.shuffledQueue : this.queue;
if (this.currentQueueIndex < 0 || this.currentQueueIndex >= currentQueue.length) {
return;
@ -193,6 +195,9 @@ export class Player {
}
this.audio.src = streamUrl;
if (startTime > 0) {
this.audio.currentTime = startTime;
}
await this.audio.play();
this.updateMediaSessionPlaybackState();

View file

@ -1,5 +1,5 @@
//js/ui-interactions.js
import { SVG_CLOSE, formatTime, trackDataStore, getTrackTitle, getTrackArtists } from './utils.js';
import { SVG_CLOSE, SVG_BIN, formatTime, trackDataStore, getTrackTitle, getTrackArtists } from './utils.js';
export function initializeUIInteractions(player, api) {
const sidebar = document.querySelector('.sidebar');
@ -8,6 +8,7 @@ export function initializeUIInteractions(player, api) {
const queueBtn = document.getElementById('queue-btn');
const queueModalOverlay = document.getElementById('queue-modal-overlay');
const closeQueueBtn = document.getElementById('close-queue-btn');
const clearQueueBtn = document.getElementById('clear-queue-btn');
const queueList = document.getElementById('queue-list');
let draggedQueueIndex = null;
@ -40,6 +41,13 @@ export function initializeUIInteractions(player, api) {
closeQueueBtn.addEventListener('click', () => {
queueModalOverlay.style.display = 'none';
});
if (clearQueueBtn) {
clearQueueBtn.addEventListener('click', () => {
player.clearQueue();
renderQueue();
});
}
queueModalOverlay.addEventListener('click', e => {
if (e.target === queueModalOverlay) {
@ -50,6 +58,10 @@ export function initializeUIInteractions(player, api) {
function renderQueue() {
const currentQueue = player.getCurrentQueue();
if (clearQueueBtn) {
clearQueueBtn.style.display = currentQueue.length > 0 ? 'block' : 'none';
}
if (currentQueue.length === 0) {
queueList.innerHTML = '<div class="placeholder-text">Queue is empty.</div>';
return;
@ -78,7 +90,7 @@ export function initializeUIInteractions(player, api) {
</div>
<div class="track-item-duration">${formatTime(track.duration)}</div>
<button class="queue-remove-btn" data-track-index="${index}" title="Remove from queue">
${SVG_CLOSE}
${SVG_BIN}
</button>
</div>
`;

View file

@ -34,6 +34,7 @@ export const SVG_DOWNLOAD = '<svg xmlns="http://www.w3.org/2000/svg" width="24"
export const SVG_MENU = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="1"></circle><circle cx="12" cy="5" r="1"></circle><circle cx="12" cy="19" r="1"></circle></svg>';
export const SVG_HEART = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="heart-icon"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>';
export const SVG_CLOSE = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
export const SVG_BIN = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>';
export const formatTime = (seconds) => {
if (isNaN(seconds)) return '0:00';

View file

@ -1520,7 +1520,7 @@ input:checked + .slider::before {
margin: 0;
}
#queue-modal-header button {
#queue-modal-header #close-queue-btn {
background: transparent;
border: none;
color: var(--muted-foreground);
@ -1535,7 +1535,12 @@ input:checked + .slider::before {
transition: all var(--transition);
}
#queue-modal-header button:hover {
#queue-modal-header #clear-queue-btn {
background-color: transparent;
}
#queue-modal-header #clear-queue-btn:hover,
#queue-modal-header #close-queue-btn:hover {
background-color: var(--secondary);
color: var(--foreground);
}