mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-07 06:59:46 +00:00
feat(card): the LED strip tool in the Devices editor (#780)
Stage 4 of #780 (ТЗ §4–§5). «LED strip» next to «Add» draws a chain with clean clicks only (pan, pinch, a second finger, cancel and the synthetic click after navigation add nothing), snaps to the grid and to physical wall faces / zero-wall axes, stops at the first face of masonry, partitions, columns and windows (doors, gates and passages are cut by geometry), Shift gives 45°. Ctrl+Z removes the chain's own point first, Esc finishes, a double click or a click on the first point (≥3 vertices) closes; fewer than two distinct points write nothing. A finished strip opens the device picker (lights first, taken markers explained, «New device…» binds in that dialog's own write, «Later» keeps unbound geometry). A selected strip shows its vertex handles (a drag re-checks both neighbours and the whole path) and a new Devices tray branch: device settings, bind/change, unbind, show as icon, delete. The device dialog gets the representation section: show as strip (restores a hidden shape at once or draws one for this marker, behind the dialog's own save/discard guard), show as icon, unbind/delete for a hidden shape. Every geometry or representation change is one optimistic write and one LED command of the device history; Undo/Redo restores only its own strip record and refuses when a newer change sits on it. A rebinding renames the link in the marker save, a deleted marker leaves an unbound strip, a bound marker may not move to another space. Plan/Background show strips as a passive translucent mark. The tool, its `led` dictionary (en static, ru/de/fr lazy) and placement geometry are a new lazy `led-strip-editor` chunk (9.5 KB gzip), loaded only on the tool, an editable strip in the shown space or a strip device's dialog. The initial graph gets the loader and delegation only (src/led-strip-card.ts); the lazy editor graph +122 B, inside its ceiling. Mutant anchors follow the moved code (marker dialog guard, static LED layer). Issue: #780 User-Visible: no
This commit is contained in:
@@ -6084,9 +6084,9 @@ const MUTANT_DEFINITIONS = [
|
||||
patches: [{
|
||||
file: 'custom_components/houseplan/validation.py',
|
||||
find: ' extra=vol.ALLOW_EXTRA, # unknown (legacy) keys do not break loading\n'
|
||||
+ ' ),\n canonicalize_config_geometry,\n _config_wall_segment_invariants,\n)',
|
||||
+ ' ),\n canonicalize_config_geometry,\n _config_wall_segment_invariants,\n',
|
||||
replace: ' extra=vol.ALLOW_EXTRA, # unknown (legacy) keys do not break loading\n'
|
||||
+ ' ),\n lambda value: value,\n _config_wall_segment_invariants,\n)',
|
||||
+ ' ),\n lambda value: value,\n _config_wall_segment_invariants,\n',
|
||||
}],
|
||||
},
|
||||
{
|
||||
@@ -7387,7 +7387,7 @@ const MUTANT_DEFINITIONS = [
|
||||
find: ' ${passageGlowTunnels}\n'
|
||||
+ ' <g class="decorlayer" pointer-events="none">${decorImages}</g>\n'
|
||||
+ ' <g class="hp-stairs-layer" pointer-events="none">${stairShapes}</g>\n'
|
||||
+ ' ${glowPools}\n ${wallUnion',
|
||||
+ ' ${glowPools}\n ${leds.size',
|
||||
replace: ' ${passageGlowTunnels}\n'
|
||||
+ ' ${!space.bg && !disp.showNames ? svg`<g class="room-svg-labels" pointer-events="none">${space.rooms.map((room) => {\n'
|
||||
+ ' const center = roomCenter(room);\n'
|
||||
@@ -7397,7 +7397,7 @@ const MUTANT_DEFINITIONS = [
|
||||
+ ' <g class="decorlayer" pointer-events="none">${decorImages}</g>\n'
|
||||
+ ' <g class="hp-stairs-layer" pointer-events="none">${stairShapes}</g>\n'
|
||||
+ ' ${glowPools}\n'
|
||||
+ ' ${wallUnion',
|
||||
+ ' ${leds.size',
|
||||
}],
|
||||
},
|
||||
{
|
||||
@@ -13741,8 +13741,9 @@ const MUTANT_DEFINITIONS = [
|
||||
+ 'Перевёрнутое условие закрывает «грязный» диалог молча и спрашивает у чистого',
|
||||
patches: [{
|
||||
file: 'src/editors/marker-dialog.ts',
|
||||
find: " if (!edit || !dirty) { forgetMarkerBaseline(this.host); this._closeMarkerDialog(); return; }",
|
||||
replace: " if (!edit || dirty) { forgetMarkerBaseline(this.host); this._closeMarkerDialog(); return; }",
|
||||
// #780: the guard is the dialog's shared `leave` (close and the LED representation switch).
|
||||
find: " if (edit && dirty && !await this.host._confirmDanger({",
|
||||
replace: " if ((!edit || !dirty) && !await this.host._confirmDanger({",
|
||||
}],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user