mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 12:13:42 +01:00
Every settings tab in Yaak and Yaak Proxy now renders its heading, description, optional banner and content through SettingsPage, which puts the same 1.5rem gap between each. The banner slot hides itself when nothing inside it has content, so Yaak's General tab no longer gets an accidental gap from the empty commercial-use banner, and the proxy's General tab no longer sits tight under its description. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
177 lines
6.2 KiB
TypeScript
177 lines
6.2 KiB
TypeScript
import { patchModel, settingsAtom } from "@yaakapp-internal/models";
|
|
import type { ProxySetting } from "@yaakapp-internal/models";
|
|
import { InlineCode, SettingsPage } from "@yaakapp-internal/ui";
|
|
import { useAtomValue } from "jotai";
|
|
import { CommercialUseBanner } from "../CommercialUseBanner";
|
|
import {
|
|
SettingRowBoolean,
|
|
SettingRowSelect,
|
|
SettingRowText,
|
|
SettingsList,
|
|
SettingsSection,
|
|
} from "../core/SettingRow";
|
|
|
|
export function SettingsProxy() {
|
|
const settings = useAtomValue(settingsAtom);
|
|
const proxy = enabledProxyOrDefault(settings.proxy);
|
|
|
|
const patchProxy = async (patch: Partial<EnabledProxySetting>) => {
|
|
await patchModel(settings, {
|
|
proxy: {
|
|
...proxy,
|
|
...patch,
|
|
auth: Object.hasOwn(patch, "auth") ? (patch.auth ?? null) : proxy.auth,
|
|
},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<SettingsPage
|
|
title="Proxy"
|
|
description="Configure a proxy server for HTTP requests. Useful for corporate firewalls, debugging traffic, or routing through specific infrastructure."
|
|
banner={<CommercialUseBanner source="proxy-settings" title="Using a proxy for work?" />}
|
|
>
|
|
<SettingsList className="space-y-8">
|
|
<SettingsSection title="Proxy">
|
|
<SettingRowSelect
|
|
title="Proxy"
|
|
description="Choose how Yaak should discover or use proxy settings."
|
|
name="proxy"
|
|
value={settings.proxy?.type ?? "automatic"}
|
|
onChange={async (v) => {
|
|
if (v === "automatic") {
|
|
await patchModel(settings, { proxy: undefined });
|
|
} else if (v === "enabled") {
|
|
await patchModel(settings, { proxy });
|
|
} else {
|
|
await patchModel(settings, { proxy: { type: "disabled" } });
|
|
}
|
|
}}
|
|
options={[
|
|
{ label: "Automatic proxy detection", value: "automatic" },
|
|
{ label: "Custom proxy configuration", value: "enabled" },
|
|
{ label: "No proxy", value: "disabled" },
|
|
]}
|
|
selectClassName="w-64!"
|
|
/>
|
|
</SettingsSection>
|
|
|
|
{settings.proxy?.type === "enabled" && (
|
|
<>
|
|
<SettingsSection title="Custom Proxy">
|
|
<SettingRowBoolean
|
|
checked={!settings.proxy.disabled}
|
|
title="Enable proxy"
|
|
description="Temporarily disable the proxy without losing the configuration."
|
|
onChange={(enabled) => patchProxy({ disabled: !enabled })}
|
|
/>
|
|
<SettingRowText
|
|
name="proxyHttp"
|
|
title={
|
|
<>
|
|
Proxy for <InlineCode>http://</InlineCode> traffic
|
|
</>
|
|
}
|
|
description="Proxy host used for unencrypted HTTP traffic."
|
|
value={settings.proxy.http}
|
|
placeholder="localhost:9090"
|
|
onChange={(http) => patchProxy({ http })}
|
|
/>
|
|
<SettingRowText
|
|
name="proxyHttps"
|
|
title={
|
|
<>
|
|
Proxy for <InlineCode>https://</InlineCode> traffic
|
|
</>
|
|
}
|
|
description="Proxy host used for HTTPS traffic."
|
|
value={settings.proxy.https}
|
|
placeholder="localhost:9090"
|
|
onChange={(https) => patchProxy({ https })}
|
|
/>
|
|
<SettingRowText
|
|
name="proxyBypass"
|
|
title="Proxy Bypass"
|
|
description="Comma-separated list of hosts that should bypass the proxy."
|
|
value={settings.proxy.bypass}
|
|
placeholder="127.0.0.1, *.example.com, localhost:3000"
|
|
inputWidthClassName="w-96!"
|
|
onChange={(bypass) => patchProxy({ bypass })}
|
|
/>
|
|
</SettingsSection>
|
|
|
|
<SettingsSection title="Authentication">
|
|
<SettingRowBoolean
|
|
checked={settings.proxy.auth != null}
|
|
title="Enable authentication"
|
|
description="Send proxy credentials with proxied requests."
|
|
onChange={(enabled) =>
|
|
patchProxy({ auth: enabled ? { user: "", password: "" } : null })
|
|
}
|
|
/>
|
|
|
|
{settings.proxy.auth != null && (
|
|
<>
|
|
<SettingRowText
|
|
required
|
|
name="proxyUser"
|
|
title="User"
|
|
description="Username for proxy authentication."
|
|
value={settings.proxy.auth.user}
|
|
placeholder="myUser"
|
|
onChange={(user) =>
|
|
patchProxy({
|
|
auth: {
|
|
user,
|
|
password:
|
|
settings.proxy?.type === "enabled"
|
|
? (settings.proxy.auth?.password ?? "")
|
|
: "",
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
<SettingRowText
|
|
name="proxyPassword"
|
|
title="Password"
|
|
description="Password for proxy authentication."
|
|
value={settings.proxy.auth.password}
|
|
placeholder="s3cretPassw0rd"
|
|
type="password"
|
|
onChange={(password) =>
|
|
patchProxy({
|
|
auth: {
|
|
user:
|
|
settings.proxy?.type === "enabled"
|
|
? (settings.proxy.auth?.user ?? "")
|
|
: "",
|
|
password,
|
|
},
|
|
})
|
|
}
|
|
/>
|
|
</>
|
|
)}
|
|
</SettingsSection>
|
|
</>
|
|
)}
|
|
</SettingsList>
|
|
</SettingsPage>
|
|
);
|
|
}
|
|
|
|
type EnabledProxySetting = Extract<ProxySetting, { type: "enabled" }>;
|
|
|
|
function enabledProxyOrDefault(proxy: ProxySetting | null): EnabledProxySetting {
|
|
if (proxy?.type === "enabled") return proxy;
|
|
|
|
return {
|
|
disabled: false,
|
|
type: "enabled",
|
|
http: "",
|
|
https: "",
|
|
auth: { user: "", password: "" },
|
|
bypass: "",
|
|
};
|
|
}
|