diff --git a/src/components/ConfigureNodeFormModal/TrojanForm.tsx b/src/components/ConfigureNodeFormModal/TrojanForm.tsx index a5f1e0fa..4e10af4a 100644 --- a/src/components/ConfigureNodeFormModal/TrojanForm.tsx +++ b/src/components/ConfigureNodeFormModal/TrojanForm.tsx @@ -43,7 +43,7 @@ export const TrojanForm = ({ onLinkGeneration }: { onLinkGeneration: (link: stri return onLinkGeneration( generateURL({ - protocol: protocol, + protocol, username: values.password, host: values.server, port: values.port, @@ -92,7 +92,7 @@ export const TrojanForm = ({ onLinkGeneration }: { onLinkGeneration: (link: stri )} diff --git a/src/components/ConfigureNodeFormModal/TuicForm.tsx b/src/components/ConfigureNodeFormModal/TuicForm.tsx new file mode 100644 index 00000000..0090a0d4 --- /dev/null +++ b/src/components/ConfigureNodeFormModal/TuicForm.tsx @@ -0,0 +1,81 @@ +import { Checkbox, NumberInput, Select, TextInput } from '@mantine/core' +import { useForm, zodResolver } from '@mantine/form' +import { useTranslation } from 'react-i18next' +import { z } from 'zod' + +import { FormActions } from '~/components/FormActions' +import { DEFAULT_TUIC_FORM_VALUES, tuicSchema } from '~/constants' +import { generateURL } from '~/utils' + +export const TuicForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => { + const { t } = useTranslation() + const { onSubmit, getInputProps, reset } = useForm>({ + initialValues: DEFAULT_TUIC_FORM_VALUES, + validate: zodResolver(tuicSchema), + }) + + const handleSubmit = onSubmit((values) => { + const query = { + congestion_control: values.congestion_control, + alpn: values.alpn, + sni: values.sni, + allow_insecure: values.allowInsecure, + disable_sni: values.disable_sni, + udp_relay_mode: values.udp_relay_mode, + } + + return onLinkGeneration( + generateURL({ + protocol: 'tuic', + username: values.uuid, + password: values.password, + host: values.server, + port: values.port, + hash: values.name, + params: query, + }), + ) + }) + + return ( +
+ + + + + + + + + + + + + + + + + ) +} diff --git a/src/components/ConfigureNodeFormModal/index.tsx b/src/components/ConfigureNodeFormModal/index.tsx index f0f94e29..aec18ce9 100644 --- a/src/components/ConfigureNodeFormModal/index.tsx +++ b/src/components/ConfigureNodeFormModal/index.tsx @@ -1,4 +1,4 @@ -import { Divider, MantineProvider, Modal, Stack, Tabs, TextInput } from '@mantine/core' +import { MantineProvider, Modal, Stack, Tabs, TextInput } from '@mantine/core' import { useForm, zodResolver } from '@mantine/form' import { useTranslation } from 'react-i18next' import { z } from 'zod' @@ -10,6 +10,7 @@ import { SSForm } from './SSForm' import { SSRForm } from './SSRForm' import { Socks5Form } from './Socks5Form' import { TrojanForm } from './TrojanForm' +import { TuicForm } from './TuicForm' import { V2rayForm } from './V2rayForm' const schema = z.object({ tag: z.string().nonempty() }) @@ -38,16 +39,18 @@ export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; o } return ( - + - - SS SSR Trojan + Tuic HTTP SOCKS5 @@ -87,6 +91,12 @@ export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; o + + + + + + diff --git a/src/constants/default.ts b/src/constants/default.ts index 8aa4fd12..8fdd6203 100644 --- a/src/constants/default.ts +++ b/src/constants/default.ts @@ -3,7 +3,7 @@ import { z } from 'zod' import { GlobalInput, Policy } from '~/schemas/gql/graphql' import { DialMode, LogLevel, TLSImplementation, TcpCheckHttpMethod, UTLSImitate } from './misc' -import { httpSchema, socks5Schema, ssSchema, ssrSchema, trojanSchema, v2raySchema } from './schema' +import { httpSchema, socks5Schema, ssSchema, ssrSchema, trojanSchema, tuicSchema, v2raySchema } from './schema' export const DEFAULT_ENDPOINT_URL = `${location.protocol}//${location.hostname}:2023/graphql` @@ -132,6 +132,20 @@ export const DEFAULT_TROJAN_FORM_VALUES: z.infer = { ssPassword: '', } +export const DEFAULT_TUIC_FORM_VALUES: z.infer = { + name: '', + port: 0, + server: '', + alpn: '', + congestion_control: '', + disable_sni: false, + allowInsecure: false, + uuid: '', + password: '', + udp_relay_mode: '', + sni: '', +} + export const DEFAULT_HTTP_FORM_VALUES: z.infer = { host: '', name: '', diff --git a/src/constants/schema.ts b/src/constants/schema.ts index 24755ca2..5f02d430 100644 --- a/src/constants/schema.ts +++ b/src/constants/schema.ts @@ -92,6 +92,20 @@ export const trojanSchema = z.object({ obfs: z.enum(['none', 'websocket']), }) +export const tuicSchema = z.object({ + name: z.string(), + server: z.string().nonempty(), + port: z.number().min(0).max(65535), + uuid: z.string().nonempty(), + password: z.string().nonempty(), + allowInsecure: z.boolean(), + disable_sni: z.boolean(), + sni: z.string(), + congestion_control: z.string(), + alpn: z.string(), + udp_relay_mode: z.string(), +}) + export const httpSchema = z.object({ username: z.string(), password: z.string(), diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index abba6006..4f37dc12 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -41,6 +41,7 @@ "collapse": "collapse", "config": "Config", "configureNode": { + "congestionControl": "Congestion Control", "dtlsObfuscation": "Obfuscated as DTLS1.2 Packets", "forceTLS": "forcibly TLS on", "host": "Host", diff --git a/src/i18n/locales/zh-Hans.json b/src/i18n/locales/zh-Hans.json index 7564a58e..d09b715d 100644 --- a/src/i18n/locales/zh-Hans.json +++ b/src/i18n/locales/zh-Hans.json @@ -41,6 +41,7 @@ "collapse": "折叠", "config": "配置", "configureNode": { + "congestionControl": "拥堵控制算法", "dtlsObfuscation": "伪装为 DTLS1.2 数据包", "forceTLS": "强制开启 TLS", "host": "主机地址",