Fill a blind's slider with its closed part, like its card and Home Assistant's cover dialog (0.2.79)
On the tile (and the strip of a full-page blind) the small slider filled with the open part, while the blind's card draws the blind hanging from the top: a closed blind looked open on one and closed on the other. Now both fill with the closed part and dragging right closes; the text still gives the position (open %). The editor's mockup follows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -848,7 +848,9 @@ inline int slider_value(const Tile &t){
|
||||
auto d=t.domain();float value=0;
|
||||
if(d=="light")value=std::isfinite(t.brightness)?t.brightness/255:0;
|
||||
if(d=="fan")value=std::isfinite(t.percentage)?t.percentage/100:0;
|
||||
if(d=="cover")value=std::isfinite(t.position)?t.position/100:0;
|
||||
// A blind's bar is the blind itself: the closed part is filled, so a closed cover is a full bar, as on its card and in
|
||||
// Home Assistant's own cover dialog (firmware 0.2.66+; before, the bar filled with the open part, the other way round).
|
||||
if(d=="cover")value=std::isfinite(t.position)?(100-t.position)/100:1;
|
||||
if(d=="media_player")value=std::isfinite(t.volume)?t.volume:0;
|
||||
if(d=="number"||d=="input_number") {char *end;float state=strtof(t.state.c_str(),&end);if(end!=t.state.c_str() && t.maximum>t.minimum)value=(state-t.minimum)/(t.maximum-t.minimum);}
|
||||
return std::clamp((int)std::lround(value*1000),0,1000);
|
||||
@@ -864,7 +866,7 @@ inline void commit_slider(unsigned i,int raw){
|
||||
// The slider stays where the finger left it while the light fades towards it (Tile::hold_slider).
|
||||
if(d=="light"){int sent=std::max(3,(int)std::lround(value*255));action("light.turn_on",t.entity,"brightness",std::to_string(sent));t.hold_slider(esphome::millis(),sent);}
|
||||
if(d=="fan"){int sent=(int)std::lround(value*100);action("fan.set_percentage",t.entity,"percentage",std::to_string(sent));t.hold_slider(esphome::millis(),sent);}
|
||||
if(d=="cover")action("cover.set_cover_position",t.entity,"position",std::to_string((int)std::lround(value*100)));
|
||||
if(d=="cover")action("cover.set_cover_position",t.entity,"position",std::to_string(100-(int)std::lround(value*100)));
|
||||
if(d=="media_player"){action("media_player.volume_set",t.entity,"volume_level",std::to_string(value));t.hold_slider(esphome::millis(),value);}
|
||||
if(d=="number"||d=="input_number") {
|
||||
if(!std::isfinite(t.minimum)||!std::isfinite(t.maximum)||t.maximum<=t.minimum||t.step<=0)return;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Test results app 0.2.79 / firmware 0.2.66 (2026-09-18)
|
||||
|
||||
Max, after 0.2.78: "Blinds schuif is andersom in de overlay mode en op de tile (dicht is open bij de ander)", and on the
|
||||
choice: "full closed = volledig ingekleurd voelt logischer". The cover card (0.2.58) draws the blind hanging from the
|
||||
top, as Home Assistant's cover dialog does: the filled part is the closed part. The tile's small slider (and the strip
|
||||
of a full-page blind) filled with the open part. Now both fill with the closed part.
|
||||
|
||||
## What changed
|
||||
|
||||
- `runtime_tiles::slider_value` gives a cover `(100 - position) / 100`; `commit_slider` sends `100 - value` as the
|
||||
position, so dragging right closes. The tile's text still shows the position (open %), as Home Assistant does.
|
||||
- The editor's TileCard fills a cover's mini slider with `100 - current_position`.
|
||||
|
||||
## Automated
|
||||
|
||||
- `tools/check.sh`: Python, C++ 18/18, packages, icons, Vitest 77/77 (a new case: a blind at 30 % open fills 70 %),
|
||||
vue-tsc, build, bundle fresh.
|
||||
- `tools/check.sh --firmware` (ESPHome 2026.6.2): CYD 1,652,384 B = 90.0 % of the 1,835,008 B slot (+0 B against 0.2.78),
|
||||
Guition 2,026,624 B = 24.9 %.
|
||||
|
||||
## Not tested
|
||||
|
||||
- On real hardware: the direction of a drag on a blind's tile slider and the full-page blind strip on both boards.
|
||||
@@ -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.65"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.66"
|
||||
# 0: no drift limit. A press that drifts is still a tap as long as the finger lets go on the tile
|
||||
# (runtime_tiles::event checks where it let go: LVGL keeps the press on the tile and would click it
|
||||
# anywhere), and a quick flick is LVGL's gesture, never a tap (the home_page gesture handler in on_boot).
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.65"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.66"
|
||||
# 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.
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
############################################################
|
||||
|
||||
substitutions:
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.65"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.66"
|
||||
# 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.
|
||||
|
||||
@@ -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.65"
|
||||
SCREEN_FIRMWARE_VERSION: "0.2.66"
|
||||
# 0: no drift limit. A press that drifts is still a tap as long as the finger lets go on the tile
|
||||
# (runtime_tiles::event checks where it let go: LVGL keeps the press on the tile and would click it
|
||||
# anywhere), and a quick flick is LVGL's gesture, never a tap (the home_page gesture handler in on_boot).
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 0.2.79 (firmware 0.2.66)
|
||||
|
||||
A blind's bar reads the same way on the tile and on its card.
|
||||
|
||||
- **The small slider of a blind fills with the closed part.** A closed blind is a full bar, an open one an empty bar, and dragging to the right closes it, as on the blind's card and in Home Assistant's own cover dialog, where the blind hangs down from the top. Before, the tile filled with the open part, so a closed blind looked open next to its card. The editor's mockup draws it the same way. The position in the text stays how far the blind is open, as Home Assistant says it.
|
||||
- Needs firmware 0.2.66: press **Update** on the screen. Includes everything from 0.2.78.
|
||||
|
||||
## 0.2.78 (firmware 0.2.65)
|
||||
|
||||
Fixes from a full test round of 0.2.72 to 0.2.76, a light switch that works in the dark, and a way back to the menu.
|
||||
|
||||
@@ -37,7 +37,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.65'
|
||||
FIRMWARE_VERSION = '0.2.66'
|
||||
# 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.
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<title>ESP Screens</title>
|
||||
<script type="module" crossorigin src="./assets/index-DfYonu9c.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index-Cp1JAouO.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-DUJYFAbE.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: ESP Screen Manager
|
||||
version: "0.2.78"
|
||||
version: "0.2.79"
|
||||
slug: esp_screen_manager
|
||||
description: Choose tiles for your CYD and Guition touchscreen, without reflashing.
|
||||
url: https://github.com/MaxGramser/homeassistant_espscreen
|
||||
|
||||
@@ -61,7 +61,8 @@ const fill = computed(() => {
|
||||
const a = c.a || {};
|
||||
if (domain.value === "light") return c.state === "on" ? (a.brightness !== undefined ? Math.round((a.brightness / 255) * 100) : 100) : 0;
|
||||
if (domain.value === "fan") return c.state === "on" ? (a.percentage ?? 100) : 0;
|
||||
if (domain.value === "cover") return a.current_position ?? (c.state === "open" ? 100 : 0);
|
||||
// A blind's bar fills with its closed part, as on the screen (firmware 0.2.66+) and in Home Assistant's cover dialog.
|
||||
if (domain.value === "cover") return 100 - (a.current_position ?? (c.state === "open" ? 100 : 0));
|
||||
if (domain.value === "media_player") return Math.round((a.volume_level ?? 0) * 100);
|
||||
if (domain.value === "number" || domain.value === "input_number") {
|
||||
const value = Number(c.state), min = Number(a.min ?? 0), max = Number(a.max ?? 100);
|
||||
|
||||
@@ -59,6 +59,11 @@ describe("TileCard", () => {
|
||||
expect(lamp.find(".ic").classes()).toContain("lit");
|
||||
expect(lamp.find(".mini-slider").attributes("style")).toContain("50%");
|
||||
});
|
||||
it("fills a blind's bar with its closed part, like the screen and its card", () => {
|
||||
state.liveStates["cover.c"] = { state: "open", word: "Open", a: { current_position: 30 } };
|
||||
const blind = placed({ entity: "cover.c", name: "", slot: 2, options: { inline: "slider" } });
|
||||
expect(blind.find(".mini-slider").attributes("style")).toContain("70%");
|
||||
});
|
||||
it("draws the large value, the wide card's toggle and an unavailable entity in grey", () => {
|
||||
state.liveStates["sensor.t"] = { state: "1249", word: null, a: { unit_of_measurement: "W" } };
|
||||
const big = placed({ entity: "sensor.t", name: "Power", slot: 0, options: { display: "watch" } });
|
||||
|
||||
Reference in New Issue
Block a user