This commit is contained in:
@@ -88,6 +88,7 @@ els('.room').forEach((node) => {
|
||||
cover: el('[data-role="cover"]', node),
|
||||
song: el('[data-role="song"]', node),
|
||||
artist: el('[data-role="artist"]', node),
|
||||
progress: el('[data-role="progress"]', node),
|
||||
steps: els('.step', node),
|
||||
volume: null,
|
||||
playState: null,
|
||||
@@ -131,6 +132,7 @@ function paintRoom(room) {
|
||||
room.steps.forEach((button) => { button.disabled = !room.available; });
|
||||
paintTrack(room);
|
||||
const playing = room.playState === 'play';
|
||||
room.node.classList.toggle('playing', playing);
|
||||
room.play.classList.toggle('playing', playing);
|
||||
room.play.disabled = !room.available || room.playState === null;
|
||||
room.play.setAttribute(
|
||||
@@ -183,6 +185,22 @@ function renderTrack(track, refs) {
|
||||
|
||||
function paintTrack(room) {
|
||||
renderTrack(room.available ? room.track : null, room);
|
||||
paintProgress(room);
|
||||
}
|
||||
|
||||
/* The discreet cursor on the line below the song, sized off the same
|
||||
{position_ms, duration_ms} the poll hands back -- absent for anything
|
||||
HEOS never sends a progress event for (an AVR input, an internet radio
|
||||
stream with no fixed length), in which case the line stays plain. */
|
||||
function paintProgress(room) {
|
||||
const track = room.available ? room.track : null;
|
||||
room.progress.hidden = !track;
|
||||
if (!track) return;
|
||||
const { position_ms: position, duration_ms: duration } = track;
|
||||
const known = typeof duration === 'number' && duration > 0 && typeof position === 'number';
|
||||
const percent = known ? Math.min(100, Math.max(0, (position / duration) * 100)) : 0;
|
||||
room.progress.classList.toggle('known', known);
|
||||
room.progress.style.setProperty('--progress', percent);
|
||||
}
|
||||
|
||||
/* A merged room moves into the host's card, because that is what merging
|
||||
|
||||
+35
-5
@@ -83,6 +83,13 @@ svg { width: 22px; height: 22px; fill: currentColor; }
|
||||
gap: 14px;
|
||||
}
|
||||
.card.offline { opacity: .5; }
|
||||
/* A tint, not a repaint -- it should read at a glance without competing
|
||||
with the song title right above it. */
|
||||
.card.room.playing {
|
||||
background: linear-gradient(135deg,
|
||||
color-mix(in srgb, var(--live) 18%, var(--card)) 0%,
|
||||
var(--card) 70%);
|
||||
}
|
||||
|
||||
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
||||
.card-head h2 {
|
||||
@@ -99,12 +106,8 @@ svg { width: 22px; height: 22px; fill: currentColor; }
|
||||
.pill.on { color: var(--live); }
|
||||
|
||||
/* --- now playing, between the room's name and its volume --------------- */
|
||||
/* The padding matches the card's gap, so the line sits halfway between the
|
||||
song and the volume. It goes with the block, when nothing is playing. */
|
||||
.now-playing {
|
||||
display: flex; align-items: center; gap: 16px; min-width: 0;
|
||||
padding-bottom: 14px;
|
||||
border-bottom: 1px solid var(--edge);
|
||||
}
|
||||
.cover {
|
||||
flex: 0 0 auto;
|
||||
@@ -118,6 +121,27 @@ svg { width: 22px; height: 22px; fill: currentColor; }
|
||||
.song { font-size: 20px; font-weight: 550; }
|
||||
.artist { font-size: 17px; color: var(--muted); }
|
||||
|
||||
/* Doubles as the line between the song and the volume -- it goes with the
|
||||
block, when nothing is playing. Muted throughout, so it never competes
|
||||
with the volume meter below it; the cursor only shows once a position is
|
||||
actually known (an AVR input or a stream with no duration never gets one). */
|
||||
.progress { position: relative; height: 3px; border-radius: 999px; background: #0c111b; }
|
||||
.progress-fill {
|
||||
display: block; height: 100%; width: calc(var(--progress, 0) * 1%);
|
||||
border-radius: 999px; background: var(--muted);
|
||||
transition: width .12s ease-out;
|
||||
}
|
||||
.progress-cursor {
|
||||
display: none;
|
||||
position: absolute; top: 50%;
|
||||
left: calc(var(--progress, 0) * 1%);
|
||||
width: 7px; height: 7px; margin-left: -3.5px;
|
||||
border-radius: 50%; background: var(--muted);
|
||||
transform: translateY(-50%);
|
||||
transition: left .12s ease-out;
|
||||
}
|
||||
.progress.known .progress-cursor { display: block; }
|
||||
|
||||
/* --- volume ---------------------------------------------------------- */
|
||||
.volume { display: flex; align-items: center; gap: 14px; }
|
||||
|
||||
@@ -241,8 +265,14 @@ svg { width: 22px; height: 22px; fill: currentColor; }
|
||||
one around every room in it. */
|
||||
.joined .card.room { background: none; border: 0; border-radius: 0; padding: 0; gap: 12px; }
|
||||
.joined .card.room + .card.room { border-top: 1px solid var(--edge); padding-top: 14px; }
|
||||
/* Flush against the group's own card, so no radius here -- .playing has
|
||||
to out-specificity the plain "background: none" above to show at all. */
|
||||
.joined .card.room.playing {
|
||||
background: linear-gradient(135deg,
|
||||
color-mix(in srgb, var(--live) 18%, transparent) 0%,
|
||||
transparent 70%);
|
||||
}
|
||||
.joined .card-head h2 { font-size: 15px; font-weight: 550; color: var(--muted); }
|
||||
.joined .now-playing { padding-bottom: 12px; }
|
||||
.joined .cover { width: 52px; height: 52px; border-radius: 10px; }
|
||||
.joined .song { font-size: 18px; }
|
||||
.joined .step { height: 54px; }
|
||||
|
||||
Reference in New Issue
Block a user