Skip to content

Commit

Permalink
feat: add configure tuic modal (#157)
Browse files Browse the repository at this point in the history
* feat: add configure tuic modal

* feat(tuic): add congestion control select options

---------

Co-authored-by: Kevin Yu <[email protected]>
  • Loading branch information
kunish and piyoki authored Jul 13, 2023
1 parent 2ad88ea commit a564445
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 8 deletions.
4 changes: 2 additions & 2 deletions src/components/ConfigureNodeFormModal/TrojanForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -92,7 +92,7 @@ export const TrojanForm = ({ onLinkGeneration }: { onLinkGeneration: (link: stri
)}

<Checkbox
label="Allow Insecure"
label={t('allowInsecure')}
disabled={values.method !== 'origin' || values.obfs !== 'none'}
{...getInputProps('allowInsecure', { type: 'checkbox' })}
/>
Expand Down
81 changes: 81 additions & 0 deletions src/components/ConfigureNodeFormModal/TuicForm.tsx
Original file line number Diff line number Diff line change
@@ -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<z.infer<typeof tuicSchema>>({
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 (
<form onSubmit={handleSubmit}>
<TextInput label={t('configureNode.name')} {...getInputProps('name')} />

<TextInput label={t('configureNode.host')} withAsterisk {...getInputProps('server')} />

<NumberInput label={t('configureNode.port')} withAsterisk min={0} max={65535} {...getInputProps('port')} />

<TextInput label="UUID" withAsterisk {...getInputProps('uuid')} />

<TextInput label={t('configureNode.password')} withAsterisk {...getInputProps('password')} />

<Select
label={t('configureNode.congestionControl')}
data={[
{ label: 'bbr', value: 'bbr' },
{ label: 'cubic', value: 'cubic' },
]}
{...getInputProps('congestion_control')}
/>

<TextInput label="Alpn" {...getInputProps('alpn')} />

<TextInput label="SNI" {...getInputProps('sni')} />

<Checkbox label="Disable SNI" {...getInputProps('disable_sni', { type: 'checkbox' })} />

<Select
label="UDP Relay Mode"
data={[
{ label: 'native', value: 'native' },
{ label: 'quic', value: 'quic' },
]}
{...getInputProps('udp_relay_mode')}
/>

<Checkbox label={t('allowInsecure')} {...getInputProps('allowInsecure', { type: 'checkbox' })} />

<FormActions reset={reset} />
</form>
)
}
20 changes: 15 additions & 5 deletions src/components/ConfigureNodeFormModal/index.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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() })
Expand Down Expand Up @@ -38,16 +39,18 @@ export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; o
}

return (
<Modal opened={opened} onClose={onClose} title={t('configureNode.title')} size="md">
<Modal opened={opened} onClose={onClose} title={t('configureNode.title')} size="auto">
<TextInput size="xs" label={t('tag')} withAsterisk {...form.getInputProps('tag')} />

<Divider />

<MantineProvider
theme={{
components: {
Tabs: { defaultProps: { variant: 'outline' } },
TabsPanel: { defaultProps: { pt: 'md' } },
TabsPanel: { defaultProps: { pt: 'xs' } },
TextInput: { defaultProps: { size: 'xs' } },
Select: { defaultProps: { size: 'xs' } },
NumberInput: { defaultProps: { size: 'xs' } },
Checkbox: { defaultProps: { size: 'xs' } },
Stack: { defaultProps: { spacing: 'xs' } },
},
}}
Expand All @@ -59,6 +62,7 @@ export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; o
<Tabs.Tab value="ss">SS</Tabs.Tab>
<Tabs.Tab value="ssr">SSR</Tabs.Tab>
<Tabs.Tab value="trojan">Trojan</Tabs.Tab>
<Tabs.Tab value="tuic">Tuic</Tabs.Tab>
<Tabs.Tab value="http">HTTP</Tabs.Tab>
<Tabs.Tab value="socks5">SOCKS5</Tabs.Tab>
</Tabs.List>
Expand Down Expand Up @@ -87,6 +91,12 @@ export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; o
</Stack>
</Tabs.Panel>

<Tabs.Panel value="tuic">
<Stack>
<TuicForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="http">
<Stack>
<HTTPForm onLinkGeneration={onLinkGeneration} />
Expand Down
16 changes: 15 additions & 1 deletion src/constants/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down Expand Up @@ -132,6 +132,20 @@ export const DEFAULT_TROJAN_FORM_VALUES: z.infer<typeof trojanSchema> = {
ssPassword: '',
}

export const DEFAULT_TUIC_FORM_VALUES: z.infer<typeof tuicSchema> = {
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<typeof httpSchema> = {
host: '',
name: '',
Expand Down
14 changes: 14 additions & 0 deletions src/constants/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"collapse": "collapse",
"config": "Config",
"configureNode": {
"congestionControl": "Congestion Control",
"dtlsObfuscation": "Obfuscated as DTLS1.2 Packets",
"forceTLS": "forcibly TLS on",
"host": "Host",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/zh-Hans.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"collapse": "折叠",
"config": "配置",
"configureNode": {
"congestionControl": "拥堵控制算法",
"dtlsObfuscation": "伪装为 DTLS1.2 数据包",
"forceTLS": "强制开启 TLS",
"host": "主机地址",
Expand Down

0 comments on commit a564445

Please sign in to comment.