From c1c3aa975483155f977ae2f7d37e763d3e569502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 18 Jul 2026 03:48:35 +0200 Subject: [PATCH] fix(settings): resync threshold rows after a reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each MetricRow is keyed on the stable metric name, so a per-row or reset-all mutation that lands a new override (typically null) never re-ran the useState initializers — the switch, min/max fields, and override mode kept showing the just-cleared values while the "Überschrieben" badge (driven straight off the prop) vanished, a contradictory row until a reload. Re-derive an identity from the override prop and resync local state during render when it changes; typing in the fields never touches that identity, so this never fights a live edit. --- .../settings/thresholds-editor-section.tsx | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/components/settings/thresholds-editor-section.tsx b/src/components/settings/thresholds-editor-section.tsx index b0bda483b..1c364e1d1 100644 --- a/src/components/settings/thresholds-editor-section.tsx +++ b/src/components/settings/thresholds-editor-section.tsx @@ -225,6 +225,32 @@ function MetricRow({ String(override?.max ?? effective?.default?.greenMax ?? bounds.max), ); + // v1.30.1 M9 — the row is keyed on the stable `metric`, so a per-row + // reset (or "reset all") that lands a NEW `override` (typically + // `null`) never re-runs the `useState` initializers above: the + // component instance survives the refetch. Pre-fix the switch and + // min/max fields kept showing the stale override after the server + // confirmed it was cleared, while the "Überschrieben" badge (driven + // straight off the `hasOverride` prop, not state) vanished — a + // contradictory row until a hard reload. Re-derive an identity string + // from the override prop and resync local state during render + // whenever it actually changes; typing in the fields never changes + // `overrideIdentity`, so this never fights a live edit. + const overrideIdentity = override + ? `${override.min}:${override.max}` + : "unset"; + const [syncedIdentity, setSyncedIdentity] = useState(overrideIdentity); + if (overrideIdentity !== syncedIdentity) { + setSyncedIdentity(overrideIdentity); + setOverrideMode(hasOverride); + setMinStr( + String(override?.min ?? effective?.default?.greenMin ?? bounds.min), + ); + setMaxStr( + String(override?.max ?? effective?.default?.greenMax ?? bounds.max), + ); + } + const minNum = parseFloat(minStr); const maxNum = parseFloat(maxStr); const valid =