workable POC
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
const status = document.querySelector('#status');
|
||||
const buttons = [...document.querySelectorAll('.group-button')];
|
||||
const apiPrefix = document.body.dataset.apiPrefix;
|
||||
const url = new URL(window.location.href);
|
||||
const suppliedKey = url.searchParams.get('key');
|
||||
if (suppliedKey) {
|
||||
sessionStorage.setItem('fasthue-api-key', suppliedKey);
|
||||
url.searchParams.delete('key');
|
||||
history.replaceState({}, '', url);
|
||||
}
|
||||
const apiKey = sessionStorage.getItem('fasthue-api-key');
|
||||
|
||||
function apiFetch(path, options = {}) {
|
||||
return fetch(path, {
|
||||
...options,
|
||||
headers: { ...options.headers, Authorization: `Bearer ${apiKey || ''}` },
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
Reference in New Issue
Block a user