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',