mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 11:53:10 +08:00
feat(desktop): toast after fetching a provider model list
The picker that appears under each model field is easy to miss, so surface a success toast pointing the user at the dropdown once a non-empty list loads. Empty lists keep the existing inline notice.
This commit is contained in:
@@ -2593,6 +2593,41 @@ describe('Settings > Providers tab', () => {
|
||||
expect(noMatches).toHaveAttribute('aria-disabled', 'true')
|
||||
})
|
||||
|
||||
it('toasts that the fetched list is now pickable from the dropdown', async () => {
|
||||
const dialog = await openProviderFormWithModels({
|
||||
ok: true,
|
||||
endpoint: 'https://api.example.com/v1/models',
|
||||
models: [
|
||||
{ id: 'gpt-5-mini', ownedBy: 'openai' },
|
||||
{ id: 'claude-sonnet-4-6', ownedBy: 'anthropic' },
|
||||
],
|
||||
})
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: /Fetch models|获取模型/i }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(useUIStore.getState().toasts[useUIStore.getState().toasts.length - 1]).toMatchObject({
|
||||
type: 'success',
|
||||
message: 'Model list loaded. Pick a model from the dropdown now.',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('does not toast when the fetched model list is empty', async () => {
|
||||
const dialog = await openProviderFormWithModels({
|
||||
ok: true,
|
||||
endpoint: 'https://api.example.com/v1/models',
|
||||
models: [],
|
||||
})
|
||||
|
||||
fireEvent.click(within(dialog).getByRole('button', { name: /Fetch models|获取模型/i }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(providerStoreState.fetchModels).toHaveBeenCalled()
|
||||
})
|
||||
expect(useUIStore.getState().toasts).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('routes a picked model through the shared model change handler', async () => {
|
||||
const dialog = await openProviderFormWithModels({
|
||||
ok: true,
|
||||
|
||||
@@ -762,6 +762,7 @@ Row 9, all 8 cells: continuing from straight down, turning left through lower-le
|
||||
'settings.providers.fetchModelsApiKeyHint': 'Enter an API key to fetch the model list.',
|
||||
'settings.providers.fetchModelsSupportHint': 'This works only when the upstream provider publishes a model list endpoint.',
|
||||
'settings.providers.fetchModelsLoaded': 'Model list loaded ({count}). Pick one or keep typing the ID.',
|
||||
'settings.providers.fetchModelsToast': 'Model list loaded. Pick a model from the dropdown now.',
|
||||
'settings.providers.fetchModelsEmpty': 'No models found. Enter the model ID manually.',
|
||||
'settings.providers.fetchModelsPick': 'Choose {label} from the fetched list',
|
||||
'settings.providers.fetchModelsGroupOther': 'Other',
|
||||
|
||||
@@ -764,6 +764,7 @@ export const jp: Record<TranslationKey, string> = {
|
||||
'settings.providers.fetchModelsApiKeyHint': 'モデル一覧を取得するには API キーを入力してください。',
|
||||
'settings.providers.fetchModelsSupportHint': '上流プロバイダーがモデル一覧エンドポイントを公開している場合のみ取得できます。',
|
||||
'settings.providers.fetchModelsLoaded': 'モデル一覧を取得しました({count} 件)。選択しても、手入力を続けても構いません。',
|
||||
'settings.providers.fetchModelsToast': 'モデル一覧を取得しました。ドロップダウンからモデルを選択できます。',
|
||||
'settings.providers.fetchModelsEmpty': 'モデルが見つかりません。モデル ID を手入力してください。',
|
||||
'settings.providers.fetchModelsPick': '取得したリストから{label}を選択',
|
||||
'settings.providers.fetchModelsGroupOther': 'その他',
|
||||
|
||||
@@ -764,6 +764,7 @@ export const kr: Record<TranslationKey, string> = {
|
||||
'settings.providers.fetchModelsApiKeyHint': '모델 목록을 가져오려면 API 키를 입력하세요.',
|
||||
'settings.providers.fetchModelsSupportHint': '상위 공급자가 모델 목록 엔드포인트를 제공하는 경우에만 가져올 수 있습니다.',
|
||||
'settings.providers.fetchModelsLoaded': '모델 목록을 가져왔습니다({count}개). 선택하거나 직접 입력해도 됩니다.',
|
||||
'settings.providers.fetchModelsToast': '모델 목록을 가져왔습니다. 이제 드롭다운에서 모델을 선택할 수 있습니다.',
|
||||
'settings.providers.fetchModelsEmpty': '모델을 찾지 못했습니다. 모델 ID를 직접 입력하세요.',
|
||||
'settings.providers.fetchModelsPick': '가져온 목록에서 {label} 선택',
|
||||
'settings.providers.fetchModelsGroupOther': '기타',
|
||||
|
||||
@@ -763,6 +763,7 @@ export const zh: Record<TranslationKey, string> = {
|
||||
'settings.providers.fetchModelsApiKeyHint': '要填寫 API Key 才能取得模型清單',
|
||||
'settings.providers.fetchModelsSupportHint': '僅當上游服務商提供模型清單端點時才能取得。',
|
||||
'settings.providers.fetchModelsLoaded': '已取得模型清單({count} 個),可直接選擇,也可繼續手動輸入。',
|
||||
'settings.providers.fetchModelsToast': '已取得模型清單,現在可以在下拉框中選擇模型了。',
|
||||
'settings.providers.fetchModelsEmpty': '沒有找到模型,請手動填寫模型 ID。',
|
||||
'settings.providers.fetchModelsPick': '從已取得的清單中選擇{label}',
|
||||
'settings.providers.fetchModelsGroupOther': '其他',
|
||||
|
||||
@@ -763,6 +763,7 @@ export const zh: Record<TranslationKey, string> = {
|
||||
'settings.providers.fetchModelsApiKeyHint': '要填写 API Key 才能获取模型列表',
|
||||
'settings.providers.fetchModelsSupportHint': '仅当上游服务商提供模型列表接口时才能获取。',
|
||||
'settings.providers.fetchModelsLoaded': '已获取模型列表({count} 个),可直接选择,也可继续手动输入。',
|
||||
'settings.providers.fetchModelsToast': '已获取模型列表,现在可以在下拉框中选择模型了。',
|
||||
'settings.providers.fetchModelsEmpty': '没有找到模型,请手动填写模型 ID。',
|
||||
'settings.providers.fetchModelsPick': '从已获取的列表中选择{label}',
|
||||
'settings.providers.fetchModelsGroupOther': '其他',
|
||||
|
||||
@@ -1254,6 +1254,7 @@ function openExternalUrl(url: string) {
|
||||
function ProviderFormModal({ open, onClose, mode, provider, presets }: ProviderFormProps) {
|
||||
const { createProvider, updateProvider, testConfig, fetchModels } = useProviderStore()
|
||||
const fetchSettings = useSettingsStore((s) => s.fetchAll)
|
||||
const addToast = useUIStore((s) => s.addToast)
|
||||
const t = useTranslation()
|
||||
const baseUrlInputId = useId()
|
||||
|
||||
@@ -1638,6 +1639,14 @@ function ProviderFormModal({ open, onClose, mode, provider, presets }: ProviderF
|
||||
if (modelsRequestRef.current !== requestId) return
|
||||
if (result.ok) {
|
||||
setFetchedModels(result.models)
|
||||
// The picker that just appeared is easy to miss below the button, so
|
||||
// point the user at it. Empty lists already render an inline notice.
|
||||
if (result.models.length > 0) {
|
||||
addToast({
|
||||
type: 'success',
|
||||
message: t('settings.providers.fetchModelsToast'),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setFetchedModels(null)
|
||||
setModelsErrorCode(result.errorCode)
|
||||
|
||||
Reference in New Issue
Block a user