metacubexd/src/pages/Config.tsx
2023-09-02 19:06:02 +08:00

258 lines
6.4 KiB
TypeScript

import { createForm } from '@felte/solid'
import { validator } from '@felte/validator-zod'
import { useI18n } from '@solid-primitives/i18n'
import { For, Show, createSignal, onMount } from 'solid-js'
import { z } from 'zod'
import { PROXIES_PREVIEW_TYPE } from '~/config/enum'
import { themes } from '~/constants'
import { useRequest } from '~/signals'
import {
applyThemeByMode,
autoCloseConns,
autoSwitchTheme,
favDayTheme,
favNightTheme,
proxiesPreviewType,
setAutoCloseConns,
setAutoSwitchTheme,
setFavDayTheme,
setFavNightTheme,
setProxiesPreviewType,
setUrlForDelayTest,
urlForDelayTest,
} from '~/signals/config'
import type { DNSQuery, Config as IConfig } from '~/types'
const dnsQueryFormSchema = z.object({
name: z.string(),
type: z.string(),
})
const DNSQueryForm = () => {
const [t] = useI18n()
const request = useRequest()
const { form } = createForm<z.infer<typeof dnsQueryFormSchema>>({
extend: validator({ schema: dnsQueryFormSchema }),
onSubmit: async (values) => {
request
.get('dns/query', {
searchParams: { name: values.name, type: values.type },
})
.json<DNSQuery>()
.then(({ Answer }) =>
setDNSQueryResult(Answer?.map(({ data }) => data) || []),
)
},
})
const [DNSQueryResult, setDNSQueryResult] = createSignal<string[]>([])
return (
<div class="flex flex-col">
<form use:form={form} class="flex flex-col gap-2 sm:flex-row">
<input
name="name"
class="input input-bordered w-full max-w-xs sm:flex-1"
/>
<div class="flex items-center gap-2">
<select name="type" class="select select-bordered">
<option>A</option>
<option>AAAA</option>
<option>MX</option>
</select>
<button type="submit" class="btn btn-primary">
{t('dnsQuery')}
</button>
</div>
</form>
<Show when={DNSQueryResult().length > 0}>
<div class="flex flex-col p-4">
<For each={DNSQueryResult()}>
{(item) => <div class="py-2">{item}</div>}
</For>
</div>
</Show>
</div>
)
}
const configFormSchema = z.object({
port: z.number(),
'socks-port': z.number(),
'redir-port': z.number(),
'tproxy-port': z.number(),
'mixed-port': z.number(),
})
const ConfigForm = () => {
const request = useRequest()
const portsList = [
{
label: 'Http Port',
key: 'port',
},
{
label: 'Socks Port',
key: 'socks-port',
},
{
label: 'Redir Port',
key: 'redir-port',
},
{
label: 'Tproxy Port',
key: 'tproxy-port',
},
{
label: 'Mixed Port',
key: 'mixed-port',
},
]
const { form, setInitialValues, reset } = createForm<
z.infer<typeof configFormSchema>
>({ extend: validator({ schema: configFormSchema }) })
onMount(async () => {
const configs = await request.get('configs').json<IConfig>()
setInitialValues(configs)
reset()
})
return (
<div>
<form class="contents" use:form={form}>
<For each={portsList}>
{(item) => (
<div class="form-control w-64 max-w-xs">
<label class="label">
<span class="label-text">{item.label}</span>
</label>
<input
name={item.key}
type="number"
class="input input-bordered"
placeholder={item.label}
/>
</div>
)}
</For>
</form>
</div>
)
}
const ConfigForXd = () => {
const [t] = useI18n()
return (
<div class="grid gap-4">
<div class="flex flex-col">
<div class="pb-4">{t('autoSwitchTheme')}</div>
<input
type="checkbox"
class="toggle"
checked={autoSwitchTheme()}
onChange={(e) => {
setAutoSwitchTheme(e.target.checked)
applyThemeByMode()
}}
/>
</div>
<Show when={autoSwitchTheme()}>
<div class="flex flex-col">
<div class="pb-4">{t('favDayTheme')}</div>
<select
class="select select-bordered w-full max-w-xs"
onChange={(e) => {
setFavDayTheme(e.target.value)
applyThemeByMode()
}}
>
<For each={themes}>
{(theme) => (
<option selected={favDayTheme() === theme} value={theme}>
{theme}
</option>
)}
</For>
</select>
</div>
<div class="flex flex-col">
<div class="pb-4">{t('favNightTheme')}</div>
<select
class="select select-bordered w-full max-w-xs"
onChange={(e) => {
setFavNightTheme(e.target.value)
applyThemeByMode()
}}
>
<For each={themes}>
{(theme) => (
<option selected={favNightTheme() === theme} value={theme}>
{theme}
</option>
)}
</For>
</select>
</div>
</Show>
<div>
<div class="pb-4">{t('proxiesPreviewType')}</div>
<div class="flex items-center gap-4">
<For each={Object.values(PROXIES_PREVIEW_TYPE)}>
{(value) => (
<label class="flex items-center gap-2">
<span>{t(value)}</span>
<input
class="radio"
aria-label={value}
type="radio"
checked={value === proxiesPreviewType()}
onChange={() => setProxiesPreviewType(value)}
/>
</label>
)}
</For>
</div>
</div>
<div>
<div class="pb-4">{t('autoCloseConns')}</div>
<input
class="toggle"
type="checkbox"
checked={autoCloseConns()}
onChange={(e) => setAutoCloseConns(e.target.checked)}
/>
</div>
<div class="flex flex-col">
<div class="pb-4">{t('urlForDelayTest')}</div>
<input
class="w-100 input input-bordered max-w-md"
value={urlForDelayTest()}
onChange={(e) => setUrlForDelayTest(e.target?.value!)}
/>
</div>
</div>
)
}
export default () => {
return (
<div class="flex flex-col gap-4">
<DNSQueryForm />
<ConfigForm />
<ConfigForXd />
</div>
)
}