repo_description: A cross-platform desktop All-in-One assistant tool for Claude Code, Codex, OpenCode, openclaw & Gemini CLI.
repo_topics: ai-tools claude-code codex desktop-app mcp minimax omo open-source openclaw openclaw-ui opencode provider-management rust skills skills-management tauri typescript wsl-support
code: /**
   * 全局出站代理 React Hooks
   *
   * 提供获取、设置和测试全局代理的 React Query hooks。
   */
  
  import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
  import { toast } from "sonner";
  import { useTranslation } from "react-i18next";
  import {
    getGlobalProxyUrl,
    setGlobalProxyUrl,
    testProxyUrl,
    getUpstreamProxyStatus,
    scanLocalProxies,
    type ProxyTestResult,
    type UpstreamProxyStatus,
    type DetectedProxy,
  } from "@/lib/api/globalProxy";
  
  /**
   * 获取全局代理 URL
   */
  export function useGlobalProxyUrl() {
    return useQuery({
      queryKey: ["globalProxyUrl"],
      queryFn: getGlobalProxyUrl,
      staleTime: 30 * 1000, // 30秒内不重新获取，避免展开时闪烁
    });
  }
  
  /**
   * 设置全局代理 URL
   */
  export function useSetGlobalProxyUrl() {
    const queryClient = useQueryClient();
    const { t } = useTranslation();
  
    return useMutation({
      mutationFn: setGlobalProxyUrl,
      onSuccess: () => {
        toast.success(t("settings.globalProxy.saved"));
        queryClient.invalidateQueries({ queryKey: ["globalProxyUrl"] });
        queryClient.invalidateQueries({ queryKey: ["upstreamProxyStatus"] });
      },
      onError: (error: unknown) => {
        const message =
          error instanceof Error
            ? error.message
            : typeof error === "string"
              ? error
              : "Unknown error";
        toast.error(t("settings.globalProxy.saveFailed", { error: message }));
      },
    });
  }
  
  /**
   * 测试代理连接
   */
  export function useTestProxy() {
    const { t } = useTranslation();
  
    return useMutation({
      mutationFn: testProxyUrl,
      onSuccess: (result: ProxyTestResult) => {
        if (result.success) {
          toast.success(
            t("settings.globalProxy.testSuccess", { latency: result.latencyMs }),
          );
        } else {
          toast.error(
            t("settings.globalProxy.testFailed", { error: result.error }),
          );
        }
      },
      onError: (error: Error) => {
        toast.error(error.message);
      },
    });
  }
  
  /**
   * 获取当前出站代理状态
   */
  export function useUpstreamProxyStatus() {
    return useQuery<UpstreamProxyStatus>({
      queryKey: ["upstreamProxyStatus"],
      queryFn: getUpstreamProxyStatus,
    });
  }
  
  /**
   * 扫描本地代理
   */
  export function useScanProxies() {
    const { t } = useTranslation();
  
    return useMutation({
      mutationFn: scanLocalProxies,
      onError: (error: Error) => {
        toast.error(
          t("settings.globalProxy.scanFailed", { error: error.message }),
        );
      },
    });
  }
  
  export type { DetectedProxy };
  