From 7fc707ab8ccf841cbc17650c013668b84f8bf77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 17 Apr 2026 10:28:19 -0400 Subject: [PATCH] fix(onboarding): stabilize connector-model state so native re-renders its options children → Chromium's native dropdown is not torn down mid-interaction. + */ +function connectorCatalogsEqual( + a: Record, + b: Record, +): boolean { + const keysA = Object.keys(a); + const keysB = Object.keys(b); + if (keysA.length !== keysB.length) return false; + for (const key of keysA) { + const listA = a[key]; + const listB = b[key]; + if (!listB || listA.length !== listB.length) return false; + for (let i = 0; i < listA.length; i++) { + const x = listA[i]; + const y = listB[i]; + if (x.id !== y.id || x.label !== y.label || x.enabled !== y.enabled) return false; + } + } + return true; +} + interface UseConnectorModelSelectionResult { executionReadyConnectors: ProfileSnapshot["connectors"]; hasAtLeastOneReady: boolean; @@ -100,10 +127,18 @@ export function useConnectorModelSelection( executionReadyConnectors.map(async (connector) => [connector.id, await loadConnectorModels(connector)] as const), ); if (cancelled) return; - setConnectorModelsById(Object.fromEntries(entries)); + const next = Object.fromEntries(entries); + // Guard against no-op state updates: snapshot refreshes re-run this + // effect with the same CONNECTORS data, and returning a new object + // reference here cascades through `connectorModels` → `modelOptions` + // and collapses any open native