/** * Appearance & Behavior › System Settings › HTTP Proxy: how the IDE's own * connections (HTTP Client, tool / JDK / agent downloads, update checks) reach * the network. A manual proxy also reaches child processes as `HTTP_PROXY`. */ import { useId, useRef, useState } from "react"; import clsx from "clsx"; import { call, commands, isTauri } from "@/platform/ipc"; import { tx, useTx } from "@/platform/i18n"; import { PROXY_PORT_LIMITS, proxyProblem, withProxyKind, type ProxyKindValid, type ProxyModeValid, type ProxySettingsValid, } from "@/platform/proxySettings"; import { Button, Checkbox, Input, Popup, T } from "@/ui"; import { NumberInput, Row, SearchLabel } from "../components/Form"; import { usePageContext, useSetting } from "../components/context"; import { stage } from "../model/staging"; import type { PageSpec } from "./spec"; import styles from "./HttpProxy.module.css"; const MODES: Array<{ value: ProxyModeValid; label: string; hint?: string }> = [ { value: "none", label: "No proxy" }, { value: "auto", label: "Auto-detect proxy settings", hint: "Uses the system proxy: the HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables.", }, { value: "manual", label: "Manual proxy configuration" }, ]; const KINDS: Array<{ value: ProxyKindValid; label: string }> = [ { value: "http", label: "HTTP" }, { value: "socks", label: "SOCKS" }, ]; /** The staged proxy settings and a setter per field (each written as its own key). */ function useProxy(): [ProxySettingsValid, (patch: Partial) => void] { const [proxy] = useSetting("proxy", "global"); const { pageId } = usePageContext(); const update = (patch: Partial) => { for (const [field, value] of Object.entries(patch)) stage(pageId, "global", `proxy.${field}`, value); }; return [proxy, update]; } function Radio({ name, checked, onSelect, label, disabled, }: { name: string; checked: boolean; onSelect: () => void; label: string; disabled?: boolean; }) { return ( ); } function ProxyOptions() { const [proxy, update] = useProxy(); const name = useId(); const kindName = useId(); const ids = { host: useId(), port: useId(), noProxy: useId(), login: useId(), password: useId(), }; const manual = proxy.mode === "manual"; const auth = manual && proxy.authenticate; const problem = proxyProblem(proxy); return (
{MODES.map((m) => (
update({ mode: m.value })} label={m.label} /> {m.hint && (
{m.hint}
)}
))}
{KINDS.map((k) => ( update(withProxyKind(proxy, k.value))} label={k.label} /> ))}
update({ host: e.target.value })} /> {manual ? ( update({ port })} {...PROXY_PORT_LIMITS} integer aria-label="Port number" /> ) : ( )}
update({ noProxy: e.target.value })} />
update({ authenticate })} label={} />
update({ login: e.target.value })} /> update({ password: e.target.value })} />
{problem && (
{problem}
)}
); } type CheckState = { status: "idle" | "running" } | { status: "ok" | "failed"; text: string }; /** Check connection…: asks for a URL and GETs it with the settings as edited. */ function CheckConnection({ proxy }: { proxy: ProxySettingsValid }) { const t = useTx(); const anchor = useRef(null); const urlId = useId(); const [open, setOpen] = useState(false); const [url, setUrl] = useState("http://"); const [state, setState] = useState({ status: "idle" }); const check = async () => { setState({ status: "running" }); try { const status = await call(commands.proxyCheckConnection(proxy, url)); setState({ status: "ok", text: t`Connection successful: ${status}` }); } catch (e) { const message = e instanceof Error ? e.message : String(e); setState({ status: "failed", text: t`Problem with connection: ${message}`, }); } }; const running = state.status === "running"; return (
setOpen(false)} anchor={anchor} placement="bottom-start" offset={4} aria-label="Check connection" >
{ e.preventDefault(); if (!running && url.trim()) void check(); }} > setUrl(e.target.value)} /> {state.status === "ok" || state.status === "failed" ? state.text : running ? t("Connecting…") : ""}
); } export const HTTP_PROXY_PAGE: PageSpec = { id: "general.httpProxy", title: "HTTP Proxy", order: 2, keywords: ["proxy", "network", "socks", "http_proxy", "no_proxy", "connection"], sections: [ { options: [ { kind: "custom", label: "Manual proxy configuration", keywords: [ "No proxy", "Auto-detect proxy settings", "Host name", "Port number", "No proxy for", "Proxy authentication", "Login", "Password", "Check connection…", ], component: ProxyOptions, }, ], }, ], };