Give each screen its own YAML override that survives updates (0.2.61)

Override YAML on a screen edits <name>.local.yaml, a package loaded after
the shared board package. New profiles get an empty one; an existing
profile is attached on the first save without reformatting the file. The
editor validates YAML, refuses the managed sections and substitutions,
and Save & check runs ESPHome's full validation of the complete profile.

The example uses !extend: ESPHome appends package lists instead of
merging them by id, so a bare id added a second display without a
platform and failed the build. An override is 12 KB at most and a
too-large body answers as JSON instead of a bare 413. The sidecar is
written before the profile includes it, and a symlinked sidecar is
refused. Firmware stays 0.2.52.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Max Gramser
2026-09-17 08:23:13 +02:00
parent 87b2082f81
commit 8a587303d7
12 changed files with 694 additions and 4 deletions
+43 -1
View File
@@ -57,7 +57,10 @@
<p class="eyebrow" id="screen-name"></p>
<h2>Make it your screen</h2>
</div>
<span id="delivery" class="badge"></span>
<div class="editor-head-actions">
<button id="open-override" class="quiet mini" type="button">Override YAML</button>
<span id="delivery" class="badge"></span>
</div>
</div>
<section class="topbar-editor" id="topbar" aria-labelledby="topbar-title">
<div class="section-title">
@@ -370,6 +373,45 @@
<p id="firmware-status" role="status"></p>
<pre id="firmware-log"></pre>
</dialog>
<dialog id="override-dialog" class="override-dialog" aria-labelledby="override-title">
<div class="dialog-head">
<div>
<p class="eyebrow">ADVANCED · LOCAL OVERRIDE</p>
<h2 id="override-title">Override YAML</h2>
</div>
<button id="close-override" class="quiet" type="button" aria-label="Close">✕</button>
</div>
<p class="override-intro">
This small file is yours. It is loaded after the shared screen package and stays in place when
ESP Screen Manager updates. Change hardware-specific details here, such as a display model.
</p>
<div class="override-notice">
<span class="override-icon" aria-hidden="true">⌘</span>
<div>
<strong>What is safe to change?</strong>
<span>Display, touchscreen, substitutions, pins and other device details. Name, Wi-Fi, API, OTA and package links remain managed.</span>
</div>
</div>
<div class="override-file-row">
<span id="override-file" class="override-file"></span>
<span id="override-state" class="badge"></span>
</div>
<div class="yaml-editor" id="yaml-editor-wrap">
<div id="override-gutter" class="yaml-gutter" aria-hidden="true">1</div>
<textarea id="override-editor" spellcheck="false" autocapitalize="off" autocomplete="off" autocorrect="off"
aria-label="Local override YAML" placeholder="# Example\ndisplay:\n - id: !extend my_display\n model: ST7789V"></textarea>
</div>
<div class="override-tools">
<button id="override-example" class="quiet mini" type="button">Use example</button>
<button id="override-empty" class="quiet mini" type="button">Clear</button>
<span id="override-count" class="hint"></span>
</div>
<p id="override-status" class="override-status" role="status"></p>
<div class="yaml-actions override-actions">
<button id="override-check" class="quiet" type="button">Save & check</button>
<button id="override-save" type="button">Save override</button>
</div>
</dialog>
<dialog id="tile-sheet" class="tile-sheet" aria-label="Configure tile"></dialog>
<dialog id="topbar-sheet" class="tile-sheet" aria-label="Top bar"></dialog>
<dialog id="alerts-dialog" class="alerts" aria-label="Alerts">