Player: 'Play next' action + accent-correct queue buttons
- Added playNext(track): inserts a track right after the current one (Spotify 'Play next'), vs addToQueue which appends to the end. Falls back to addToQueue when nothing is playing. - Artist-detail track rows now show BOTH a Play-next (⇥) and Add-to-queue (+) button; the delegated handler builds one shared library-track payload and routes to playNext / addToQueue. (Add-to-queue was already wired; play-next + the second button are new.) - Fixed the queue button's hardcoded 29,185,84 to var(--accent-rgb) so it follows the settings accent (kettui UI-consistency), and styled the new play-next button to match. Note: deliberately NOT adding queue buttons to SEARCH results — those are stream/download (non-library) tracks the queue's auto-advance can't reliably play. JS syntax clean on both files.
This commit is contained in:
parent
65f49ccecd
commit
1e514693f1
3 changed files with 39 additions and 12 deletions
|
|
@ -4085,6 +4085,13 @@ function _buildTrackRow(track, album, admin) {
|
|||
const queueTd = document.createElement('td');
|
||||
queueTd.className = 'col-queue';
|
||||
if (!track._missingExpected && track.file_path) {
|
||||
const playNextBtn = document.createElement('button');
|
||||
playNextBtn.className = 'enhanced-playnext-btn';
|
||||
// Play-next glyph (queue-with-arrow feel)
|
||||
playNextBtn.innerHTML = '⇥'; // ⇥
|
||||
playNextBtn.title = 'Play next';
|
||||
queueTd.appendChild(playNextBtn);
|
||||
|
||||
const queueBtn = document.createElement('button');
|
||||
queueBtn.className = 'enhanced-queue-btn';
|
||||
queueBtn.innerHTML = '+';
|
||||
|
|
@ -4270,8 +4277,10 @@ function _attachTableDelegation(table, album) {
|
|||
}
|
||||
}
|
||||
|
||||
// Queue button
|
||||
if (target.closest('.enhanced-queue-btn')) {
|
||||
// Queue / Play-next buttons (share the same track payload)
|
||||
const isQueueBtn = target.closest('.enhanced-queue-btn');
|
||||
const isPlayNextBtn = target.closest('.enhanced-playnext-btn');
|
||||
if (isQueueBtn || isPlayNextBtn) {
|
||||
e.stopPropagation();
|
||||
if (track.file_path) {
|
||||
const artistName = artistDetailPageState.enhancedData ? artistDetailPageState.enhancedData.artist.name : '';
|
||||
|
|
@ -4279,7 +4288,7 @@ function _attachTableDelegation(table, album) {
|
|||
if (!albumArt && artistDetailPageState.enhancedData) {
|
||||
albumArt = artistDetailPageState.enhancedData.artist?.thumb_url;
|
||||
}
|
||||
addToQueue({
|
||||
const payload = {
|
||||
title: track.title || 'Unknown Track',
|
||||
artist: artistName || 'Unknown Artist',
|
||||
album: album.title || 'Unknown Album',
|
||||
|
|
@ -4292,7 +4301,9 @@ function _attachTableDelegation(table, album) {
|
|||
album_id: album.id,
|
||||
bitrate: track.bitrate,
|
||||
sample_rate: track.sample_rate
|
||||
});
|
||||
};
|
||||
if (isPlayNextBtn && typeof playNext === 'function') playNext(payload);
|
||||
else addToQueue(payload);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2104,6 +2104,19 @@ function addToQueue(track) {
|
|||
}
|
||||
}
|
||||
|
||||
// Insert a track to play right after the current one (Spotify "Play next").
|
||||
function playNext(track) {
|
||||
if (npQueue.length === 0 || npQueueIndex < 0) {
|
||||
// Nothing queued / playing — same as add-to-queue (which auto-plays).
|
||||
addToQueue(track);
|
||||
return;
|
||||
}
|
||||
npQueue.splice(npQueueIndex + 1, 0, track);
|
||||
showToast('Playing next', 'success');
|
||||
renderNpQueue();
|
||||
updateNpPrevNextButtons();
|
||||
}
|
||||
|
||||
function removeFromQueue(index) {
|
||||
if (index < 0 || index >= npQueue.length) return;
|
||||
const wasCurrentTrack = (index === npQueueIndex);
|
||||
|
|
|
|||
|
|
@ -48808,26 +48808,29 @@ textarea.enhanced-meta-field-input {
|
|||
width: 36px;
|
||||
text-align: center;
|
||||
}
|
||||
.enhanced-queue-btn {
|
||||
.enhanced-queue-btn,
|
||||
.enhanced-playnext-btn {
|
||||
background: none;
|
||||
border: 1px solid rgba(29, 185, 84, 0.2);
|
||||
color: rgba(29, 185, 84, 0.5);
|
||||
border: 1px solid rgba(var(--accent-rgb), 0.2);
|
||||
color: rgba(var(--accent-rgb), 0.5);
|
||||
border-radius: 50%;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s ease;
|
||||
padding: 0;
|
||||
margin: 0 2px;
|
||||
}
|
||||
.enhanced-queue-btn:hover {
|
||||
background: rgba(29, 185, 84, 0.12);
|
||||
color: rgba(29, 185, 84, 0.9);
|
||||
border-color: rgba(29, 185, 84, 0.4);
|
||||
.enhanced-queue-btn:hover,
|
||||
.enhanced-playnext-btn:hover {
|
||||
background: rgba(var(--accent-rgb), 0.12);
|
||||
color: rgba(var(--accent-rgb), 0.9);
|
||||
border-color: rgba(var(--accent-rgb), 0.4);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue