From cf2103ebf8aab55871dc8d5e2d3f04323fbe0ab2 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sun, 12 Jul 2026 03:08:30 +0800 Subject: [PATCH] Preserve API mode selections after default list changes Keep the configured API mode visible when it is no longer enabled by default. This prevents the General settings dropdown from appearing to select an unrelated fallback model. Show the current mode as a disabled option until the user explicitly chooses an available mode. --- src/popup/sections/GeneralPart.jsx | 37 +++++-- .../sections/api-modes-provider-utils.mjs | 15 ++- .../popup/api-modes-provider-utils.test.mjs | 99 +++++++++++++++++++ 3 files changed, 142 insertions(+), 9 deletions(-) diff --git a/src/popup/sections/GeneralPart.jsx b/src/popup/sections/GeneralPart.jsx index 28b51b71e..bf1798b89 100644 --- a/src/popup/sections/GeneralPart.jsx +++ b/src/popup/sections/GeneralPart.jsx @@ -1,7 +1,7 @@ import { useTranslation } from 'react-i18next' import { useLayoutEffect, useRef, useState } from 'react' import FileSaver from 'file-saver' -import { isApiModeSelected, getApiModesFromConfig } from '../../utils/index.mjs' +import { getApiModesFromConfig, modelNameToDesc } from '../../utils/index.mjs' import { isUsingAzureOpenAiApiModel, isUsingClaudeApiModel, @@ -21,7 +21,11 @@ import { config as menuConfig } from '../../content-script/menu-tools' import { PencilIcon } from '@primer/octicons-react' import { importDataIntoStorage } from './import-data-cleanup.mjs' import { resolveOpenAICompatibleRequest } from '../../services/apis/provider-registry.mjs' -import { getApiModeDisplayLabel } from './api-modes-provider-utils.mjs' +import { + getApiModeDisplayLabel, + getSelectedApiModeOptionValue, + UNMATCHED_API_MODE_VALUE, +} from './api-modes-provider-utils.mjs' import { buildProviderOverrideFinalConfigUpdate, createProviderApiKeyDraftSelectionSignature, @@ -107,6 +111,14 @@ export function GeneralPart({ config.apiMode && typeof config.apiMode === 'object' ? { apiMode: config.apiMode } : { modelName: config.modelName } + const selectedApiModeValue = getSelectedApiModeOptionValue(apiModes, config) + const currentApiModeLabel = config.apiMode + ? getApiModeDisplayLabel( + config.apiMode, + t, + Array.isArray(config.customOpenAIProviders) ? config.customOpenAIProviders : [], + ) || t(Models.customModel.desc) + : modelNameToDesc(config.modelName, t, config.customModelName) const selectedProviderRequest = resolveOpenAICompatibleRequest(config, selectedProviderSession) const selectedProviderId = selectedProviderRequest?.providerId || '' const selectedProviderSecretTargetId = resolveProviderSecretTargetId(selectedProviderRequest) @@ -480,15 +492,26 @@ export function GeneralPart({ : undefined } required + value={selectedApiModeValue} onChange={(e) => { + if (e.target.value === UNMATCHED_API_MODE_VALUE) return if (e.target.value === '-1') { updateConfig({ modelName: 'customModel', apiMode: null }) return } - const apiMode = apiModes[e.target.value] - updateConfig({ apiMode: apiMode }) + const apiMode = apiModes[Number(e.target.value)] + if (!apiMode) { + e.currentTarget.value = selectedApiModeValue + return + } + updateConfig({ apiMode }) }} > + {selectedApiModeValue === UNMATCHED_API_MODE_VALUE && ( + + )} {apiModes.map((apiMode, index) => { const desc = getApiModeDisplayLabel( apiMode, @@ -497,15 +520,13 @@ export function GeneralPart({ ) if (desc) { return ( - ) } })} - + {isUsingMultiModeModel(config) && (