NA page-number key: hold 2 s = status page, keep holding to 3 s = LOCATIONS page

- nav_hold_more: longer holds go further (tested on NA's Companion emulator: 2.5 s -> 19, 3.5 s -> 98, tap -> 1)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 16:06:04 -04:00
co-authored by Claude Opus 5.5
parent b9a0f3905f
commit 0813734e78
9 changed files with 34 additions and 5 deletions
+1
View File
@@ -311,6 +311,7 @@ Smart-plug keys (outlets.json) are never copied.
page gets a blue band naming it ("SC", "SC WS", "SC?" when it stops answering). It flashes until that location
acknowledges, then stays; the page's own name and number shrink into the top 60% so they stay readable. Red stays
for NA's own problems.
- **Page-number key holds at NA** (`nav_hold_ms` 2000 + `nav_hold_more`): tap = page 1, hold 2 s = the status page (19), keep holding to 3 s = the LOCATIONS page (98) to pick a location. WS and SC keep a 1 s hold to their status page.
- **ALL AUTO-FIX** (LOCATIONS page 98, bottom-left): blue "ALL ON", or grey naming the paused locations. Tap: pause
auto-fix at NA, WS and SC at once; tap again: every one back to its own auto-fix hours (`autofix auto`). Alarms stay
on and holds still fix.
+8 -2
View File
@@ -855,7 +855,7 @@
"ssh": "studio@10.1.7.39"
}
},
"nav_hold_ms": 1000,
"nav_hold_ms": 2000,
"nav_keys": [
"pagenum"
],
@@ -2299,5 +2299,11 @@
"heartbeat": "sp_hb",
"state": "sp_state"
},
"nav_locations_band": true
"nav_locations_band": true,
"nav_hold_more": [
{
"ms": 3000,
"page": 98
}
]
}
+8
View File
@@ -333,6 +333,14 @@ def nav_key(kind, names, status_page=None, hold_ms=1000, tap_page=1, cfg=None):
"options": {"surfaceId": prop("self"), "page": prop(status_page)}, "children": {}}]
step["action_sets"] = {"down": [], "up": tap, str(hold_ms): hold}
step["options"]["runWhileHeld"] = [hold_ms]
# Longer holds go further (NA, 2026-10-21: 2 s the status page, still held at 3 s the LOCATIONS page).
for i, more in enumerate(sorted((cfg or {}).get("nav_hold_more") or [], key=lambda m: m["ms"])):
if more["ms"] > hold_ms:
step["action_sets"][str(more["ms"])] = [{"type": "action", "id": stable_id("nav", "hold%d" % (i + 2)),
"definitionId": "set_page", "connectionId": "internal",
"options": {"surfaceId": prop("self"), "page": prop(more["page"])},
"children": {}}]
step["options"]["runWhileHeld"].append(more["ms"])
key["options"]["notes"] = ("%s (%s): colour follows the ALL button on the status page. "
"Undo on every page with: python3 nav_keys.py --revert" % (NAV_MARKER, kind))
return key
Binary file not shown.
Binary file not shown.
+2
View File
@@ -71,6 +71,8 @@ field("nav_keys", "list", ["pagenum"], "Which of Companion's page keys (page up,
apply="pages")
field("nav_hold_ms", "int", 1000, "Holding the page-number key this long jumps to the Status page.", "Companion",
advanced=True, lo=200, hi=5000, apply="pages")
field("nav_hold_more", "list", [], "Longer holds on the page-number key: [{\"ms\": 3000, \"page\": 98}] - still held at 3 s, "
"it goes on to page 98 (NA: 2 s the status page, 3 s the LOCATIONS page).", "Companion", advanced=True, apply="pages")
field("nav_tap_page", "int", 1, "Tapping the page-number key goes to this page.", "Companion", advanced=True, lo=1,
apply="pages")
field("variables", "dict", {}, "The custom variables the panel uses inside Companion.", "Companion", required=True)
Binary file not shown.
+11
View File
@@ -616,3 +616,14 @@ class TestAllAutoFix(unittest.TestCase):
key = page["page"]["controls"]["3"]["1"]
self.assertIn("all autofix", key["options"]["notes"])
self.assertIn("sp_all_cmd", json.dumps(key["steps"]))
class TestLongerHolds(unittest.TestCase):
def test_na_page_key_goes_to_status_at_2s_and_locations_at_3s(self):
na = json.load(open(os.path.join(ROOT, "config.json")))
cfg = dict(na, nav_hold_ms=2000, nav_hold_more=[{"ms": 3000, "page": 98}])
st = make_page.nav_key("pagenum", cfg["variables"], 19, 2000, 1, cfg)["steps"]["0"]
pages = {k: [a["options"]["page"]["value"] for a in v] for k, v in st["action_sets"].items()}
self.assertEqual(pages, {"down": [], "up": [1], "2000": [19], "3000": [98]})
self.assertEqual(st["options"]["runWhileHeld"], [2000, 3000])
self.assertEqual(schema.validate(cfg)[0], [])
+4 -3
View File
@@ -2274,10 +2274,11 @@ class TestPage(unittest.TestCase):
self.assertTrue(key["options"]["notes"].startswith("STATUS nav key (%s)" % kind))
step = key["steps"]["0"]
self.assertEqual(step["action_sets"]["down"], [])
tap, hold = step["action_sets"]["up"][0], step["action_sets"]["1000"][0]
tap, hold = step["action_sets"]["up"][0], step["action_sets"]["2000"][0] # NA: 2 s ...
self.assertEqual((tap["definitionId"], tap["options"]["page"]["value"]), (action, 1)) # page 1 outright, not "startup"
self.assertEqual((hold["definitionId"], hold["options"]["page"]["value"]), ("set_page", 19))
self.assertEqual(step["options"]["runWhileHeld"], [1000])
self.assertEqual(step["action_sets"]["3000"][0]["options"]["page"]["value"], 98) # ... then 3 s: LOCATIONS
self.assertEqual(step["options"]["runWhileHeld"], [2000, 3000])
box = [l for l in key["style"]["layers"] if l["type"] == "box"][0]
self.assertTrue(box["color"]["isExpression"])
self.assertIn("'$.all.b'", box["color"]["value"]) # follows the ALL button
@@ -2297,7 +2298,7 @@ class TestPage(unittest.TestCase):
for r in c.values():
for ctl in r.values():
sets = ctl.get("steps", {}).get("0", {}).get("action_sets", {})
if "2000" in sets:
if "2000" in sets and sets["2000"][0]["definitionId"] != "set_page": # not the page-number key's hold
holds[sets["2000"][0]["options"]["value"]["value"]] = sets["up"]
self.assertEqual(len(holds), len(CONFIG["restart_page"]["keys"]))
self.assertIn("$(custom:sp_cmd);force rs_tascam $(internal:time_unix)", holds)