Show merged rooms inside the host's card
Two cards side by side said nothing about whether the rooms were playing together; now a room that joins the AVR moves into its card, under the input it is playing, and leaving puts the card back in its own slot. The button changes with it: Join Home Cinema when it stands alone, Leave when it is in the group, since the card's position already says which it is. Also fixes Separate everything, which sent a GET to a POST-only route and so failed with a 405 and snapped the rooms straight back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+33
-2
@@ -3,6 +3,7 @@
|
||||
network round trip before it looks like it did anything feels broken. */
|
||||
|
||||
const STEP = Number(document.documentElement.dataset.step) || 2;
|
||||
const HOST_LABEL = document.documentElement.dataset.host || 'the AVR';
|
||||
const POLL_MS = 5000;
|
||||
|
||||
const el = (sel, root = document) => root.querySelector(sel);
|
||||
@@ -18,6 +19,8 @@ const ui = {
|
||||
inputName: el('[data-role="input-name"]'),
|
||||
sheet: el('[data-role="sheet"]'),
|
||||
options: el('[data-role="options"]'),
|
||||
joined: el('[data-role="joined"]'),
|
||||
joinedRooms: el('[data-role="joined-rooms"]'),
|
||||
};
|
||||
|
||||
const rooms = {};
|
||||
@@ -50,6 +53,7 @@ els('.room').forEach((node) => {
|
||||
const room = {
|
||||
key,
|
||||
node,
|
||||
slot: el(`.room-slot[data-slot="${key}"]`),
|
||||
level: el('[data-role="level"]', node),
|
||||
bar: el('[data-role="bar"]', node),
|
||||
toggle: el('[data-role="group"]', node),
|
||||
@@ -81,7 +85,30 @@ function paintRoom(room) {
|
||||
room.toggle.disabled = !room.available;
|
||||
room.toggle.classList.toggle('busy', room.busy);
|
||||
room.toggle.setAttribute('aria-pressed', String(room.grouped));
|
||||
room.toggleLabel.textContent = room.grouped ? 'Grouped with AVR' : 'Separate';
|
||||
// Where the card sits already says whether it is grouped, so the button
|
||||
// says what tapping it does instead.
|
||||
room.toggleLabel.textContent = room.grouped ? 'Leave' : `Join ${HOST_LABEL}`;
|
||||
placeRoom(room);
|
||||
}
|
||||
|
||||
/* A merged room moves into the host's card, because that is what merging
|
||||
means: one group, playing one thing. Leaving puts the card back in its
|
||||
own slot, which is why the slots exist. */
|
||||
function placeRoom(room) {
|
||||
const target = room.grouped ? ui.joinedRooms : room.slot;
|
||||
if (room.node.parentElement !== target) target.appendChild(room.node);
|
||||
}
|
||||
|
||||
function paintGrouping() {
|
||||
const order = Object.keys(rooms);
|
||||
const inside = Array.from(ui.joinedRooms.children);
|
||||
// Keep them in the order the cards are declared, not the order they joined.
|
||||
inside
|
||||
.slice()
|
||||
.sort((a, b) => order.indexOf(a.dataset.room) - order.indexOf(b.dataset.room))
|
||||
.forEach((node) => ui.joinedRooms.appendChild(node));
|
||||
ui.joined.hidden = inside.length === 0;
|
||||
ui.splitAll.hidden = inside.length === 0;
|
||||
}
|
||||
|
||||
/* Press and hold to keep moving, accelerating as you hold. */
|
||||
@@ -154,6 +181,7 @@ async function setGrouped(key, joined) {
|
||||
room.busy = true;
|
||||
room.grouped = joined; // show the new state while the speakers catch up
|
||||
paintRoom(room);
|
||||
paintGrouping();
|
||||
try {
|
||||
const data = await api('/api/group', { target: key, joined });
|
||||
applyJoined(data.joined || []);
|
||||
@@ -170,12 +198,13 @@ function applyJoined(joined) {
|
||||
room.grouped = joined.includes(room.key);
|
||||
paintRoom(room);
|
||||
});
|
||||
paintGrouping();
|
||||
}
|
||||
|
||||
ui.splitAll.addEventListener('click', async () => {
|
||||
try {
|
||||
applyJoined([]);
|
||||
const data = await api('/api/group/none');
|
||||
const data = await api('/api/group/none', {}); // {} so it is a POST, as the route requires
|
||||
applyJoined(data.joined || []);
|
||||
} catch (error) {
|
||||
toast(error.message);
|
||||
@@ -237,6 +266,7 @@ function render(state) {
|
||||
if (!room.taps && !room.inflight) room.volume = incoming.volume;
|
||||
paintRoom(room);
|
||||
});
|
||||
paintGrouping();
|
||||
|
||||
const avr = state.avr || {};
|
||||
inputs = avr.inputs || [];
|
||||
@@ -283,4 +313,5 @@ document.addEventListener('visibilitychange', () => {
|
||||
});
|
||||
|
||||
Object.values(rooms).forEach(paintRoom);
|
||||
paintGrouping();
|
||||
refresh();
|
||||
|
||||
Reference in New Issue
Block a user