diff --git a/README_EXTENDED.md b/README_EXTENDED.md index 35f4fed..8c42d82 100644 --- a/README_EXTENDED.md +++ b/README_EXTENDED.md @@ -229,8 +229,11 @@ written until you press the button. Every screen has two buttons in Home Assistant (firmware 0.2.45+). An automation presses them with the `button.press` action: -- **`button._wake`** does what a tap does: a screen in standby lights up, and the standby - time starts counting again. On a screen that is already on, only the count starts again. +- **`button._wake`** lights the screen up: a screen in standby goes to its normal brightness + (the second hand of an analog clock runs again), and the standby time starts counting again. On a + screen that is already on, only the count starts again. Wake is not a touch: **Back to page 1** keeps + counting from the last touch, so pressing Wake on every motion doesn't keep an open card or a later + page up, and a screen whose time ran out during standby lights up on page 1 (firmware 0.2.56+). - **`button._sleep`** puts the screen in standby right away, the same as when the standby time runs out, and also works with **Auto standby** off. The screen stays in standby until someone taps it, **Wake** is pressed or an alert comes in; switching Auto standby off doesn't end it. An alert diff --git a/docs/RELEASING.md b/docs/RELEASING.md index f0f4080..1a1a636 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -176,6 +176,29 @@ icons sit off-center in the browser); run `generate_packages.py` afterward. The `MDI_GLYPH_*` substitutions are retired: `TILEn_ICON` in manual profiles must come from the set. No changed preferences or keys. +### Compatibility 0.2.65 / firmware 0.2.56 + +Both board profiles and the editor page; the app raises `FIRMWARE_VERSION`. Storage, tile protocol, preferences, keys +and entities are unchanged. + +- Two clocks. `last_touch_ms` stays the standby time: a touch, Wake, `wake_display`, an alert ending + (`alert_dismiss`) and Auto standby on restart it, exactly as before. The new non-restored `last_use_ms` is Back to + page 1: the boot, the three touchscreen triggers (`on_touch`, `on_update`, `on_release`), `open_settings` from Home + Assistant and the UI self test write it, nothing else. Before, Wake reset the one clock both rules read, so an + automation pressing Wake on every motion held a card or page 2 up indefinitely. +- The Back to page 1 check moved from the one-second interval into the script `back_to_page_1_when_due` (same + condition, now on `last_use_ms`, still paused while `display_dimmed`). The interval runs it, and so does Wake + right after `wake_display` on a dimmed screen: a page whose time ran out during standby goes home in the same pass, + before LVGL draws the old page at full brightness. `ui_state` logs `use_idle_ms` beside `idle_ms`. +- `wake_display` is unchanged and still restarts only the standby clock: a tap on the dim overlay is a touch through + the touchscreen triggers anyway, and an alert blocks the rule while it is up. +- Older firmware keeps counting Wake, an alert ending and Auto standby on as a touch for Back to page 1. The Claude + skill says that from 0.2.56 Wake is no touch; an installed skill shows as outdated until it is installed again. +- `static/app.js` no longer selects `inventory.screens[0]` in `refresh()` or `applyLive()`; the only way into a screen + is its button. `renderScreens()` shows `#choose` ("Choose a screen") while nothing is selected and screens exist, + `#empty` while there are none; both start `hidden` in `index.html`, so neither flashes before the first inventory. + A screen picked before the full inventory arrives still gets the 0.2.58 catalogue redraw. + ### Compatibility 0.2.64 / firmware 0.2.55 Both board profiles, the Claude skill and the editor's alert tips; the app raises `FIRMWARE_VERSION`. Storage, tile diff --git a/docs/TEST_RESULTS_0265.md b/docs/TEST_RESULTS_0265.md new file mode 100644 index 0000000..8fb2434 --- /dev/null +++ b/docs/TEST_RESULTS_0265.md @@ -0,0 +1,83 @@ +# Test results app 0.2.65 / firmware 0.2.56 (2026-09-17) + +Two requests from Max. The Wake button in Home Assistant should only bring back the light (and the second hand of an +analog clock), not postpone Back to page 1. And ESP Screens should open without choosing a screen by itself. See +CHANGELOG 0.2.65 and the compatibility note in docs/RELEASING.md. Built on 0.2.64 (`e68162b`). + +## Cause + +- Wake (0.2.53) was designed as "a tap": on a dimmed screen it ran `wake_display`, on a screen that was on it set + `last_touch_ms`. That one clock also drove the Back to page 1 check in the one-second interval, so every Wake started + the two minutes again. An automation pressing Wake on every motion kept an open card or page 2 up as long as someone + moved in the room. The same held for an alert ending and for Auto standby switched on. +- `refresh()` and `applyLive()` in `static/app.js` selected `inventory.screens[0]` whenever nothing was selected, since + the first version of the editor. + +## Automated + +- Python (`.venv-portal`): 314 tests OK (312 on 0.2.64). `tests/test_wake_sleep.py`: `test_wake_is_a_tap` became + `test_wake_is_light_not_a_tap` (Wake runs `wake_display` and then `back_to_page_1_when_due`, and neither touches + `last_use_ms`), and the new `test_back_to_page_1_counts_from_the_last_touch` checks in both profiles and both packages + that the rule reads `last_use_ms` only, runs from the interval and Wake only, and that exactly the boot, the three + touchscreen triggers, `open_settings` and the UI self test write that clock, while `alert_dismiss` and Auto standby + write only `last_touch_ms`. `tests/test_editor_startup.py`: no `select()` besides the screen button, the + "Choose a screen" card and the install card start hidden and follow the selection, and the 0.2.58 catalogue redraw + stays. +- C++ (`clang++ -std=c++17 -Wall -Wextra -Werror -I.`): 16/16 PASS. +- `generate_packages.py --check` green. + +## Firmware on the Mac (host builds, driven over the ESPHome API) + +The 0.2.53 Wake/Sleep harness on host builds of both packages (own device names and API ports), with a probe that +also logs `tile_page`, the age of `last_use_ms`, `runtime_tiles::awake()` (what the second hand follows) and the Back +to page 1 setting. **Guition 48/48, CYD 48/48.** The 35 earlier checks (standby timer, Sleep with Auto standby off +across a real minute tick, alert, calibration) all still pass. The 13 new ones: + +| Check | Result on both boards | +|---|---| +| Back to page 1 on at its default | on, 120 s | +| Wake on page 2, touch 100 s ago | standby time restarts (`idle_ms` < 3 s), page-1 clock keeps its 100 s | +| Wake again with the page-1 clock at 125 s | page 1 within the next interval pass, screen stays on | +| A card open with the clock at 125 s, Wake pressed three times | the card closes anyway | +| Sleep on page 2 with "Also on standby" off | dimmed, page 2 kept, `awake()` false | +| Page-1 clock at 300 s while in standby | still page 2: the rule waits for the light | +| Wake after that | in the same pass: bright, page 1, `awake()` true (the probe right after it logs `idle_ms=0`) | +| Sleep and Wake with 30 s on the clock | page 2 stays | +| `open_settings` from Home Assistant with the clock at 300 s | the page stays open, clock restarted | +| `open_settings` -1 | closes, page 1 | +| An alert on page 2 with the clock at 300 s | page 2 kept while the alert is up | +| The alert dismissed | page 1, standby time restarted | + +A real touch cannot be injected into the host's SDL touchscreen; the profile test covers the three touchscreen +triggers that write the page-1 clock. + +## Builds (ESPHome 2026.6.2) + +Check profiles with the generated packages and local components, as for 0.2.64. Both compile without errors. + +| Profile | RAM | Flash | vs 0.2.64 | +|---|---|---|---| +| CYD | 23.7% (77,572 B) | 77.5% (1,421,263 B) | +72 B RAM, +272 B flash | +| Guition | 24.7% (80,932 B) | 18.8% (1,524,939 B) | +80 B RAM, +292 B flash | + +(The 0.2.64 numbers come from that release's check builds, whose device names were five characters shorter.) + +## ESP Screens + +The real add-on from this tree on the demo home (two screens, fake Home Assistant), in the browser pane: + +- Opening the page: nothing selected, the right side says "Choose a screen", the install card and the editor hidden. + The Refresh button and a light inventory select nothing. +- Clicking a screen opens the editor with its top bar, tiles and the entity list (34 results), and marks it in the + list. With an unsaved name, clicking the other screen asks "You have unsaved changes. Open a different screen + anyway?"; No keeps the screen, Yes opens the other one. Live updates afterwards keep that choice. +- After a reload nothing is selected again. A live update with no screens shows "Start with a screen" with its button; + with the screens back, "Choose a screen" returns. Settings and back to My screens keep the empty choice. +- At 375 px the screens sit in their row above a short "Choose a screen" card (no tall empty card, no icon, no + horizontal scroll); tapping a screen opens the editor. +- No console errors. + +## Not tested + +- Physical screens: not flashed in this round. Wake on Studio 1 from Home Assistant after the update is Max's check. +- The page in Home Assistant's Ingress frame. diff --git a/guition-4848s040.yaml b/guition-4848s040.yaml index b7937e2..1ab12f6 100644 --- a/guition-4848s040.yaml +++ b/guition-4848s040.yaml @@ -2,7 +2,7 @@ # Source profile for packages/guition.yaml (tools/generate_packages.py); see docs/GUITION.md. # A screen gets its tiles from the ESP Screen Manager add-on while it runs. The CYD is its own profile. substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.55" + SCREEN_FIRMWARE_VERSION: "0.2.56" # 0: no drift limit; LVGL decides, releasing inside the tile is a tap, leaving it is not # (like iOS). The CYD keeps a limit because its resistive panel jumps. TOUCH_MOVE_LIMIT_PX: "0" @@ -142,6 +142,7 @@ esphome: } } id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(display_dimmed) = false; - lambda: |- auto &settings = screen_settings::current; @@ -372,11 +373,11 @@ api: then: - lambda: |- const auto &cfg = screen_settings::current; - ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u dimmed=%d", + ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u use_idle_ms=%u dimmed=%d", cfg.standby_enabled, cfg.standby_seconds, cfg.brightness, cfg.standby_brightness, cfg.night_enabled, cfg.night_start, cfg.night_end, cfg.night_brightness, cfg.show_clock, cfg.clock_24h, cfg.home_on_standby, - (unsigned)(millis() - id(last_touch_ms)), id(display_dimmed)); + (unsigned)(millis() - id(last_touch_ms)), (unsigned)(millis() - id(last_use_ms)), id(display_dimmed)); ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page), runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); ESP_LOGI("ui_diag", "rotation=%u actual=%u", (unsigned)runtime_tiles::rotation, (unsigned)id(screen_lvgl).get_rotation()); @@ -415,6 +416,8 @@ api: then: - lambda: |- if (page < 0) { id(go_home).execute(); return; } + // Opened for someone to look at: Back to page 1 counts from now, as after a touch. + id(last_use_ms) = millis(); id(wake_display).execute(); settings_screen::open((uint8_t) page); ESP_LOGI("settings", "page %d open from Home Assistant", page); @@ -529,19 +532,7 @@ interval: return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL); then: - script.execute: dim_display - # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps - # showing what someone looked at minutes ago; after this long the screen is a screen again. - # Independent of standby, which may be off or much later. - - if: - condition: - lambda: |- - if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; - if (id(display_dimmed)) return false; - bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || - (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); - return away && (millis() - id(last_touch_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; - then: - - script.execute: go_home + - script.execute: back_to_page_1_when_due time: - platform: homeassistant @@ -606,11 +597,18 @@ globals: type: std::string restore_value: no + # Two clocks. last_touch_ms is the standby time: a touch, Wake, an alert ending and Auto standby on restart it. + # last_use_ms is Back to page 1 (firmware 0.2.56+): only a touch, or Home Assistant opening the settings page. - id: last_touch_ms type: uint32_t restore_value: no initial_value: '0' + - id: last_use_ms + type: uint32_t + restore_value: no + initial_value: '0' + # Debounce for do_tile_action: protects against repeated events from # multiple separate press/release cycles for one physical touch (noise in # the resistive layer), causing the same HA action to fire multiple times @@ -1283,6 +1281,7 @@ touchscreen: on_touch: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = true; cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id); cyd::edge_swipe.begin(touch.x, touch.y, static_cast(id(screen_lvgl).get_rotation())); @@ -1290,6 +1289,7 @@ touchscreen: on_update: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); // Only the contact that started the touch counts; the guard ignores other ids. for (const auto &point : touches) { // Trace every sample of an edge touch: the log then shows how often the panel delivers. @@ -1317,6 +1317,7 @@ touchscreen: on_release: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = false; if (cyd::edge_swipe.armed() && cyd::edge_swipe.inward() > 0) ESP_LOGI("touch", "edge swipe not fired: %d px inward, %d px vertical", cyd::edge_swipe.inward(), cyd::edge_swipe.sideways()); @@ -3513,6 +3514,7 @@ script: then: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); static unsigned test_page=0; id(tile_page) = runtime_tiles::enabled ? test_page++ % runtime_tiles::page_count() : 1; - script.execute: show_tile_page @@ -3655,6 +3657,24 @@ script: - lambda: 'id(tile_page) = 0;' - script.execute: show_tile_page + # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps + # showing what someone looked at minutes ago; after this long the screen is a screen again. + # Independent of standby, which may be off or much later; paused while the screen is in standby. + # The time runs from the last touch (last_use_ms, firmware 0.2.56+): Wake, an alert or Auto standby + # light the screen and restart the standby time, but nobody used a page. Checked every second and by Wake. + - id: back_to_page_1_when_due + then: + - if: + condition: + lambda: |- + if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; + if (id(display_dimmed)) return false; + bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || + (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); + return away && (millis() - id(last_use_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; + then: + - script.execute: go_home + # ---------- ALERT (HA action show_alert) ---------- # The screen wakes, keeps its normal brightness and shows the card until OK or the # timeout (0: until OK); the standby interval waits on alert_active. A new alert @@ -4526,11 +4546,12 @@ text: internal: ${DASHBOARD_INBOX_INTERNAL} button: - # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is a tap: it lights a dimmed - # screen and counts the standby time from now. Sleep is the standby time running out, right away - # and also with Auto standby off; it holds until a tap, Wake or an alert, and closes an alert that - # is up. Neither saves anything, so an automation may press them on every motion. No - # entity_category: they are controls, not settings. + # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is light, not a tap (0.2.56+): it + # lights a dimmed screen and counts the standby time from now, while Back to page 1 keeps counting + # from the last touch, so Wake on every motion no longer holds a card or page 2 up. Sleep is the + # standby time running out, right away and also with Auto standby off; it holds until a tap, Wake + # or an alert, and closes an alert that is up. Neither saves anything, so an automation may press + # them on every motion. No entity_category: they are controls, not settings. - platform: template id: wake_button name: "Wake" @@ -4542,6 +4563,8 @@ button: lambda: 'return id(display_dimmed);' then: - script.execute: wake_display + # A page whose time ran out during standby: light up on page 1, not on the old page first. + - script.execute: back_to_page_1_when_due else: - lambda: 'id(last_touch_ms) = millis();' - platform: template diff --git a/home-like-2432s028.yaml b/home-like-2432s028.yaml index d3d128d..79d8c47 100644 --- a/home-like-2432s028.yaml +++ b/home-like-2432s028.yaml @@ -17,7 +17,7 @@ ############################################################ substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.55" + SCREEN_FIRMWARE_VERSION: "0.2.56" # A tap survives a finger that drifts up to this far (320 px over 58 mm: 1 cm); further is a swipe. TOUCH_MOVE_LIMIT_PX: "56" # Shortest contact that counts as a tap; a resistive panel bounces, a capacitive one does not. @@ -248,6 +248,7 @@ esphome: id(ts_touch).set_raw_correction(${TOUCH_AFFINE_XX}f, ${TOUCH_AFFINE_XY}f, ${TOUCH_AFFINE_XC}f, ${TOUCH_AFFINE_YX}f, ${TOUCH_AFFINE_YY}f, ${TOUCH_AFFINE_YC}f); cyd::touch_guard.configure(${TOUCH_MOVE_LIMIT_PX}, ${TOUCH_MIN_PRESS_MS}); id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(display_dimmed) = false; - lambda: |- auto &settings = screen_settings::current; @@ -485,11 +486,11 @@ api: then: - lambda: |- const auto &cfg = screen_settings::current; - ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u dimmed=%d", + ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u use_idle_ms=%u dimmed=%d", cfg.standby_enabled, cfg.standby_seconds, cfg.brightness, cfg.standby_brightness, cfg.night_enabled, cfg.night_start, cfg.night_end, cfg.night_brightness, cfg.show_clock, cfg.clock_24h, cfg.home_on_standby, - (unsigned)(millis() - id(last_touch_ms)), id(display_dimmed)); + (unsigned)(millis() - id(last_touch_ms)), (unsigned)(millis() - id(last_use_ms)), id(display_dimmed)); ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page), runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); lv_area_t nav, grid; @@ -527,6 +528,8 @@ api: then: - lambda: |- if (page < 0) { id(go_home).execute(); return; } + // Opened for someone to look at: Back to page 1 counts from now, as after a touch. + id(last_use_ms) = millis(); id(wake_display).execute(); settings_screen::open((uint8_t) page); ESP_LOGI("settings", "page %d open from Home Assistant", page); @@ -641,19 +644,7 @@ interval: return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL); then: - script.execute: dim_display - # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps - # showing what someone looked at minutes ago; after this long the screen is a screen again. - # Independent of standby, which may be off or much later. - - if: - condition: - lambda: |- - if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; - if (id(display_dimmed)) return false; - bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || - (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); - return away && (millis() - id(last_touch_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; - then: - - script.execute: go_home + - script.execute: back_to_page_1_when_due time: - platform: homeassistant @@ -718,11 +709,18 @@ globals: type: std::string restore_value: no + # Two clocks. last_touch_ms is the standby time: a touch, Wake, an alert ending and Auto standby on restart it. + # last_use_ms is Back to page 1 (firmware 0.2.56+): only a touch, or Home Assistant opening the settings page. - id: last_touch_ms type: uint32_t restore_value: no initial_value: '0' + - id: last_use_ms + type: uint32_t + restore_value: no + initial_value: '0' + # Debounce for do_tile_action: this resistive XPT2046 panel sometimes gives # multiple separate press/release cycles for one physical touch (noise in # the resistive layer), causing the same HA action to fire multiple times @@ -1414,6 +1412,7 @@ touchscreen: on_touch: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = true; cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id); screen_calibration::press(); @@ -1421,6 +1420,7 @@ touchscreen: on_update: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); // Only the contact that started the touch counts; the guard ignores other ids. for (const auto &point : touches) { cyd::touch_guard.update(point.x, point.y, point.id); @@ -1428,6 +1428,7 @@ touchscreen: on_release: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = false; screen_calibration::release(id(ts_touch).filtered_raw_x(), id(ts_touch).filtered_raw_y()); @@ -3526,6 +3527,7 @@ script: then: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); static unsigned test_page=0; id(tile_page) = runtime_tiles::enabled ? test_page++ % runtime_tiles::page_count() : 1; - script.execute: show_tile_page @@ -3656,6 +3658,24 @@ script: - lambda: 'id(tile_page) = 0;' - script.execute: show_tile_page + # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps + # showing what someone looked at minutes ago; after this long the screen is a screen again. + # Independent of standby, which may be off or much later; paused while the screen is in standby. + # The time runs from the last touch (last_use_ms, firmware 0.2.56+): Wake, an alert or Auto standby + # light the screen and restart the standby time, but nobody used a page. Checked every second and by Wake. + - id: back_to_page_1_when_due + then: + - if: + condition: + lambda: |- + if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; + if (id(display_dimmed)) return false; + bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || + (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); + return away && (millis() - id(last_use_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; + then: + - script.execute: go_home + # ---------- ALERT (HA action show_alert) ---------- # The screen wakes, keeps its normal brightness and shows the card until OK or the # timeout (0: until OK); the standby interval waits on alert_active. A new alert @@ -4494,11 +4514,12 @@ button: entity_category: config on_press: - lambda: 'if (runtime_tiles::enabled) screen_calibration::begin();' - # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is a tap: it lights a dimmed - # screen and counts the standby time from now. Sleep is the standby time running out, right away - # and also with Auto standby off; it holds until a tap, Wake or an alert, and closes an alert that - # is up. Neither saves anything, so an automation may press them on every motion. No - # entity_category: they are controls, not settings. + # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is light, not a tap (0.2.56+): it + # lights a dimmed screen and counts the standby time from now, while Back to page 1 keeps counting + # from the last touch, so Wake on every motion no longer holds a card or page 2 up. Sleep is the + # standby time running out, right away and also with Auto standby off; it holds until a tap, Wake + # or an alert, and closes an alert that is up. Neither saves anything, so an automation may press + # them on every motion. No entity_category: they are controls, not settings. - platform: template id: wake_button name: "Wake" @@ -4510,6 +4531,8 @@ button: lambda: 'return id(display_dimmed);' then: - script.execute: wake_display + # A page whose time ran out during standby: light up on page 1, not on the old page first. + - script.execute: back_to_page_1_when_due else: - lambda: 'id(last_touch_ms) = millis();' - platform: template diff --git a/packages/cyd.yaml b/packages/cyd.yaml index c6b4ea4..6ec0a60 100644 --- a/packages/cyd.yaml +++ b/packages/cyd.yaml @@ -18,7 +18,7 @@ ############################################################ substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.55" + SCREEN_FIRMWARE_VERSION: "0.2.56" # A tap survives a finger that drifts up to this far (320 px over 58 mm: 1 cm); further is a swipe. TOUCH_MOVE_LIMIT_PX: "56" # Shortest contact that counts as a tap; a resistive panel bounces, a capacitive one does not. @@ -252,6 +252,7 @@ esphome: id(ts_touch).set_raw_correction(${TOUCH_AFFINE_XX}f, ${TOUCH_AFFINE_XY}f, ${TOUCH_AFFINE_XC}f, ${TOUCH_AFFINE_YX}f, ${TOUCH_AFFINE_YY}f, ${TOUCH_AFFINE_YC}f); cyd::touch_guard.configure(${TOUCH_MOVE_LIMIT_PX}, ${TOUCH_MIN_PRESS_MS}); id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(display_dimmed) = false; - lambda: |- auto &settings = screen_settings::current; @@ -489,11 +490,11 @@ api: then: - lambda: |- const auto &cfg = screen_settings::current; - ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u dimmed=%d", + ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u use_idle_ms=%u dimmed=%d", cfg.standby_enabled, cfg.standby_seconds, cfg.brightness, cfg.standby_brightness, cfg.night_enabled, cfg.night_start, cfg.night_end, cfg.night_brightness, cfg.show_clock, cfg.clock_24h, cfg.home_on_standby, - (unsigned)(millis() - id(last_touch_ms)), id(display_dimmed)); + (unsigned)(millis() - id(last_touch_ms)), (unsigned)(millis() - id(last_use_ms)), id(display_dimmed)); ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page), runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); lv_area_t nav, grid; @@ -531,6 +532,8 @@ api: then: - lambda: |- if (page < 0) { id(go_home).execute(); return; } + // Opened for someone to look at: Back to page 1 counts from now, as after a touch. + id(last_use_ms) = millis(); id(wake_display).execute(); settings_screen::open((uint8_t) page); ESP_LOGI("settings", "page %d open from Home Assistant", page); @@ -630,19 +633,7 @@ interval: return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL); then: - script.execute: dim_display - # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps - # showing what someone looked at minutes ago; after this long the screen is a screen again. - # Independent of standby, which may be off or much later. - - if: - condition: - lambda: |- - if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; - if (id(display_dimmed)) return false; - bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || - (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); - return away && (millis() - id(last_touch_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; - then: - - script.execute: go_home + - script.execute: back_to_page_1_when_due time: - platform: homeassistant @@ -707,11 +698,18 @@ globals: type: std::string restore_value: no + # Two clocks. last_touch_ms is the standby time: a touch, Wake, an alert ending and Auto standby on restart it. + # last_use_ms is Back to page 1 (firmware 0.2.56+): only a touch, or Home Assistant opening the settings page. - id: last_touch_ms type: uint32_t restore_value: no initial_value: '0' + - id: last_use_ms + type: uint32_t + restore_value: no + initial_value: '0' + # Debounce for do_tile_action: this resistive XPT2046 panel sometimes gives # multiple separate press/release cycles for one physical touch (noise in # the resistive layer), causing the same HA action to fire multiple times @@ -1403,6 +1401,7 @@ touchscreen: on_touch: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = true; cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id); screen_calibration::press(); @@ -1410,6 +1409,7 @@ touchscreen: on_update: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); // Only the contact that started the touch counts; the guard ignores other ids. for (const auto &point : touches) { cyd::touch_guard.update(point.x, point.y, point.id); @@ -1417,6 +1417,7 @@ touchscreen: on_release: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = false; screen_calibration::release(id(ts_touch).filtered_raw_x(), id(ts_touch).filtered_raw_y()); @@ -3515,6 +3516,7 @@ script: then: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); static unsigned test_page=0; id(tile_page) = runtime_tiles::enabled ? test_page++ % runtime_tiles::page_count() : 1; - script.execute: show_tile_page @@ -3645,6 +3647,24 @@ script: - lambda: 'id(tile_page) = 0;' - script.execute: show_tile_page + # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps + # showing what someone looked at minutes ago; after this long the screen is a screen again. + # Independent of standby, which may be off or much later; paused while the screen is in standby. + # The time runs from the last touch (last_use_ms, firmware 0.2.56+): Wake, an alert or Auto standby + # light the screen and restart the standby time, but nobody used a page. Checked every second and by Wake. + - id: back_to_page_1_when_due + then: + - if: + condition: + lambda: |- + if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; + if (id(display_dimmed)) return false; + bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || + (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); + return away && (millis() - id(last_use_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; + then: + - script.execute: go_home + # ---------- ALERT (HA action show_alert) ---------- # The screen wakes, keeps its normal brightness and shows the card until OK or the # timeout (0: until OK); the standby interval waits on alert_active. A new alert @@ -4483,11 +4503,12 @@ button: entity_category: config on_press: - lambda: 'if (runtime_tiles::enabled) screen_calibration::begin();' - # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is a tap: it lights a dimmed - # screen and counts the standby time from now. Sleep is the standby time running out, right away - # and also with Auto standby off; it holds until a tap, Wake or an alert, and closes an alert that - # is up. Neither saves anything, so an automation may press them on every motion. No - # entity_category: they are controls, not settings. + # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is light, not a tap (0.2.56+): it + # lights a dimmed screen and counts the standby time from now, while Back to page 1 keeps counting + # from the last touch, so Wake on every motion no longer holds a card or page 2 up. Sleep is the + # standby time running out, right away and also with Auto standby off; it holds until a tap, Wake + # or an alert, and closes an alert that is up. Neither saves anything, so an automation may press + # them on every motion. No entity_category: they are controls, not settings. - platform: template id: wake_button name: "Wake" @@ -4499,6 +4520,8 @@ button: lambda: 'return id(display_dimmed);' then: - script.execute: wake_display + # A page whose time ran out during standby: light up on page 1, not on the old page first. + - script.execute: back_to_page_1_when_due else: - lambda: 'id(last_touch_ms) = millis();' - platform: template diff --git a/packages/guition.yaml b/packages/guition.yaml index 4b9750b..b4ce68c 100644 --- a/packages/guition.yaml +++ b/packages/guition.yaml @@ -3,7 +3,7 @@ # Source profile for packages/guition.yaml (tools/generate_packages.py); see docs/GUITION.md. # A screen gets its tiles from the ESP Screen Manager add-on while it runs. The CYD is its own profile. substitutions: - SCREEN_FIRMWARE_VERSION: "0.2.55" + SCREEN_FIRMWARE_VERSION: "0.2.56" # 0: no drift limit; LVGL decides, releasing inside the tile is a tap, leaving it is not # (like iOS). The CYD keeps a limit because its resistive panel jumps. TOUCH_MOVE_LIMIT_PX: "0" @@ -146,6 +146,7 @@ esphome: } } id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(display_dimmed) = false; - lambda: |- auto &settings = screen_settings::current; @@ -376,11 +377,11 @@ api: then: - lambda: |- const auto &cfg = screen_settings::current; - ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u dimmed=%d", + ESP_LOGI("ui_diag", "settings standby=%d timeout=%d brightness=%d dim=%d night=%d start=%d end=%d night_dim=%d clock=%d clock24=%d home=%d idle_ms=%u use_idle_ms=%u dimmed=%d", cfg.standby_enabled, cfg.standby_seconds, cfg.brightness, cfg.standby_brightness, cfg.night_enabled, cfg.night_start, cfg.night_end, cfg.night_brightness, cfg.show_clock, cfg.clock_24h, cfg.home_on_standby, - (unsigned)(millis() - id(last_touch_ms)), id(display_dimmed)); + (unsigned)(millis() - id(last_touch_ms)), (unsigned)(millis() - id(last_use_ms)), id(display_dimmed)); ESP_LOGI("ui_diag", "navigation page=%d runtime_detail=%d", id(tile_page), runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); ESP_LOGI("ui_diag", "rotation=%u actual=%u", (unsigned)runtime_tiles::rotation, (unsigned)id(screen_lvgl).get_rotation()); @@ -419,6 +420,8 @@ api: then: - lambda: |- if (page < 0) { id(go_home).execute(); return; } + // Opened for someone to look at: Back to page 1 counts from now, as after a touch. + id(last_use_ms) = millis(); id(wake_display).execute(); settings_screen::open((uint8_t) page); ESP_LOGI("settings", "page %d open from Home Assistant", page); @@ -518,19 +521,7 @@ interval: return (millis() - id(last_touch_ms)) > (screen_settings::current.standby_seconds * 1000UL); then: - script.execute: dim_display - # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps - # showing what someone looked at minutes ago; after this long the screen is a screen again. - # Independent of standby, which may be off or much later. - - if: - condition: - lambda: |- - if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; - if (id(display_dimmed)) return false; - bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || - (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); - return away && (millis() - id(last_touch_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; - then: - - script.execute: go_home + - script.execute: back_to_page_1_when_due time: - platform: homeassistant @@ -595,11 +586,18 @@ globals: type: std::string restore_value: no + # Two clocks. last_touch_ms is the standby time: a touch, Wake, an alert ending and Auto standby on restart it. + # last_use_ms is Back to page 1 (firmware 0.2.56+): only a touch, or Home Assistant opening the settings page. - id: last_touch_ms type: uint32_t restore_value: no initial_value: '0' + - id: last_use_ms + type: uint32_t + restore_value: no + initial_value: '0' + # Debounce for do_tile_action: protects against repeated events from # multiple separate press/release cycles for one physical touch (noise in # the resistive layer), causing the same HA action to fire multiple times @@ -1272,6 +1270,7 @@ touchscreen: on_touch: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = true; cyd::touch_guard.begin(millis(), touch.x, touch.y, touch.id); cyd::edge_swipe.begin(touch.x, touch.y, static_cast(id(screen_lvgl).get_rotation())); @@ -1279,6 +1278,7 @@ touchscreen: on_update: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); // Only the contact that started the touch counts; the guard ignores other ids. for (const auto &point : touches) { // Trace every sample of an edge touch: the log then shows how often the panel delivers. @@ -1306,6 +1306,7 @@ touchscreen: on_release: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); id(touch_down) = false; if (cyd::edge_swipe.armed() && cyd::edge_swipe.inward() > 0) ESP_LOGI("touch", "edge swipe not fired: %d px inward, %d px vertical", cyd::edge_swipe.inward(), cyd::edge_swipe.sideways()); @@ -3502,6 +3503,7 @@ script: then: - lambda: |- id(last_touch_ms) = millis(); + id(last_use_ms) = millis(); static unsigned test_page=0; id(tile_page) = runtime_tiles::enabled ? test_page++ % runtime_tiles::page_count() : 1; - script.execute: show_tile_page @@ -3644,6 +3646,24 @@ script: - lambda: 'id(tile_page) = 0;' - script.execute: show_tile_page + # Back to page 1 by itself (0.2.44+). A card, a settings page or a second page left open keeps + # showing what someone looked at minutes ago; after this long the screen is a screen again. + # Independent of standby, which may be off or much later; paused while the screen is in standby. + # The time runs from the last touch (last_use_ms, firmware 0.2.56+): Wake, an alert or Auto standby + # light the screen and restart the standby time, but nobody used a page. Checked every second and by Wake. + - id: back_to_page_1_when_due + then: + - if: + condition: + lambda: |- + if (!runtime_tiles::auto_home || id(touch_down) || id(calibration_active) || id(alert_active)) return false; + if (id(display_dimmed)) return false; + bool away = settings_screen::visible() || !id(active_entity).empty() || id(tile_page) != 0 || + (runtime_tiles::detail_root && !lv_obj_has_flag(runtime_tiles::detail_root, LV_OBJ_FLAG_HIDDEN)); + return away && (millis() - id(last_use_ms)) > (uint32_t) runtime_tiles::auto_home_seconds * 1000UL; + then: + - script.execute: go_home + # ---------- ALERT (HA action show_alert) ---------- # The screen wakes, keeps its normal brightness and shows the card until OK or the # timeout (0: until OK); the standby interval waits on alert_active. A new alert @@ -4515,11 +4535,12 @@ text: internal: ${DASHBOARD_INBOX_INTERNAL} button: - # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is a tap: it lights a dimmed - # screen and counts the standby time from now. Sleep is the standby time running out, right away - # and also with Auto standby off; it holds until a tap, Wake or an alert, and closes an alert that - # is up. Neither saves anything, so an automation may press them on every motion. No - # entity_category: they are controls, not settings. + # Wake and Sleep for Home Assistant automations (0.2.45+). Wake is light, not a tap (0.2.56+): it + # lights a dimmed screen and counts the standby time from now, while Back to page 1 keeps counting + # from the last touch, so Wake on every motion no longer holds a card or page 2 up. Sleep is the + # standby time running out, right away and also with Auto standby off; it holds until a tap, Wake + # or an alert, and closes an alert that is up. Neither saves anything, so an automation may press + # them on every motion. No entity_category: they are controls, not settings. - platform: template id: wake_button name: "Wake" @@ -4531,6 +4552,8 @@ button: lambda: 'return id(display_dimmed);' then: - script.execute: wake_display + # A page whose time ran out during standby: light up on page 1, not on the old page first. + - script.execute: back_to_page_1_when_due else: - lambda: 'id(last_touch_ms) = millis();' - platform: template diff --git a/screen_manager/CHANGELOG.md b/screen_manager/CHANGELOG.md index 5b75f7e..5cff1d1 100644 --- a/screen_manager/CHANGELOG.md +++ b/screen_manager/CHANGELOG.md @@ -1,3 +1,14 @@ +## 0.2.65 (firmware 0.2.56) + +Wake lights the screen, and ESP Screens lets you pick the screen. + +- **Wake is for the light.** The **Wake** button in Home Assistant still turns a screen in standby up to its normal brightness, brings back the second hand of an analog clock and starts the standby time again. It no longer counts as a touch for **Back to page 1**: that keeps counting from the last time someone touched the screen. An automation that presses Wake on every motion used to keep an open card or page 2 up for as long as someone moved in the room; now the screen goes back to page 1 on time. +- **Straight to page 1 after standby.** When the Back to page 1 time ran out while the screen was in standby, Wake lights it up on page 1 at once, instead of showing the old page for a moment first. With time left, the page stays. +- **Only a touch counts.** An alert that closes by itself and turning Auto standby on also start the standby time again, but not the Back to page 1 time. Opening the settings page from Home Assistant (`open_settings`) still counts, so that page stays open. +- **ESP Screens opens without a chosen screen.** It used to open the first screen in the list; now you pick one. Until then the page says **Choose a screen**, and with no screens yet it still offers to install one. +- The Claude skill describes the new Wake. Install it again from Settings → Claude to get it. +- Needs firmware 0.2.56 for Wake: press **Update** on the screen. The ESP Screens change works right after updating the app. Includes everything from 0.2.64. + ## 0.2.64 (firmware 0.2.55) A long alert title stays on its own line. diff --git a/screen_manager/DOCS.md b/screen_manager/DOCS.md index 175c5dd..4ac4111 100644 --- a/screen_manager/DOCS.md +++ b/screen_manager/DOCS.md @@ -35,5 +35,6 @@ about a second and a half, or put the built-in **Settings** card on a page. What there appears here within a second, and the other way around. In Home Assistant every screen also has a **Wake** and a **Sleep** button (firmware 0.2.45 or -newer). Press them from an automation with `button.press`: Wake does what a tap does, Sleep puts -the screen in standby right away, also with Auto standby off. +newer). Press them from an automation with `button.press`: Wake lights the screen up and restarts the +standby time, Sleep puts the screen in standby right away, also with Auto standby off. Wake is not a +touch, so an open card or a later page still goes back to page 1 on time (firmware 0.2.56 or newer). diff --git a/screen_manager/app/claude_skill.py b/screen_manager/app/claude_skill.py index b5160b8..ef88c67 100644 --- a/screen_manager/app/claude_skill.py +++ b/screen_manager/app/claude_skill.py @@ -257,7 +257,7 @@ Every screen has these entities in Home Assistant, on its ESPHome device. `_wake` | Wakes the screen the way a tap does and counts the standby time from that moment; a screen that is already on only restarts that count. Firmware {WAKE_SLEEP_MIN_FIRMWARE} or newer. | +| `button._wake` | Lights the screen up to its normal brightness and counts the standby time from that moment; a screen that is already on only restarts that count. Firmware {WAKE_SLEEP_MIN_FIRMWARE} or newer. Wake is not a touch: from firmware 0.2.56 an open card or a later page still goes back to page 1 on its own time, and a screen whose time ran out during standby wakes on page 1. | | `button._sleep` | Puts the screen in standby right away, also with Auto standby off, and closes an alert that is showing. It stays in standby until someone taps it, Wake is pressed or an alert arrives. Firmware {WAKE_SLEEP_MIN_FIRMWARE} or newer. | | `switch._auto_standby` | On: the screen dims after the standby time without a touch. Off: the screen wakes up and stays on, except after Sleep, which holds until Wake, a tap or an alert. Firmware {AUTO_STANDBY_MIN_FIRMWARE} or newer. | | `number._standby_after` | Seconds without a touch before standby, 60 to 86400. | @@ -268,7 +268,7 @@ Every screen has these entities in Home Assistant, on its ESPHome device. `_night_mode` | Night mode: the night brightness between the two times below. Firmware {SETTING_ENTITIES_MIN_FIRMWARE} or newer, like every row below it. | | `time._night_starts`, `time._night_ends` | The night hours; set them with `time.set_value`. | | `switch._24_hour_clock` | On: 24-hour clock. Off: 12-hour clock. | -| `switch._back_to_page_1` | On: after `number._back_to_page_1_after` seconds without a touch (30 to 3600) the screen closes a card and goes back to page 1. | +| `switch._back_to_page_1` | On: after `number._back_to_page_1_after` seconds without a touch (30 to 3600) the screen closes a card and goes back to page 1. Pressing Wake, an alert or Auto standby don't count as a touch. | | `switch._back_to_page_1_on_standby` | On: going into standby also goes back to page 1. | | `switch._swipe_between_pages` | On: swipe between pages. | | `select._rotation` | Guition only: `0°`, `90°`, `180°` or `270°`. | diff --git a/screen_manager/app/core.py b/screen_manager/app/core.py index 7517f1f..edc633c 100644 --- a/screen_manager/app/core.py +++ b/screen_manager/app/core.py @@ -17,7 +17,7 @@ WEEKDAYS = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'] REPO = 'https://github.com/MaxGramser/homeassistant_espscreen' REFS = {'cyd': 'main', 'guition': 'main'} # Firmware shipped with this app release; screens below it get an update offer. -FIRMWARE_VERSION = '0.2.55' +FIRMWARE_VERSION = '0.2.56' # The Auto standby switch a screen offers Home Assistant automations. AUTO_STANDBY_MIN_FIRMWARE = '0.2.41' # The settings page the screen opens itself, and the screen.settings tile that opens it. diff --git a/screen_manager/app/static/app.js b/screen_manager/app/static/app.js index 6ef112f..122ffa3 100644 --- a/screen_manager/app/static/app.js +++ b/screen_manager/app/static/app.js @@ -76,6 +76,7 @@ function select(id) { $("#open-override").disabled = !screen.update?.profile; $("#editor").hidden = false; $("#empty").hidden = true; + $("#choose").hidden = true; $("#dirty").textContent = "All saved"; $("#save-detail").textContent = "Changes apply without reflashing."; renderScreens(); @@ -494,6 +495,12 @@ function renderPending() { } function renderScreens() { renderPending(); + // ESP Screens opens without a chosen screen (app 0.2.65+): the owner picks one. Until then the right side asks + // for that, or offers the install while there are no screens yet. + if (!selected) { + $("#choose").hidden = !inventory.screens.length; + $("#empty").hidden = !!inventory.screens.length; + } // Keep an open address form alive across the periodic refresh. if ($("#screens .screen-host")) { renderUpdates(); @@ -2059,7 +2066,6 @@ async function refresh(full = true) { if (full) renderClaude(); if (selected) { settleSettings(); renderSettings(); } if (firstCatalogue && selected && layout && !drag.active && !chipDrag.active) { renderTopbar(); renderTiles(); renderResults(); } - if (!selected && inventory.screens.length) select(inventory.screens[0].id); if ($("#alerts-dialog").open) renderAlertScreens(); } catch { $("#connection").textContent = @@ -2391,7 +2397,6 @@ function applyLive(data) { $("#connection").classList.toggle("online", inventory.connected); renderScreens(); if (selected) { settleSettings(); renderSettings(); } - if (!selected && inventory.screens.length) select(inventory.screens[0].id); } function listen() { if (stream || typeof EventSource === "undefined") return; diff --git a/screen_manager/app/static/index.html b/screen_manager/app/static/index.html index 579205c..a21898e 100644 --- a/screen_manager/app/static/index.html +++ b/screen_manager/app/static/index.html @@ -42,7 +42,13 @@
-
+ + + ', PAGE, re.S) + self.assertTrue(choose, 'hidden until the first inventory') + self.assertIn('

Choose a screen

', choose[1]) + self.assertNotIn('