mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 16:56:16 +08:00
57713dd336
Display an info toast when switching to a provider that uses OpenAI Chat format (apiFormat === "openai_chat"), reminding users to enable the proxy service. Move toast logic from mutation to useProviderActions for better control over notification content based on provider properties.
186 lines
5.6 KiB
TypeScript
186 lines
5.6 KiB
TypeScript
import { useCallback } from "react";
|
|
import { useQueryClient } from "@tanstack/react-query";
|
|
import { toast } from "sonner";
|
|
import { useTranslation } from "react-i18next";
|
|
import { providersApi, settingsApi, type AppId } from "@/lib/api";
|
|
import type { Provider, UsageScript } from "@/types";
|
|
import {
|
|
useAddProviderMutation,
|
|
useUpdateProviderMutation,
|
|
useDeleteProviderMutation,
|
|
useSwitchProviderMutation,
|
|
} from "@/lib/query";
|
|
import { extractErrorMessage } from "@/utils/errorUtils";
|
|
|
|
/**
|
|
* Hook for managing provider actions (add, update, delete, switch)
|
|
* Extracts business logic from App.tsx
|
|
*/
|
|
export function useProviderActions(activeApp: AppId) {
|
|
const { t } = useTranslation();
|
|
const queryClient = useQueryClient();
|
|
|
|
const addProviderMutation = useAddProviderMutation(activeApp);
|
|
const updateProviderMutation = useUpdateProviderMutation(activeApp);
|
|
const deleteProviderMutation = useDeleteProviderMutation(activeApp);
|
|
const switchProviderMutation = useSwitchProviderMutation(activeApp);
|
|
|
|
// Claude 插件同步逻辑
|
|
const syncClaudePlugin = useCallback(
|
|
async (provider: Provider) => {
|
|
if (activeApp !== "claude") return;
|
|
|
|
try {
|
|
const settings = await settingsApi.get();
|
|
if (!settings?.enableClaudePluginIntegration) {
|
|
return;
|
|
}
|
|
|
|
const isOfficial = provider.category === "official";
|
|
await settingsApi.applyClaudePluginConfig({ official: isOfficial });
|
|
|
|
// 静默执行,不显示成功通知
|
|
} catch (error) {
|
|
const detail =
|
|
extractErrorMessage(error) ||
|
|
t("notifications.syncClaudePluginFailed", {
|
|
defaultValue: "同步 Claude 插件失败",
|
|
});
|
|
toast.error(detail, { duration: 4200 });
|
|
}
|
|
},
|
|
[activeApp, t],
|
|
);
|
|
|
|
// 添加供应商
|
|
const addProvider = useCallback(
|
|
async (provider: Omit<Provider, "id"> & { providerKey?: string }) => {
|
|
await addProviderMutation.mutateAsync(provider);
|
|
},
|
|
[addProviderMutation],
|
|
);
|
|
|
|
// 更新供应商
|
|
const updateProvider = useCallback(
|
|
async (provider: Provider) => {
|
|
await updateProviderMutation.mutateAsync(provider);
|
|
|
|
// 更新托盘菜单(失败不影响主操作)
|
|
try {
|
|
await providersApi.updateTrayMenu();
|
|
} catch (trayError) {
|
|
console.error(
|
|
"Failed to update tray menu after updating provider",
|
|
trayError,
|
|
);
|
|
}
|
|
},
|
|
[updateProviderMutation],
|
|
);
|
|
|
|
// 切换供应商
|
|
const switchProvider = useCallback(
|
|
async (provider: Provider) => {
|
|
try {
|
|
await switchProviderMutation.mutateAsync(provider.id);
|
|
await syncClaudePlugin(provider);
|
|
|
|
// 根据供应商类型显示不同的成功提示
|
|
if (
|
|
activeApp === "claude" &&
|
|
provider.category !== "official" &&
|
|
provider.meta?.apiFormat === "openai_chat"
|
|
) {
|
|
// OpenAI Chat 格式供应商:显示代理提示
|
|
toast.info(
|
|
t("notifications.openAIChatFormatHint", {
|
|
defaultValue:
|
|
"此供应商使用 OpenAI Chat 格式,需要开启代理服务才能正常使用",
|
|
}),
|
|
{
|
|
duration: 5000,
|
|
closeButton: true,
|
|
},
|
|
);
|
|
} else {
|
|
// 普通供应商:显示切换成功
|
|
// OpenCode: show "added to config" message instead of "switched"
|
|
const messageKey =
|
|
activeApp === "opencode"
|
|
? "notifications.addToConfigSuccess"
|
|
: "notifications.switchSuccess";
|
|
const defaultMessage =
|
|
activeApp === "opencode" ? "已添加到配置" : "切换成功!";
|
|
|
|
toast.success(t(messageKey, { defaultValue: defaultMessage }), {
|
|
closeButton: true,
|
|
});
|
|
}
|
|
} catch {
|
|
// 错误提示由 mutation 处理
|
|
}
|
|
},
|
|
[switchProviderMutation, syncClaudePlugin, activeApp, t],
|
|
);
|
|
|
|
// 删除供应商
|
|
const deleteProvider = useCallback(
|
|
async (id: string) => {
|
|
await deleteProviderMutation.mutateAsync(id);
|
|
},
|
|
[deleteProviderMutation],
|
|
);
|
|
|
|
// 保存用量脚本
|
|
const saveUsageScript = useCallback(
|
|
async (provider: Provider, script: UsageScript) => {
|
|
try {
|
|
const updatedProvider: Provider = {
|
|
...provider,
|
|
meta: {
|
|
...provider.meta,
|
|
usage_script: script,
|
|
},
|
|
};
|
|
|
|
await providersApi.update(updatedProvider, activeApp);
|
|
await queryClient.invalidateQueries({
|
|
queryKey: ["providers", activeApp],
|
|
});
|
|
// 🔧 保存用量脚本后,也应该失效该 provider 的用量查询缓存
|
|
// 这样主页列表会使用新配置重新查询,而不是使用测试时的缓存
|
|
await queryClient.invalidateQueries({
|
|
queryKey: ["usage", provider.id, activeApp],
|
|
});
|
|
toast.success(
|
|
t("provider.usageSaved", {
|
|
defaultValue: "用量查询配置已保存",
|
|
}),
|
|
{ closeButton: true },
|
|
);
|
|
} catch (error) {
|
|
const detail =
|
|
extractErrorMessage(error) ||
|
|
t("provider.usageSaveFailed", {
|
|
defaultValue: "用量查询配置保存失败",
|
|
});
|
|
toast.error(detail);
|
|
}
|
|
},
|
|
[activeApp, queryClient, t],
|
|
);
|
|
|
|
return {
|
|
addProvider,
|
|
updateProvider,
|
|
switchProvider,
|
|
deleteProvider,
|
|
saveUsageScript,
|
|
isLoading:
|
|
addProviderMutation.isPending ||
|
|
updateProviderMutation.isPending ||
|
|
deleteProviderMutation.isPending ||
|
|
switchProviderMutation.isPending,
|
|
};
|
|
}
|