Free drag & drop with fixed positions, empty cells and kept pages (0.2.31)

Tiles get an absolute grid slot instead of a packed order: a tile lands exactly
where it is dropped, dropping on another tile swaps the two, everything else
stays put, and empty cells and empty pages persist. The mockup previews the
result while dragging, a new page waits below the last one, "Pagina toevoegen"
keeps an empty page, empty cells accept the next tile from the picker, and the
mouse no longer selects text while dragging.

Storage and protocol stay version 1: `tiles[].slot` (0-47) and `pages` (1-8)
are additive, the layout message carries `slots` and `pages`. Firmware 0.2.26
places tiles on those slots (`place()` next to `pack()`); older firmware packs
in order as before and the editor says so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-14 13:00:39 +02:00
parent ad0385d60f
commit 95cdfa30cf
19 changed files with 676 additions and 140 deletions
+15 -5
View File
@@ -106,9 +106,17 @@ wifi-slaapvertraging op Home Assistant.
Selecteer je scherm, vul de titel in en zoek entiteiten. De kiezer heeft
domeinfilters met gekleurde iconen. Je kunt maximaal twintig tegels toevoegen.
Het schermvoorbeeld toont hun plaats: twee kolommen, zes tegels per pagina.
Sleep een tegel naar een andere tegel om te ordenen. Klik op een tegel voor
een eigen naam, de pijltjes voor volgorde en **Bediening & weergave instellen**:
Het schermvoorbeeld toont hun plaats: twee kolommen, zes plekken per pagina,
maximaal acht pagina's. Elke tegel heeft een vaste plek die alleen verandert als
jij hem versleept; lege plekken blijven leeg, waar je ze ook laat. Sleep een tegel
op een lege plek en hij staat daar; sleep hem op een andere tegel en die twee
wisselen (de ander neemt de vrijgekomen plek, of anders de dichtstbijzijnde vrije
plek); de rest blijft staan. Tijdens het slepen zie je in het voorbeeld al waar
alles komt; onder de laatste pagina staat dan een lege pagina klaar. **Pagina
toevoegen** maakt een lege pagina die bewaard blijft; een lege pagina heeft
**Pagina weghalen**. Klik op een lege plek om de volgende tegel uit de kiezer
daar te zetten. Met de pijltjestoetsen verplaats je een gefocuste tegel.
Klik op een tegel voor een eigen naam en **Bediening & weergave instellen**:
klikgedrag, een mini-slider, een grote waarde, een grafiek (sensoren), een
weersvoorspelling (weer) of de breedte **Dubbelbreed**. Een dubbelbrede tegel van
een klimaat, schakelaar, lamp, ventilator, stofzuiger, zonwering, mediaspeler,
@@ -122,8 +130,10 @@ zwenkstanden. De ingebouwde **Klok**
staat bovenaan de kiezer; zon, kookwekkers en personen vind je via de filters. Kies bij
**Pastel achtergrond** een eigen kleur met donkere tekst; **Standaard** herstelt
de normale weergave en **Geen** laat de kaart weg, zodat de inhoud even groot
direct op de schermachtergrond staat (firmware 0.2.16+). Hiervoor is firmware 0.2.10+ nodig. Een lege
tegel brengt je naar de zoekbalk; toevoegen vult de eerstvolgende vrije positie.
direct op de schermachtergrond staat (firmware 0.2.16+). Hiervoor is firmware 0.2.10+ nodig.
Toevoegen zonder gekozen plek vult de eerste vrije plek. Vaste plekken en lege
plekken werken op het scherm vanaf firmware 0.2.26; oudere firmware schuift de
tegels aan tot de eerste vrije plek, de editor meldt dat onder het voorbeeld.
Het voorbeeld toont de indeling, geen live sensorwaarden.
Klik **Opslaan & naar scherm** om je wijzigingen door te sturen.
+22
View File
@@ -177,6 +177,28 @@ staan iconen in de browser uit het midden); draai daarna `generate_packages.py`.
De substituties `MDI_GLYPH_*` zijn vervallen: `TILEn_ICON` in handmatige
profielen moet uit de set komen. Geen gewijzigde preferences of sleutels.
### Compatibiliteit 0.2.31 / firmware 0.2.26
Opslagversie en tegelprotocol blijven 1. `tiles[].slot` is additief: de absolute plek
van een tegel (pagina × 6 + rij × 2 + kolom, 0–47, `MAX_SLOTS` in `core.py`); een
dubbelbrede tegel staat op een even plek en bedekt ook de plek rechts ervan. Lege plekken
zijn toegestaan. `validate_layout` eist plekken voor alle tegels of voor geen: zonder
plekken (oude editor, oude opslag) krijgt de indeling de plekken van de oude
volgorde-packing (`pack_slots`, hetzelfde als `pack()` in de firmware), zodat er op
het scherm niets verandert; met plekken worden overlap, oneven dubbelbreed en bereik
geweigerd en de tegels op plek gesorteerd. `save()` herhaalt de packing na het
terugzetten van opgeslagen opties (die kunnen een tegel verbreden). `pages` (1–8) is
een optioneel, additief veld: pagina's die de gebruiker leeg wil houden.
Op de draad krijgt het layoutbericht `slots` (één plek per entity, in dezelfde
volgorde) en `pages`. Firmware 0.2.26 (`Model::set_layout` met posities, `place()`
naast het oude `pack()`, `MAX_PAGES` 8) tekent de tegels op die plekken; een wijziging
van alleen plekken (`moved`) herplaatst de pagina's zonder tegelstatussen te wissen.
Oudere firmware negeert beide velden en pakt de entities in volgorde; omdat de
entities op plek gesorteerd zijn is dat de oude weergave zonder gaten, daarom geen
`min_firmware`. De editor meldt het (`has_gaps`/`hasGaps`) bij firmware < 0.2.26. Geen
gewijzigde preferences of sleutels.
### Compatibiliteit 0.2.30 / firmware 0.2.25
Alleen de editor: het statusbolletje in de schermlijst is een eigen `span.dot`
+44
View File
@@ -0,0 +1,44 @@
# Testresultaten app 0.2.31 / firmware 0.2.26 (2026-09-14)
Vrij slepen in de editor met vaste plekken, lege plekken en lege pagina's;
firmware 0.2.26 tekent de tegels op die plekken.
## Wat veranderde
- `core.py`: `SLOTS_PER_PAGE`/`MAX_PAGES`/`MAX_SLOTS`, `pack_slots`, `has_gaps`;
`validate_layout` geeft elke tegel een `slot` (oude volgorde-packing zonder plekken,
anders validatie op bereik, even plek voor dubbelbreed en overlap, gesorteerd) en
accepteert `pages` (1–8). `server.py`: `slots` en `pages` in het layoutbericht;
`save()` pakt opnieuw na het terugzetten van opgeslagen opties en valideert nogmaals.
- `runtime_model.h`: `Model.slots`/`explicit_slots`/`pages`, `set_layout(..., positions,
moved)`, `place()`; `runtime_tiles.h`: parser leest `slots`/`pages`, `page_count()` en
`place_page()` gebruiken `place()`. Versie 0.2.26 in beide profielen en pakketten.
- `app.js`: grid-model (`arrange`/`commit`/`placeTile`, `nearestFree`, `firstFree`),
hover-preview tijdens slepen (`setTarget` rendert het resultaat, `slotAt` kiest de
cel op afstand), pointer capture vanaf pointerdown en op `documentElement` tijdens de
sleep (de mockup wordt herrenderd), lege cellen als knoppen (`insertAt`), pagina's
toevoegen/weghalen, pijltjestoetsen, hint voor firmware < 0.2.26. `style.css`:
`user-select: none` op editor en kiezer, `.preview-cell`, `.placeholder`, `.new-page`.
## Geautomatiseerd
- Python: 91 tests OK (nieuw `tests/test_positions.py`: packing zonder plekken, expliciete
plekken met gaten en sortering, geweigerde overlap/oneven/bereik/gemengd, `pages`,
`slots`/`pages` op de draad, oude opslag en oude editor). `generate_packages.py --check` groen.
- C++ (clang++ -std=c++17 -Wall -Wextra -Werror -I.): alle `tests/*.cpp` PASS;
`test_runtime_model` dekt validatie van posities, `moved` zonder statusverlies,
even plek voor dubbelbreed, lege tussenpagina, `pages`, terugval zonder plekken.
- ESPHome compile (bench-pakketten met lokale componenten): `easy-guition-device.yaml`
SUCCESS (RAM 31,9%, flash 18,3%), `easy-cyd-device.yaml` SUCCESS (RAM 30,9%, flash 76,1%).
- Lokale add-on (devserver met nep-HA, echte pointer-events in de browser): twee enkele
tegels, tweede dubbelbreed → blijft op rij twee, gat op plek 2; entiteit uit de kiezer
in het gat gesleept → plek 2, geen tekstselectie; hover-preview toont de nieuwe pagina
met placeholder; enkele tegel op dubbelbrede gedropt → wissel; pagina toevoegen/weghalen;
pijltjestoetsen 6 → 5 → 6 met focus; lege plek klikken + kiezer → tegel op die plek;
opslaan verstuurt `slots [0,2,3,6]` en state-indexen in plekvolgorde.
## Nog niet geverifieerd
- Op echte hardware: de indeling met gaten en een lege pagina op CYD en Guition na de
firmware-update (Max test via GitHub-release → add-on → firmware bouwen in ESP Screens).
- Touch-slepen (hold 260 ms) op een telefoon in de HA-app.