diff --git a/custom_components/omni_pca/frontend/src/omni-panel-programs.ts b/custom_components/omni_pca/frontend/src/omni-panel-programs.ts index 7effcd5..6b82bb6 100644 --- a/custom_components/omni_pca/frontend/src/omni-panel-programs.ts +++ b/custom_components/omni_pca/frontend/src/omni-panel-programs.ts @@ -441,6 +441,33 @@ export class OmniPanelPrograms extends LitElement { } } + /** Augment a bucket with a "preserve original" option if ``current`` + * isn't represented by any entry. Real-world programs reference object + * indexes far past the discovered range (e.g. raw byte values from + * undecoded extended-output addressing on Omni Pro II — Unit 33025). + * Without this option the form silently coerces such values to the + * first known entry, which looks like the user already selected it. + * + * The synthesized entry is prepended so it's visually distinct (top + * of the list) and labelled to make the situation obvious. + */ + private _bucketWithPreserve( + bucket: NamedObject[] | null, + kind: string, + current: number, + ): NamedObject[] { + const list = bucket ?? []; + if (current === 0) return list; // 0 = "no object", no synth + if (list.some((o) => o.index === current)) return list; + return [ + { + index: current, + name: `(undiscovered ${kind} ${current} — preserve original)`, + }, + ...list, + ]; + } + private _onObjectChange(e: Event): void { const value = parseInt((e.target as HTMLSelectElement).value, 10); if (Number.isFinite(value)) this._patchDraft({ pr2: value }); @@ -965,11 +992,14 @@ export class OmniPanelPrograms extends LitElement { private _renderEventCategoryFields(decoded: DecodedEvent): TemplateResult { if (decoded.category === "button") { + const buttons = this._bucketWithPreserve( + this._objects?.buttons ?? null, "button", decoded.button ?? 0, + ); return html` `; } if (decoded.category === "unit") { + const units = this._bucketWithPreserve( + this._objects?.units ?? null, "unit", decoded.unit ?? 0, + ); return html` `:e.category==="zone"?a` + `}if(e.category==="zone"){let r=this._bucketWithPreserve(this._objects?.zones??null,"zone",e.zone??0);return a` `:e.category==="unit"?a` + `}if(e.category==="unit"){let r=this._bucketWithPreserve(this._objects?.units??null,"unit",e.unit??0);return a` `:e.category==="fixed"?a` + `}return e.category==="fixed"?a` - `}_renderActionSection(e){let r=ae(e.cmd??0),i=r?.ref_kind?this._pickBucket(r.ref_kind):null,s=e.cmd===9;return a` + `}_renderActionSection(e){let r=ae(e.cmd??0),i=r?.ref_kind?this._bucketWithPreserve(this._pickBucket(r.ref_kind),r.ref_kind,e.pr2??0):null,s=e.cmd===9;return a`
Action `:""}
- `}};d.styles=G` + `}};d.styles=W` :host { display: block; min-height: 100vh; diff --git a/dev/artifacts/screenshots/2026-05-16/01-overview.png b/dev/artifacts/screenshots/2026-05-16/01-overview.png index a150fd7..64975cc 100644 Binary files a/dev/artifacts/screenshots/2026-05-16/01-overview.png and b/dev/artifacts/screenshots/2026-05-16/01-overview.png differ diff --git a/dev/artifacts/screenshots/2026-05-16/08-side-panel-programs.png b/dev/artifacts/screenshots/2026-05-16/08-side-panel-programs.png index 7aa74da..57913df 100644 Binary files a/dev/artifacts/screenshots/2026-05-16/08-side-panel-programs.png and b/dev/artifacts/screenshots/2026-05-16/08-side-panel-programs.png differ diff --git a/dev/artifacts/screenshots/2026-05-16/09-side-panel-detail.png b/dev/artifacts/screenshots/2026-05-16/09-side-panel-detail.png index 929ba80..6da6eaa 100644 Binary files a/dev/artifacts/screenshots/2026-05-16/09-side-panel-detail.png and b/dev/artifacts/screenshots/2026-05-16/09-side-panel-detail.png differ diff --git a/dev/artifacts/screenshots/2026-05-16/10-side-panel-editor.png b/dev/artifacts/screenshots/2026-05-16/10-side-panel-editor.png index 4830f03..60ff9f0 100644 Binary files a/dev/artifacts/screenshots/2026-05-16/10-side-panel-editor.png and b/dev/artifacts/screenshots/2026-05-16/10-side-panel-editor.png differ