Files

92 lines
3.0 KiB
JavaScript
Raw Permalink Normal View History

2026-08-09 16:32:42 +02:00
const status = document.querySelector('#status');
const buttons = [...document.querySelectorAll('.group-button')];
const apiPrefix = document.body.dataset.apiPrefix;
function apiFetch(path, options = {}) {
2026-08-09 17:25:45 +02:00
return fetch(path, options);
2026-08-09 16:32:42 +02:00
}
function showStatus(message, persistent = false) {
status.textContent = message;
status.classList.add('visible');
if (!persistent) window.setTimeout(() => status.classList.remove('visible'), 1800);
}
async function refresh() {
try {
const response = await apiFetch(`${apiPrefix}/groups`, { cache: 'no-store' });
const body = await response.json();
if (!response.ok) throw new Error(body.error || 'Could not check the bridge');
const states = new Map(body.groups.map(group => [group.id, group]));
buttons.forEach(button => {
const group = states.get(button.dataset.id);
button.classList.toggle('is-on', group?.on === true);
button.querySelector('small').textContent = group?.scene || '';
});
status.classList.remove('visible');
} catch (error) {
showStatus(error.message, true);
}
}
async function activateNextScene(button) {
button.disabled = true;
try {
const response = await apiFetch(`${apiPrefix}/groups/${button.dataset.id}/next-scene`, { method: 'POST' });
const body = await response.json();
if (!response.ok) throw new Error(body.error || 'Could not control the bridge');
showStatus(`${button.querySelector('span').textContent}: ${body.scene}`);
button.querySelector('small').textContent = body.scene;
window.setTimeout(refresh, 350);
} catch (error) {
showStatus(error.message, true);
} finally {
button.disabled = false;
}
}
async function turnOff(button) {
button.disabled = true;
try {
const response = await apiFetch(`${apiPrefix}/groups/${button.dataset.id}/off`, { method: 'POST' });
const body = await response.json();
if (!response.ok) throw new Error(body.error || 'Could not turn off the lights');
button.classList.remove('is-on');
button.querySelector('small').textContent = 'Lights off';
showStatus(`${button.querySelector('span').textContent}: off`);
window.setTimeout(refresh, 350);
} catch (error) {
showStatus(error.message, true);
} finally {
button.disabled = false;
}
}
buttons.forEach(button => {
let pressTimer;
let longPressHandled = false;
const clearPressTimer = () => window.clearTimeout(pressTimer);
button.addEventListener('pointerdown', () => {
longPressHandled = false;
pressTimer = window.setTimeout(() => {
longPressHandled = true;
turnOff(button);
}, 650);
});
button.addEventListener('pointerup', clearPressTimer);
button.addEventListener('pointercancel', clearPressTimer);
button.addEventListener('pointerleave', clearPressTimer);
button.addEventListener('click', event => {
if (longPressHandled) {
event.preventDefault();
longPressHandled = false;
return;
}
activateNextScene(button);
});
});
refresh();
window.setInterval(refresh, 15000);