Group media behaviour
Deploy HEOS panel / deploy (push) Successful in 27s

This commit is contained in:
franzz committed 2026-09-19 01:41:49 +02:00
1 parent d4959b4ac3
commit 14d7b91bd4
3 files changed
+34 -19

No files matched your search

+4 -4
View File
@@ -60,6 +60,7 @@ const ui = {
options: el('[data-role="options"]'), options: el('[data-role="options"]'),
avr: el('.card.avr'), avr: el('.card.avr'),
joined: el('[data-role="joined"]'), joined: el('[data-role="joined"]'),
avrMedia: el('[data-role="avr-media"]'),
avrNowPlaying: el('[data-role="avr-now-playing"]'), avrNowPlaying: el('[data-role="avr-now-playing"]'),
avrCover: el('[data-role="avr-cover"]'), avrCover: el('[data-role="avr-cover"]'),
avrSong: el('[data-role="avr-song"]'), avrSong: el('[data-role="avr-song"]'),
@@ -72,6 +73,7 @@ const ui = {
// into the AVR (a Zidoo, say) is "now playing" the same way a room's own // into the AVR (a Zidoo, say) is "now playing" the same way a room's own
// stream is. // stream is.
const avrTrack = { const avrTrack = {
media: ui.avrMedia,
nowPlaying: ui.avrNowPlaying, nowPlaying: ui.avrNowPlaying,
cover: ui.avrCover, cover: ui.avrCover,
song: ui.avrSong, song: ui.avrSong,
@@ -132,7 +134,7 @@ els('.room').forEach((node) => {
play: el('[data-role="play"]', node), play: el('[data-role="play"]', node),
next: el('[data-role="next"]', node), next: el('[data-role="next"]', node),
sources: el('.sources', node), // the resume buttons and the host toggle sources: el('.sources', node), // the resume buttons and the host toggle
nowPlaying: el('[data-role="now-playing"]', node), media: el('[data-role="media"]', node),
cover: el('[data-role="cover"]', node), cover: el('[data-role="cover"]', node),
song: el('[data-role="song"]', node), song: el('[data-role="song"]', node),
artist: el('[data-role="artist"]', node), artist: el('[data-role="artist"]', node),
@@ -233,7 +235,7 @@ function paintRoom(room) {
it flicker. */ it flicker. */
function renderTrack(track, refs) { function renderTrack(track, refs) {
renderProgress(track, refs); renderProgress(track, refs);
refs.nowPlaying.hidden = !track; refs.media.hidden = !track;
if (!track) return; if (!track) return;
refs.song.textContent = track.song; refs.song.textContent = track.song;
refs.artist.textContent = track.artist || ''; refs.artist.textContent = track.artist || '';
@@ -257,8 +259,6 @@ function renderTrack(track, refs) {
here -- a poll, a drag, or a seek landing -- corrects it and moves the here -- a poll, a drag, or a seek landing -- corrects it and moves the
mark again. */ mark again. */
function renderProgress(track, refs) { function renderProgress(track, refs) {
const { progress } = refs;
progress.hidden = !track;
refs.shown = null; refs.shown = null;
refs.tick = null; refs.tick = null;
if (!track) return; if (!track) return;
+19 -7
View File
@@ -11,11 +11,14 @@
--ink-bright: #fff; --ink-bright: #fff;
--ink-bright-muted: rgba(255, 255, 255, .8); --ink-bright-muted: rgba(255, 255, 255, .8);
--live: #3ddc97; --live: #3ddc97;
--media: #1a3333;
--muted: #8d98ad; --muted: #8d98ad;
--radius: 22px; --radius-lg: 16px;
--radius-xl: 22px;
--raised: #29334a; --raised: #29334a;
--scrim: rgba(4, 6, 11, .6); --scrim: rgba(4, 6, 11, .6);
--shadow: rgba(0, 0, 0, .45); --shadow: rgba(0, 0, 0, .45);
--shade: rgba(255, 255, 255, .05);
/* spacing scale for every gap/padding/margin in the sheet, smallest to /* spacing scale for every gap/padding/margin in the sheet, smallest to
largest: 2xs 4px, sm 8px, md 12px, gutter 16px, lg 24px. */ largest: 2xs 4px, sm 8px, md 12px, gutter 16px, lg 24px. */
--space-xs: 4px; --space-xs: 4px;
@@ -89,7 +92,7 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.card { .card {
background: var(--card); background: var(--card);
border: 1px solid var(--edge); border: 1px solid var(--edge);
border-radius: var(--radius); border-radius: var(--radius-xl);
padding: var(--space-md); padding: var(--space-md);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -116,6 +119,15 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.card-head h2 .room-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .card-head h2 .room-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* --- now playing, between the room's name and its volume --------------- */ /* --- now playing, between the room's name and its volume --------------- */
.media {
background: var(--shade);
border-radius: var(--radius-lg);
padding: var(--space-md);
display: flex;
row-gap: var(--space-md);
flex-direction: column;
}
.now-playing { .now-playing {
display: flex; align-items: center; gap: var(--space-md); min-width: 0; display: flex; align-items: center; gap: var(--space-md); min-width: 0;
} }
@@ -195,7 +207,7 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.control-btn { .control-btn {
flex: 0 0 auto; flex: 0 0 auto;
width: 72px; height: 62px; width: 72px; height: 62px;
border-radius: 16px; border-radius: var(--radius-lg);
background: var(--raised); background: var(--raised);
display: grid; place-items: center; display: grid; place-items: center;
} }
@@ -246,7 +258,7 @@ svg { width: 22px; height: 22px; fill: currentColor; }
.sources { display: flex; gap: var(--space-md); } .sources { display: flex; gap: var(--space-md); }
.sources-btn { .sources-btn {
flex: 1; min-width: 0; flex: 1; min-width: 0;
height: 50px; border-radius: 16px; height: 50px; border-radius: var(--radius-lg);
background: var(--raised); background: var(--raised);
display: flex; align-items: center; justify-content: center; gap: var(--space-sm); display: flex; align-items: center; justify-content: center; gap: var(--space-sm);
font-size: 15px; font-weight: 550; font-size: 15px; font-weight: 550;
@@ -273,7 +285,7 @@ button.sources-btn.loading .icon { display: none; }
display: flex; align-items: center; gap: var(--space-md); display: flex; align-items: center; gap: var(--space-md);
width: 100%; min-height: 50px; width: 100%; min-height: 50px;
padding: var(--space-md) var(--space-md); padding: var(--space-md) var(--space-md);
border-radius: 16px; border-radius: var(--radius-lg);
background: var(--raised); background: var(--raised);
text-align: left; text-align: left;
} }
@@ -302,7 +314,7 @@ button.sources-btn.loading .icon { display: none; }
.joined .toggle .leave { display: block; } .joined .toggle .leave { display: block; }
/* --- misc ------------------------------------------------------------- */ /* --- misc ------------------------------------------------------------- */
.wide { width: 100%; height: 50px; border-radius: 16px; font-size: 15px; } .wide { width: 100%; height: 50px; border-radius: var(--radius-lg); font-size: 15px; }
.ghost { background: transparent; border: 1px solid var(--edge); color: var(--muted); } .ghost { background: transparent; border: 1px solid var(--edge); color: var(--muted); }
.foot { margin: var(--space-xs) var(--space-xs) 0; min-height: 18px; font-size: 12px; color: var(--muted); text-align: center; } .foot { margin: var(--space-xs) var(--space-xs) 0; min-height: 18px; font-size: 12px; color: var(--muted); text-align: center; }
@@ -331,7 +343,7 @@ button.sources-btn.loading .icon { display: none; }
.option { .option {
display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
min-height: 58px; padding: 0 var(--space-md); min-height: 58px; padding: 0 var(--space-md);
border-radius: 16px; background: var(--raised); border-radius: var(--radius-lg); background: var(--raised);
font-size: 17px; text-align: left; font-size: 17px; text-align: left;
} }
.option[aria-current="true"] { background: var(--accent); color: var(--ink-bright); } .option[aria-current="true"] { background: var(--accent); color: var(--ink-bright); }
+11 -8
View File
@@ -58,15 +58,15 @@
<h2><svg class="room-icon" data-icon="{{ room.kind }}" viewBox="0 0 512 512" aria-hidden="true"><path d=""/></svg><span class="room-label">{{ room.label }}</span></h2> <h2><svg class="room-icon" data-icon="{{ room.kind }}" viewBox="0 0 512 512" aria-hidden="true"><path d=""/></svg><span class="room-label">{{ room.label }}</span></h2>
</div> </div>
<div class="now-playing" data-role="now-playing" hidden> <div class="media" data-role="media" hidden>
<img class="cover" data-role="cover" alt="" hidden> <div class="now-playing">
<img class="cover" data-role="cover" alt="">
<div class="track"> <div class="track">
<span class="song" data-role="song"></span> <span class="song" data-role="song"></span>
<span class="artist" data-role="artist"></span> <span class="artist" data-role="artist"></span>
</div> </div>
</div> </div>
<div class="progress" data-role="progress" data-target="{{ room.key }}">
<div class="progress" data-role="progress" data-target="{{ room.key }}" hidden>
<div class="progress-line"> <div class="progress-line">
<i data-role="progress-fill"></i> <i data-role="progress-fill"></i>
<b class="progress-cursor" data-role="progress-cursor"></b> <b class="progress-cursor" data-role="progress-cursor"></b>
@@ -75,6 +75,7 @@
</div> </div>
<span class="progress-total" data-role="progress-total"></span> <span class="progress-total" data-role="progress-total"></span>
</div> </div>
</div>
<div class="volume"> <div class="volume">
<button class="control-btn step" data-delta="-1" aria-label="{{ room.label }}: volume down"> <button class="control-btn step" data-delta="-1" aria-label="{{ room.label }}: volume down">
@@ -111,15 +112,16 @@
<div class="card-head"> <div class="card-head">
<h2><svg class="room-icon" data-icon="{{ host.kind }}" viewBox="0 0 512 512" aria-hidden="true"><path d=""/></svg><span class="room-label">{{ host.label }}</span></h2> <h2><svg class="room-icon" data-icon="{{ host.kind }}" viewBox="0 0 512 512" aria-hidden="true"><path d=""/></svg><span class="room-label">{{ host.label }}</span></h2>
</div> </div>
<div class="now-playing" data-role="avr-now-playing" hidden>
<img class="cover poster" data-role="avr-cover" alt="" hidden> <div class="media" data-role="avr-media" hidden>
<div class="now-playing" data-role="avr-now-playing">
<img class="cover poster" data-role="avr-cover" alt="">
<div class="track"> <div class="track">
<span class="song" data-role="avr-song"></span> <span class="song" data-role="avr-song"></span>
<span class="artist" data-role="avr-artist"></span> <span class="artist" data-role="avr-artist"></span>
</div> </div>
</div> </div>
<div class="progress" data-role="avr-progress" data-target="{{ host.key }}">
<div class="progress" data-role="avr-progress" data-target="{{ host.key }}" hidden>
<div class="progress-line"> <div class="progress-line">
<i data-role="progress-fill"></i> <i data-role="progress-fill"></i>
<b class="progress-cursor" data-role="progress-cursor"></b> <b class="progress-cursor" data-role="progress-cursor"></b>
@@ -128,6 +130,7 @@
</div> </div>
<span class="progress-total" data-role="progress-total"></span> <span class="progress-total" data-role="progress-total"></span>
</div> </div>
</div>
<button class="input-select" data-role="input-button"> <button class="input-select" data-role="input-button">
<span class="eyebrow">Input</span> <span class="eyebrow">Input</span>