From 48bff4d189e2cabc8a66fa6a584c3d3fd6cdf47b Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Tue, 8 Sep 2026 15:34:10 -0500 Subject: [PATCH] Start locked by default and remember the lock toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The card picker stub set start_locked: false, which switched off the auto-lock for every card added through the UI. Drop it from the stub, remember the Lock toggle per location in localStorage, and document when to set start_locked explicitly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- README.md | 4 ++-- dist/zone-mapper-card.js | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7446d75..bc3a016 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ A custom Lovelace card for Home Assistant that lets you draw 2D detection zones - Helper overlay (device “view cone”) with configurable horizontal FOV and rotation angle - Compact UI: - Bottom‑left: a single ✎ “Draw” button toggles a vertical menu of modes (▭ Rect, ◯ Ellipse, ⬠ Polygon) that appears above it - - Bottom‑right: 🔒 Lock toggle prevents accidental edits (disables drawing and cancels in‑progress) + - Bottom‑right: 🔒 Lock toggle prevents accidental edits (disables drawing and cancels in‑progress). The card starts locked whenever zones already exist, and the toggle is remembered per `location` in the browser. Set `start_locked` in YAML to override both. - Device and Entity pickers: choose a HA device and select X/Y sensor entity pairs directly from dropdowns; click Apply to persist - The picked device and X/Y pairs are remembered per `location`, so reloading the dashboard keeps your selection - Multi‑unit support (front‑end only): configure input/grid in mm, cm, m, in, or ft (backend remains millimetres) @@ -106,7 +106,7 @@ The majority of the configuration and management of zones takes place on the act type: custom:zone-mapper-card location: Office # friendly name shown on card; used to build zone entity ids dark_mode: false -start_locked: true # Start in lock mode +# start_locked: true # optional; forces the starting lock state. Leave it out to start locked whenever zones exist # Units (front-end only, converts to mm internally) input_units: mm # mm | cm | m | in | ft diff --git a/dist/zone-mapper-card.js b/dist/zone-mapper-card.js index 45def58..0afe474 100644 --- a/dist/zone-mapper-card.js +++ b/dist/zone-mapper-card.js @@ -173,6 +173,32 @@ function writeStoredSelection(location, deviceId, entities) { } } +const LOCK_STORAGE_PREFIX = 'zone-mapper-card.lock'; + +function lockStorageKey(location) { + return `${LOCK_STORAGE_PREFIX}.${slugifyLocation(location)}`; +} + +// Remember the lock toggle per location so a reload keeps the grid locked +function readStoredLock(location) { + try { + const raw = window.localStorage.getItem(lockStorageKey(location)); + if (raw === '1') return true; + if (raw === '0') return false; + return null; + } catch { + return null; + } +} + +function writeStoredLock(location, locked) { + try { + window.localStorage.setItem(lockStorageKey(location), locked ? '1' : '0'); + } catch { + // Nothing to do; the toggle still applies for the current page load + } +} + class ZoneMapperCard extends HTMLElement { static get GRID_MIN_SPACING_PX() { return 40; @@ -229,7 +255,6 @@ class ZoneMapperCard extends HTMLElement { return { type: 'custom:zone-mapper-card', dark_mode: false, - start_locked: false, show_undo: true, unit_display: false, // unit_label_size: 18, @@ -775,6 +800,7 @@ class ZoneMapperCard extends HTMLElement { }; btnLock.addEventListener('click', () => { this.isLocked = !this.isLocked; + writeStoredLock(this.location, this.isLocked); updateLockVisual(); this._lastLockWarningTs = 0; if (this.isLocked) { @@ -1644,16 +1670,16 @@ class ZoneMapperCard extends HTMLElement { } _applyAutoLock() { - // When the user hasn't pinned start_locked in config, lock by default - // whenever zones already exist so accidental clicks don't overwrite them. - // Only runs once per page load. + // An explicit start_locked in config always wins. Otherwise use the last + // toggle remembered for this location, and fall back to locking whenever + // zones already exist. Only runs once per page load. if (this._autoLockApplied) return; if (this._lockConfigured) { this._autoLockApplied = true; return; } - const hasZones = (this.zones || []).length > 0; - this.isLocked = hasZones; + const stored = readStoredLock(this.location); + this.isLocked = stored !== null ? stored : (this.zones || []).length > 0; this._autoLockApplied = true; if (typeof this._updateLockVisual === 'function') { this._updateLockVisual();