import { useEffect, useState } from "react"; import { useReactAt } from "i18n-auto-extractor/react"; import { useJsonRpc } from "@/hooks/useJsonRpc"; import notifications from "@/notifications"; import { Button } from "@components/Button"; import { InputField } from "@components/InputField"; import { SettingsItem } from "@components/Settings/SettingsView"; interface TurnServer { url: string; username: string; credential: string; } interface RtcServersConfig { stun: string; defaultStun: string; turnServers: TurnServer[] | null; } export default function WebRtcServersSettings() { const { $at } = useReactAt(); const [send] = useJsonRpc(); const [stun, setStun] = useState(""); const [defaultStun, setDefaultStun] = useState(""); const [turnServers, setTurnServers] = useState([]); useEffect(() => { send("getRtcServersConfig", {}, resp => { if ("error" in resp) { notifications.error(`${$at("Failed to load WebRTC servers")}: ${resp.error.data || $at("Unknown error")}`); return; } const cfg = resp.result as RtcServersConfig; setDefaultStun(cfg.defaultStun); setStun(cfg.stun || cfg.defaultStun); setTurnServers(cfg.turnServers ?? []); }); }, [send]); const saveStun = (value: string) => { send("setStunServer", { stun: value }, resp => { if ("error" in resp) { notifications.error(`${$at("Failed to save STUN")}: ${resp.error.data || $at("Unknown error")}`); return; } setStun(value); notifications.success($at("STUN server saved")); }); }; const persistTurnServers = (servers: TurnServer[]) => { send("setTurnServers", { params: { servers } }, resp => { if ("error" in resp) { notifications.error(`${$at("Failed to save TURN")}: ${resp.error.data || $at("Unknown error")}`); return; } setTurnServers(servers); notifications.success($at("TURN servers saved")); }); }; const updateTurnRow = (index: number, field: keyof TurnServer, value: string) => { setTurnServers(prev => prev.map((server, i) => (i === index ? { ...server, [field]: value } : server))); }; const addTurnRow = () => { setTurnServers(prev => [...prev, { url: "", username: "", credential: "" }]); }; const deleteTurnRow = (index: number) => { persistTurnServers(turnServers.filter((_, i) => i !== index)); }; return (
setStun(e.target.value)} placeholder={defaultStun} className="min-w-0" />
{$at("TURN Servers")}
{$at("Used as relay when direct peer-to-peer connection fails")}
{turnServers.length === 0 && (
{$at("No TURN servers configured")}
)} {turnServers.map((server, index) => (
updateTurnRow(index, "url", e.target.value)} placeholder="turn:turn.example.com:3478" /> updateTurnRow(index, "username", e.target.value)} placeholder={$at("Username")} /> updateTurnRow(index, "credential", e.target.value)} placeholder={$at("Credential")} type="password" />
))}
); }