feat(ui): enhance provider switch error notification with copy action

- Split error message into title and description for better UX
- Add one-click copy button to easily share error details
- Extend toast duration to 6s for improved readability
- Use extractErrorMessage utility for consistent error handling
- Add i18n keys: common.copy, notifications.switchFailedTitle

This improves debugging experience when provider switching fails,
allowing users to quickly copy and share error messages.
This commit is contained in:
Jason
2025-11-09 17:56:02 +08:00
parent cfcd7b892a
commit 772081312e
3 changed files with 26 additions and 8 deletions

View File

@@ -25,7 +25,8 @@
"toggleTheme": "Toggle theme",
"format": "Format",
"formatSuccess": "Formatted successfully",
"formatError": "Format failed: {{error}}"
"formatError": "Format failed: {{error}}",
"copy": "Copy"
},
"apiKeyInput": {
"placeholder": "Enter API Key",
@@ -97,7 +98,8 @@
"providerSaved": "Provider configuration saved",
"providerDeleted": "Provider deleted successfully",
"switchSuccess": "Switch successful! Please restart {{appName}} terminal to take effect",
"switchFailed": "Switch failed, please check configuration",
"switchFailedTitle": "Switch failed",
"switchFailed": "Switch failed: {{error}}",
"autoImported": "Default provider created from existing configuration",
"addFailed": "Failed to add provider: {{error}}",
"saveFailed": "Save failed: {{error}}",

View File

@@ -25,7 +25,8 @@
"toggleTheme": "切换主题",
"format": "格式化",
"formatSuccess": "格式化成功",
"formatError": "格式化失败:{{error}}"
"formatError": "格式化失败:{{error}}",
"copy": "复制"
},
"apiKeyInput": {
"placeholder": "请输入API Key",
@@ -97,7 +98,8 @@
"providerSaved": "供应商配置已保存",
"providerDeleted": "供应商删除成功",
"switchSuccess": "切换成功!请重启 {{appName}} 终端以生效",
"switchFailed": "切换失败,请检查配置",
"switchFailedTitle": "切换失败",
"switchFailed": "切换失败:{{error}}",
"autoImported": "已从现有配置创建默认供应商",
"addFailed": "添加供应商失败:{{error}}",
"saveFailed": "保存失败:{{error}}",

View File

@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { providersApi, settingsApi, type AppId } from "@/lib/api";
import type { Provider, Settings } from "@/types";
import { extractErrorMessage } from "@/utils/errorUtils";
export const useAddProviderMutation = (appId: AppId) => {
const queryClient = useQueryClient();
@@ -143,11 +144,24 @@ export const useSwitchProviderMutation = (appId: AppId) => {
);
},
onError: (error: Error) => {
const detail = extractErrorMessage(error) || t("common.unknown");
// 标题与详情分离,便于扫描 + 一键复制
toast.error(
t("notifications.switchFailed", {
defaultValue: "切换供应商失败: {{error}}",
error: error.message,
}),
t("notifications.switchFailedTitle", { defaultValue: "切换失败" }),
{
description: t("notifications.switchFailed", {
defaultValue: "切换失败:{{error}}",
error: detail,
}),
duration: 6000,
action: {
label: t("common.copy", { defaultValue: "复制" }),
onClick: () => {
navigator.clipboard?.writeText(detail).catch(() => undefined);
},
},
},
);
},
});