2023-08-28 22:36:38 +08:00
|
|
|
import { createForm } from '@felte/solid'
|
|
|
|
import { validator } from '@felte/validator-zod'
|
2023-09-02 13:54:59 +08:00
|
|
|
import { useI18n } from '@solid-primitives/i18n'
|
2023-09-05 20:53:00 +08:00
|
|
|
import { useNavigate } from '@solidjs/router'
|
2023-09-05 22:32:47 +08:00
|
|
|
import {
|
|
|
|
For,
|
|
|
|
ParentComponent,
|
|
|
|
Show,
|
|
|
|
children,
|
|
|
|
createSignal,
|
|
|
|
onMount,
|
|
|
|
} from 'solid-js'
|
2023-08-28 22:13:48 +08:00
|
|
|
import { z } from 'zod'
|
2023-09-12 21:33:16 +08:00
|
|
|
import {
|
|
|
|
fetchBackendConfigAPI,
|
|
|
|
fetchBackendVersionAPI,
|
|
|
|
restartBackendAPI,
|
|
|
|
restartingBackend,
|
|
|
|
updateBackendConfigAPI,
|
|
|
|
updateGEODatabasesAPI,
|
|
|
|
updatingGEODatabases,
|
|
|
|
upgradeBackendAPI,
|
|
|
|
upgradingBackend,
|
|
|
|
} from '~/apis'
|
2023-09-03 03:26:29 +08:00
|
|
|
import { Button } from '~/components'
|
2023-09-03 05:35:08 +08:00
|
|
|
import {
|
2023-09-05 21:09:35 +08:00
|
|
|
LANG,
|
2023-09-14 16:49:39 +08:00
|
|
|
LOG_LEVEL,
|
2023-09-12 20:50:52 +08:00
|
|
|
MODE_OPTIONS,
|
2023-09-03 05:35:08 +08:00
|
|
|
PROXIES_ORDERING_TYPE,
|
|
|
|
PROXIES_PREVIEW_TYPE,
|
2023-09-05 20:53:00 +08:00
|
|
|
ROUTES,
|
|
|
|
TAILWINDCSS_SIZE,
|
2023-09-03 05:35:08 +08:00
|
|
|
themes,
|
|
|
|
} from '~/constants'
|
2023-09-02 15:55:38 +08:00
|
|
|
import {
|
2023-09-02 19:06:02 +08:00
|
|
|
applyThemeByMode,
|
2023-09-02 15:55:38 +08:00
|
|
|
autoCloseConns,
|
2023-09-02 19:06:02 +08:00
|
|
|
autoSwitchTheme,
|
2023-09-12 20:50:52 +08:00
|
|
|
backendConfig,
|
2023-09-02 19:06:02 +08:00
|
|
|
favDayTheme,
|
|
|
|
favNightTheme,
|
2023-09-06 11:55:12 +08:00
|
|
|
latencyTestTimeoutDuration,
|
2023-09-14 16:49:39 +08:00
|
|
|
logLevel,
|
2023-09-03 05:35:08 +08:00
|
|
|
proxiesOrderingType,
|
2023-09-02 15:55:38 +08:00
|
|
|
proxiesPreviewType,
|
2023-09-06 16:08:25 +08:00
|
|
|
renderInTwoColumns,
|
2023-09-02 15:55:38 +08:00
|
|
|
setAutoCloseConns,
|
2023-09-02 19:06:02 +08:00
|
|
|
setAutoSwitchTheme,
|
2023-09-12 20:50:52 +08:00
|
|
|
setBackendConfig,
|
2023-09-02 19:06:02 +08:00
|
|
|
setFavDayTheme,
|
|
|
|
setFavNightTheme,
|
2023-09-06 11:55:12 +08:00
|
|
|
setLatencyTestTimeoutDuration,
|
2023-09-14 16:49:39 +08:00
|
|
|
setLogLevel,
|
2023-09-03 05:35:08 +08:00
|
|
|
setProxiesOrderingType,
|
2023-09-02 15:55:38 +08:00
|
|
|
setProxiesPreviewType,
|
2023-09-06 16:08:25 +08:00
|
|
|
setRenderInTwoColumns,
|
2023-09-05 20:53:00 +08:00
|
|
|
setSelectedEndpoint,
|
|
|
|
setTableSize,
|
2023-09-05 11:40:00 +08:00
|
|
|
setTwemoji,
|
2023-09-03 05:40:39 +08:00
|
|
|
setUrlForLatencyTest,
|
2023-09-05 20:53:00 +08:00
|
|
|
tableSize,
|
2023-09-03 05:40:39 +08:00
|
|
|
urlForLatencyTest,
|
2023-09-03 03:26:29 +08:00
|
|
|
useRequest,
|
2023-09-05 11:40:00 +08:00
|
|
|
useTwemoji,
|
2023-09-03 03:26:29 +08:00
|
|
|
} from '~/signals'
|
2023-09-12 21:33:16 +08:00
|
|
|
import type { DNSQuery } from '~/types'
|
2023-08-28 22:13:48 +08:00
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
const dnsQueryFormSchema = z.object({
|
|
|
|
name: z.string(),
|
|
|
|
type: z.string(),
|
|
|
|
})
|
|
|
|
|
2023-09-05 22:32:47 +08:00
|
|
|
const ConfigTitle: ParentComponent = (props) => (
|
|
|
|
<div class="pb-4 text-lg font-semibold">
|
|
|
|
{children(() => props.children)()}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
const DNSQueryForm = () => {
|
|
|
|
const [t] = useI18n()
|
|
|
|
const request = useRequest()
|
|
|
|
|
2023-09-03 02:22:38 +08:00
|
|
|
const { form, isSubmitting } = 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) || []),
|
|
|
|
)
|
|
|
|
},
|
2023-09-02 13:54:59 +08:00
|
|
|
},
|
2023-09-03 02:22:38 +08:00
|
|
|
)
|
2023-09-02 13:54:59 +08:00
|
|
|
|
|
|
|
const [DNSQueryResult, setDNSQueryResult] = createSignal<string[]>([])
|
|
|
|
|
|
|
|
return (
|
2023-09-02 14:02:25 +08:00
|
|
|
<div class="flex flex-col">
|
2023-09-02 18:04:57 +08:00
|
|
|
<form use:form={form} class="flex flex-col gap-2 sm:flex-row">
|
2023-09-10 16:42:00 +08:00
|
|
|
<input
|
|
|
|
type="search"
|
|
|
|
name="name"
|
|
|
|
class="input input-bordered w-full sm:flex-1"
|
|
|
|
/>
|
2023-09-05 22:32:47 +08:00
|
|
|
|
2023-09-02 18:04:57 +08:00
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
<select name="type" class="select select-bordered">
|
|
|
|
<option>A</option>
|
|
|
|
<option>AAAA</option>
|
|
|
|
<option>MX</option>
|
|
|
|
</select>
|
2023-09-03 02:22:38 +08:00
|
|
|
|
|
|
|
<Button type="submit" class="btn-primary" loading={isSubmitting()}>
|
2023-09-02 18:04:57 +08:00
|
|
|
{t('dnsQuery')}
|
2023-09-03 02:22:38 +08:00
|
|
|
</Button>
|
2023-09-02 18:04:57 +08:00
|
|
|
</div>
|
2023-09-02 13:54:59 +08:00
|
|
|
</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({
|
2023-08-28 22:13:48 +08:00
|
|
|
port: z.number(),
|
|
|
|
'socks-port': z.number(),
|
|
|
|
'redir-port': z.number(),
|
|
|
|
'tproxy-port': z.number(),
|
|
|
|
'mixed-port': z.number(),
|
|
|
|
})
|
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
const ConfigForm = () => {
|
2023-09-03 02:18:05 +08:00
|
|
|
const [t] = useI18n()
|
2023-09-01 14:06:21 +08:00
|
|
|
|
2023-08-31 11:15:03 +08:00
|
|
|
const portsList = [
|
2023-08-28 22:13:48 +08:00
|
|
|
{
|
2023-08-31 11:15:03 +08:00
|
|
|
label: 'Http Port',
|
2023-08-28 22:13:48 +08:00
|
|
|
key: 'port',
|
|
|
|
},
|
|
|
|
{
|
2023-08-31 11:15:03 +08:00
|
|
|
label: 'Socks Port',
|
2023-08-28 22:13:48 +08:00
|
|
|
key: 'socks-port',
|
|
|
|
},
|
|
|
|
{
|
2023-08-31 11:15:03 +08:00
|
|
|
label: 'Redir Port',
|
2023-08-28 22:13:48 +08:00
|
|
|
key: 'redir-port',
|
|
|
|
},
|
|
|
|
{
|
2023-08-31 11:15:03 +08:00
|
|
|
label: 'Tproxy Port',
|
2023-08-28 22:13:48 +08:00
|
|
|
key: 'tproxy-port',
|
|
|
|
},
|
|
|
|
{
|
2023-08-31 11:15:03 +08:00
|
|
|
label: 'Mixed Port',
|
2023-08-28 22:13:48 +08:00
|
|
|
key: 'mixed-port',
|
|
|
|
},
|
|
|
|
]
|
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
const { form, setInitialValues, reset } = createForm<
|
|
|
|
z.infer<typeof configFormSchema>
|
|
|
|
>({ extend: validator({ schema: configFormSchema }) })
|
2023-09-01 14:06:21 +08:00
|
|
|
|
2023-08-28 22:13:48 +08:00
|
|
|
onMount(async () => {
|
2023-09-12 21:33:16 +08:00
|
|
|
const configs = await fetchBackendConfigAPI()
|
2023-09-12 20:50:52 +08:00
|
|
|
setBackendConfig(configs)
|
2023-08-28 22:13:48 +08:00
|
|
|
setInitialValues(configs)
|
|
|
|
reset()
|
|
|
|
})
|
|
|
|
|
|
|
|
return (
|
2023-09-05 20:53:00 +08:00
|
|
|
<div class="flex flex-col gap-4">
|
2023-09-12 20:50:52 +08:00
|
|
|
<select
|
|
|
|
class="select select-bordered"
|
|
|
|
value={backendConfig()?.mode}
|
2023-09-12 21:33:16 +08:00
|
|
|
onChange={(e) => updateBackendConfigAPI('mode', e.target.value)}
|
2023-09-12 20:50:52 +08:00
|
|
|
>
|
|
|
|
<option value={MODE_OPTIONS.Global}>{t('global')}</option>
|
|
|
|
<option value={MODE_OPTIONS.Rule}>{t('rule')}</option>
|
|
|
|
<option value={MODE_OPTIONS.Direct}>{t('direct')}</option>
|
|
|
|
</select>
|
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
<form class="contents" use:form={form}>
|
|
|
|
<For each={portsList}>
|
|
|
|
{(item) => (
|
2023-09-03 15:30:56 +08:00
|
|
|
<div class="form-control w-64 max-w-sm">
|
2023-09-02 13:54:59 +08:00
|
|
|
<label class="label">
|
|
|
|
<span class="label-text">{item.label}</span>
|
|
|
|
</label>
|
2023-09-03 15:30:56 +08:00
|
|
|
|
2023-09-02 13:54:59 +08:00
|
|
|
<input
|
|
|
|
name={item.key}
|
|
|
|
type="number"
|
|
|
|
class="input input-bordered"
|
|
|
|
placeholder={item.label}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</For>
|
2023-09-01 14:06:21 +08:00
|
|
|
</form>
|
2023-09-03 02:18:05 +08:00
|
|
|
|
2023-09-03 15:30:56 +08:00
|
|
|
<div class="flex flex-wrap items-center gap-2">
|
2023-09-12 21:33:16 +08:00
|
|
|
<Button
|
|
|
|
loading={updatingGEODatabases()}
|
|
|
|
onClick={updateGEODatabasesAPI}
|
|
|
|
>
|
2023-09-03 02:18:05 +08:00
|
|
|
{t('updateGEODatabases')}
|
|
|
|
</Button>
|
|
|
|
|
2023-09-12 21:33:16 +08:00
|
|
|
<Button loading={upgradingBackend()} onClick={upgradeBackendAPI}>
|
2023-09-03 02:18:05 +08:00
|
|
|
{t('upgradeCore')}
|
|
|
|
</Button>
|
2023-09-04 23:35:40 +08:00
|
|
|
|
2023-09-12 21:33:16 +08:00
|
|
|
<Button loading={restartingBackend()} onClick={restartBackendAPI}>
|
2023-09-04 23:35:40 +08:00
|
|
|
{t('restartCore')}
|
|
|
|
</Button>
|
2023-09-03 02:18:05 +08:00
|
|
|
</div>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
|
|
|
<div class="flex flex-col">
|
2023-09-05 22:32:47 +08:00
|
|
|
<ConfigTitle>{t('urlForLatencyTest')}</ConfigTitle>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
|
|
|
<input
|
2023-09-05 22:32:47 +08:00
|
|
|
class="input input-bordered max-w-md"
|
2023-09-05 20:53:00 +08:00
|
|
|
value={urlForLatencyTest()}
|
|
|
|
onChange={(e) => setUrlForLatencyTest(e.target.value)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
2023-09-05 22:32:47 +08:00
|
|
|
<ConfigTitle>
|
2023-09-06 16:17:38 +08:00
|
|
|
{t('latencyTestTimeoutDuration')} ({t('ms')})
|
2023-09-05 22:32:47 +08:00
|
|
|
</ConfigTitle>
|
|
|
|
|
|
|
|
<input
|
|
|
|
type="number"
|
|
|
|
class="input input-bordered w-full max-w-md"
|
2023-09-06 11:55:12 +08:00
|
|
|
value={latencyTestTimeoutDuration()}
|
|
|
|
onChange={(e) =>
|
|
|
|
setLatencyTestTimeoutDuration(Number(e.target.value))
|
|
|
|
}
|
2023-09-05 22:32:47 +08:00
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div>
|
|
|
|
<ConfigTitle>{t('autoCloseConns')}</ConfigTitle>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
|
|
|
<input
|
|
|
|
class="toggle"
|
|
|
|
type="checkbox"
|
|
|
|
checked={autoCloseConns()}
|
|
|
|
onChange={(e) => setAutoCloseConns(e.target.checked)}
|
|
|
|
/>
|
|
|
|
</div>
|
2023-09-02 13:54:59 +08:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
2023-09-01 14:06:21 +08:00
|
|
|
|
2023-09-02 15:08:35 +08:00
|
|
|
const ConfigForXd = () => {
|
2023-09-05 21:09:35 +08:00
|
|
|
const [t, { locale }] = useI18n()
|
2023-09-05 20:53:00 +08:00
|
|
|
const navigate = useNavigate()
|
|
|
|
|
|
|
|
const onSwitchEndpointClick = () => {
|
|
|
|
setSelectedEndpoint('')
|
|
|
|
navigate(ROUTES.Setup)
|
|
|
|
}
|
2023-09-02 14:25:22 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
const autoSwitchThemeSubChild = () => (
|
|
|
|
<Show when={autoSwitchTheme()}>
|
2023-09-02 21:00:20 +08:00
|
|
|
<div class="flex flex-col">
|
2023-09-06 16:08:25 +08:00
|
|
|
<ConfigTitle>{t('favDayTheme')}</ConfigTitle>
|
2023-09-05 22:32:47 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
2023-09-04 19:12:27 +08:00
|
|
|
onChange={(e) => {
|
2023-09-06 16:08:25 +08:00
|
|
|
setFavDayTheme(e.target.value)
|
|
|
|
applyThemeByMode()
|
2023-09-04 19:12:27 +08:00
|
|
|
}}
|
2023-09-06 16:08:25 +08:00
|
|
|
>
|
|
|
|
<For each={themes}>
|
|
|
|
{(theme) => (
|
|
|
|
<option selected={favDayTheme() === theme} value={theme}>
|
|
|
|
{theme}
|
|
|
|
</option>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</select>
|
2023-09-04 19:12:27 +08:00
|
|
|
</div>
|
2023-09-02 19:06:02 +08:00
|
|
|
<div class="flex flex-col">
|
2023-09-06 16:08:25 +08:00
|
|
|
<ConfigTitle>{t('favNightTheme')}</ConfigTitle>
|
2023-09-05 22:32:47 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
2023-09-02 19:06:02 +08:00
|
|
|
onChange={(e) => {
|
2023-09-06 16:08:25 +08:00
|
|
|
setFavNightTheme(e.target.value)
|
2023-09-02 19:06:02 +08:00
|
|
|
applyThemeByMode()
|
|
|
|
}}
|
2023-09-06 16:08:25 +08:00
|
|
|
>
|
|
|
|
<For each={themes}>
|
|
|
|
{(theme) => (
|
|
|
|
<option selected={favNightTheme() === theme} value={theme}>
|
|
|
|
{theme}
|
|
|
|
</option>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</select>
|
2023-09-02 19:06:02 +08:00
|
|
|
</div>
|
2023-09-06 16:08:25 +08:00
|
|
|
</Show>
|
|
|
|
)
|
2023-09-05 22:32:47 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
const checkboxList = [
|
|
|
|
{
|
2023-09-12 21:33:16 +08:00
|
|
|
label: t('renderInTwoColumns'),
|
2023-09-06 16:08:25 +08:00
|
|
|
value: renderInTwoColumns,
|
|
|
|
onChange: setRenderInTwoColumns,
|
|
|
|
},
|
|
|
|
{
|
2023-09-12 21:33:16 +08:00
|
|
|
label: t('autoSwitchTheme'),
|
2023-09-06 16:08:25 +08:00
|
|
|
value: autoSwitchTheme,
|
|
|
|
onChange: (value: boolean) => {
|
|
|
|
setAutoSwitchTheme(value)
|
|
|
|
applyThemeByMode()
|
|
|
|
},
|
|
|
|
subChild: autoSwitchThemeSubChild,
|
|
|
|
},
|
|
|
|
{
|
2023-09-12 21:33:16 +08:00
|
|
|
label: t('useTwemoji'),
|
2023-09-06 16:08:25 +08:00
|
|
|
value: useTwemoji,
|
|
|
|
onChange: setTwemoji,
|
|
|
|
},
|
|
|
|
]
|
2023-09-03 03:26:29 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
return (
|
|
|
|
<div class="grid gap-4">
|
|
|
|
<For each={checkboxList}>
|
|
|
|
{(checkbox) => (
|
|
|
|
<>
|
|
|
|
<div class="flex flex-col">
|
2023-09-12 21:33:16 +08:00
|
|
|
<ConfigTitle>{checkbox.label}</ConfigTitle>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
2023-09-06 16:08:25 +08:00
|
|
|
<input
|
|
|
|
type="checkbox"
|
|
|
|
class="toggle"
|
|
|
|
checked={checkbox.value()}
|
|
|
|
onChange={(e) => {
|
|
|
|
checkbox.onChange(e.target.checked)
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
{checkbox.subChild?.()}
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</For>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
2023-09-02 15:55:38 +08:00
|
|
|
<div>
|
2023-09-05 22:32:47 +08:00
|
|
|
<ConfigTitle>{t('proxiesPreviewType')}</ConfigTitle>
|
2023-09-03 03:26:29 +08:00
|
|
|
|
2023-09-05 20:53:00 +08:00
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
|
|
|
value={proxiesPreviewType()}
|
|
|
|
onChange={(e) =>
|
|
|
|
setProxiesPreviewType(e.target.value as PROXIES_PREVIEW_TYPE)
|
|
|
|
}
|
|
|
|
>
|
2023-09-02 15:55:38 +08:00
|
|
|
<For each={Object.values(PROXIES_PREVIEW_TYPE)}>
|
2023-09-05 20:53:00 +08:00
|
|
|
{(value) => <option value={value}>{t(value)}</option>}
|
2023-09-02 15:55:38 +08:00
|
|
|
</For>
|
2023-09-05 20:53:00 +08:00
|
|
|
</select>
|
2023-09-02 15:08:35 +08:00
|
|
|
</div>
|
2023-09-02 15:55:38 +08:00
|
|
|
|
2023-09-03 03:26:29 +08:00
|
|
|
<div>
|
2023-09-05 22:32:47 +08:00
|
|
|
<ConfigTitle>{t('proxiesSorting')}</ConfigTitle>
|
2023-09-03 03:26:29 +08:00
|
|
|
|
2023-09-05 20:53:00 +08:00
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
|
|
|
value={proxiesOrderingType()}
|
|
|
|
onChange={(e) =>
|
|
|
|
setProxiesOrderingType(e.target.value as PROXIES_ORDERING_TYPE)
|
|
|
|
}
|
|
|
|
>
|
2023-09-03 05:35:08 +08:00
|
|
|
<For each={Object.values(PROXIES_ORDERING_TYPE)}>
|
2023-09-03 03:26:29 +08:00
|
|
|
{(value) => (
|
2023-09-05 20:53:00 +08:00
|
|
|
<option class="flex items-center gap-2" value={value}>
|
|
|
|
{t(value)}
|
|
|
|
</option>
|
2023-09-03 03:26:29 +08:00
|
|
|
)}
|
|
|
|
</For>
|
2023-09-05 20:53:00 +08:00
|
|
|
</select>
|
2023-09-03 03:26:29 +08:00
|
|
|
</div>
|
|
|
|
|
2023-09-02 15:08:35 +08:00
|
|
|
<div>
|
2023-09-05 22:32:47 +08:00
|
|
|
<ConfigTitle>{t('tableSize')}</ConfigTitle>
|
2023-09-05 20:53:00 +08:00
|
|
|
|
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
|
|
|
value={tableSize()}
|
|
|
|
onChange={(e) => setTableSize(e.target.value as TAILWINDCSS_SIZE)}
|
|
|
|
>
|
|
|
|
<For each={Object.values(TAILWINDCSS_SIZE)}>
|
|
|
|
{(value) => <option value={value}>{t(value)}</option>}
|
|
|
|
</For>
|
|
|
|
</select>
|
2023-09-02 15:55:38 +08:00
|
|
|
</div>
|
|
|
|
|
2023-09-14 16:49:39 +08:00
|
|
|
<div>
|
|
|
|
<ConfigTitle>{t('logLevel')}</ConfigTitle>
|
|
|
|
|
|
|
|
<select
|
|
|
|
class="select select-bordered w-full max-w-xs"
|
|
|
|
onChange={(e) => {
|
|
|
|
setLogLevel(e.target.value as LOG_LEVEL)
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<For
|
|
|
|
each={[
|
|
|
|
LOG_LEVEL.Info,
|
|
|
|
LOG_LEVEL.Error,
|
|
|
|
LOG_LEVEL.Warning,
|
|
|
|
LOG_LEVEL.Debug,
|
|
|
|
LOG_LEVEL.Silent,
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
{(level) => (
|
|
|
|
<option selected={logLevel() === level} value={level}>
|
|
|
|
{t(level)}
|
|
|
|
</option>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</select>
|
|
|
|
</div>
|
|
|
|
|
2023-09-05 21:09:35 +08:00
|
|
|
<div>
|
|
|
|
<Button
|
|
|
|
onClick={() => {
|
|
|
|
const curLocale = locale()
|
|
|
|
|
|
|
|
locale(curLocale === LANG.EN ? LANG.ZH : LANG.EN)
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{t('switchLanguage')}
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
|
2023-09-05 11:40:00 +08:00
|
|
|
<div>
|
2023-09-05 20:53:00 +08:00
|
|
|
<Button onClick={onSwitchEndpointClick}>{t('switchEndpoint')}</Button>
|
2023-09-02 15:08:35 +08:00
|
|
|
</div>
|
2023-09-02 15:55:38 +08:00
|
|
|
</div>
|
2023-09-02 15:08:35 +08:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-09-10 16:42:00 +08:00
|
|
|
const Versions = () => {
|
|
|
|
const [backendVersion, setBackendVersion] = createSignal('')
|
|
|
|
|
|
|
|
onMount(async () => {
|
2023-09-12 21:33:16 +08:00
|
|
|
const version = await fetchBackendVersionAPI()
|
2023-09-10 16:42:00 +08:00
|
|
|
|
|
|
|
setBackendVersion(version)
|
|
|
|
})
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div class="flex gap-4">
|
|
|
|
<kbd class="kbd">{import.meta.env.version}</kbd>
|
|
|
|
<kbd class="kbd">{backendVersion()}</kbd>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-09-02 15:08:35 +08:00
|
|
|
export default () => {
|
2023-09-02 13:54:59 +08:00
|
|
|
return (
|
|
|
|
<div class="flex flex-col gap-4">
|
|
|
|
<DNSQueryForm />
|
|
|
|
<ConfigForm />
|
2023-09-02 15:08:35 +08:00
|
|
|
<ConfigForXd />
|
2023-09-03 18:16:09 +08:00
|
|
|
|
2023-09-10 16:42:00 +08:00
|
|
|
<Versions />
|
2023-08-28 22:13:48 +08:00
|
|
|
</div>
|
|
|
|
)
|
2023-08-24 04:20:53 +08:00
|
|
|
}
|