diff --git a/appinfo/info.xml b/appinfo/info.xml index 4f2c214..44441f7 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -16,7 +16,7 @@ the buttons are redrawn from that answer, never from the card's own idea of the No build step, no bundler, no state: a PHP widget, one controller, one JS file. ]]> - 1.3.4 + 1.4.0 agpl bawnet ZigbeeCard diff --git a/js/zigbee_card.js b/js/zigbee_card.js index 8d0b342..5b61bad 100644 --- a/js/zigbee_card.js +++ b/js/zigbee_card.js @@ -60,8 +60,24 @@ text.appendChild(sub) btn.appendChild(icon) btn.appendChild(text) - btn.addEventListener('click', function () { onPress(b) }) + var held = false, holdTimer = null + btn.addEventListener('click', function () { if (held) { held = false; return } onPress(b) }) btn.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onPress(b) } }) + if (b.hold) { + btn.addEventListener('pointerdown', function () { + held = false + holdTimer = setTimeout(function () { + held = true + if (el.classList.contains('zc-busy')) { return } + busy(true); say(b.hold + ' โ€ฆ') + post(b.hold).then(function (d) { say((d.reply || 'no answer').split('\n')[0], !d.ok); return refresh() }).catch(function (e) { say('no answer: ' + e, true) }).finally(function () { busy(false) }) + }, 500) + }) + var clr = function () { if (holdTimer) { clearTimeout(holdTimer); holdTimer = null } } + btn.addEventListener('pointerup', clr) + btn.addEventListener('pointerleave', clr) + btn.addEventListener('pointercancel', clr) + } li.appendChild(btn) list.appendChild(li) rows[b.key] = { btn: btn, icon: icon, title: title, sub: sub } @@ -138,6 +154,15 @@ r.icon.textContent = (s && s.icon) || b.icon r.title.textContent = s ? s.label : 'โ€ฆ' r.sub.textContent = s ? s.now : 'asking the house' + } else if (b.kind === 'cycle') { + r.icon.textContent = b.icon + var cs = state && state.scenes && state.scene_idx != null ? state.scenes[state.scene_idx] : null + r.title.textContent = cs || b.label + r.sub.textContent = b.now + } else if (b.kind === 'dimmer') { + r.icon.textContent = b.icon + r.title.textContent = b.label + r.sub.textContent = state && state.lights_on === false ? 'off ยท tap = on' : b.now } else { r.icon.textContent = b.icon r.title.textContent = b.label diff --git a/lib/Buttons.php b/lib/Buttons.php index 80b596a..8f5d78b 100644 --- a/lib/Buttons.php +++ b/lib/Buttons.php @@ -26,12 +26,8 @@ final class Buttons { */ public const ALL = [ ['key' => 'climate', 'kind' => 'reading', 'icon' => '๐ŸŒก', 'now' => 'asking the house'], // until the first state: then the door's last change (js) - ['key' => 'scene', 'kind' => 'toggle', 'icon' => 'โ˜€๏ธ', - 'on' => ['when' => 'day', 'label' => 'night', 'now' => 'lights are on day', 'send' => 'lights night', 'icon' => '๐ŸŒ™'], - 'off' => ['when' => null, 'label' => 'day', 'now' => 'lights are on night', 'send' => 'lights day', 'icon' => 'โ˜€๏ธ']], - ['key' => 'lights_on', 'kind' => 'toggle', 'icon' => '๐Ÿ’ก', - 'on' => ['when' => true, 'label' => 'lights off', 'now' => 'lights are on', 'send' => 'lights off'], - 'off' => ['when' => false, 'label' => 'lights on', 'now' => 'lights are off', 'send' => 'lights on']], + ['key' => 'scene', 'kind' => 'cycle', 'icon' => '๐ŸŽฌ', 'label' => 'scene', 'now' => 'tap to cycle scenes', 'send' => 'lights next'], + ['key' => 'dimmer', 'kind' => 'dimmer', 'icon' => '๐Ÿ”†', 'label' => 'dim', 'now' => 'tap โˆ’10% ยท hold = off', 'send' => 'lights dim', 'hold' => 'lights off'], ['key' => 'ac', 'kind' => 'toggle', 'icon' => 'โ„๏ธ', 'on' => ['when' => 'ON', 'label' => 'AC off', 'now' => 'AC is on', 'send' => 'ac off'], 'off' => ['when' => 'OFF', 'label' => 'AC on', 'now' => 'AC is off', 'send' => 'ac on']], @@ -43,7 +39,7 @@ final class Buttons { /** Every line the page may send: the toggles' two sides, the action, and the one read. */ public const LINES = [ - 'lights day', 'lights night', 'lights on', 'lights off', + 'lights day', 'lights night', 'lights on', 'lights off', 'lights next', 'lights dim', 'ac on', 'ac off', 'heater on', 'heater off', 'feed bella', 'state',