feat(config): select tunnel mode

This commit is contained in:
kunish 2023-09-12 20:50:52 +08:00
parent 9f227c9c2c
commit 34ea1f1c56
No known key found for this signature in database
GPG Key ID: 647A12B4F782C430
10 changed files with 73 additions and 14 deletions

View File

@ -36,7 +36,6 @@ export const themes = [
export enum ROUTES { export enum ROUTES {
Overview = '/overview', Overview = '/overview',
Proxies = '/proxies', Proxies = '/proxies',
ProxyProvider = '/proxyprovider',
Rules = '/rules', Rules = '/rules',
Conns = '/conns', Conns = '/conns',
Log = '/logs', Log = '/logs',
@ -148,3 +147,9 @@ export enum TAILWINDCSS_SIZE {
MD = 'md', MD = 'md',
LG = 'lg', LG = 'lg',
} }
export enum MODE_OPTIONS {
Global = 'global',
Rule = 'rule',
Direct = 'direct',
}

View File

@ -75,4 +75,7 @@ export default {
details: 'Details', details: 'Details',
endpointURL: 'Endpoint URL', endpointURL: 'Endpoint URL',
secret: 'Secret', secret: 'Secret',
global: 'Global',
rule: 'Rule',
direct: 'Direct',
} }

View File

@ -75,4 +75,7 @@ export default {
details: '详情', details: '详情',
endpointURL: '后端地址', endpointURL: '后端地址',
secret: '密钥', secret: '密钥',
global: '全局',
rule: '规则',
direct: '直连',
} }

View File

@ -14,6 +14,7 @@ import { z } from 'zod'
import { Button } from '~/components' import { Button } from '~/components'
import { import {
LANG, LANG,
MODE_OPTIONS,
PROXIES_ORDERING_TYPE, PROXIES_ORDERING_TYPE,
PROXIES_PREVIEW_TYPE, PROXIES_PREVIEW_TYPE,
ROUTES, ROUTES,
@ -24,14 +25,17 @@ import {
applyThemeByMode, applyThemeByMode,
autoCloseConns, autoCloseConns,
autoSwitchTheme, autoSwitchTheme,
backendConfig,
favDayTheme, favDayTheme,
favNightTheme, favNightTheme,
fetchBackendConfig,
latencyTestTimeoutDuration, latencyTestTimeoutDuration,
proxiesOrderingType, proxiesOrderingType,
proxiesPreviewType, proxiesPreviewType,
renderInTwoColumns, renderInTwoColumns,
setAutoCloseConns, setAutoCloseConns,
setAutoSwitchTheme, setAutoSwitchTheme,
setBackendConfig,
setFavDayTheme, setFavDayTheme,
setFavNightTheme, setFavNightTheme,
setLatencyTestTimeoutDuration, setLatencyTestTimeoutDuration,
@ -43,11 +47,12 @@ import {
setTwemoji, setTwemoji,
setUrlForLatencyTest, setUrlForLatencyTest,
tableSize, tableSize,
updateBackendConfig,
urlForLatencyTest, urlForLatencyTest,
useRequest, useRequest,
useTwemoji, useTwemoji,
} from '~/signals' } from '~/signals'
import type { BackendVersion, DNSQuery, Config as IConfig } from '~/types' import type { BackendVersion, DNSQuery } from '~/types'
const dnsQueryFormSchema = z.object({ const dnsQueryFormSchema = z.object({
name: z.string(), name: z.string(),
@ -155,8 +160,8 @@ const ConfigForm = () => {
>({ extend: validator({ schema: configFormSchema }) }) >({ extend: validator({ schema: configFormSchema }) })
onMount(async () => { onMount(async () => {
const configs = await request.get('configs').json<IConfig>() const configs = await fetchBackendConfig()
setBackendConfig(configs)
setInitialValues(configs) setInitialValues(configs)
reset() reset()
}) })
@ -191,6 +196,16 @@ const ConfigForm = () => {
return ( return (
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<select
class="select select-bordered"
value={backendConfig()?.mode}
onChange={(e) => updateBackendConfig('mode', e.target.value)}
>
<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>
<form class="contents" use:form={form}> <form class="contents" use:form={form}>
<For each={portsList}> <For each={portsList}>
{(item) => ( {(item) => (

View File

@ -334,20 +334,20 @@ export default () => {
<div class="join flex w-full items-center md:flex-1"> <div class="join flex w-full items-center md:flex-1">
<input <input
type="search" type="search"
class="input join-item input-primary flex-1 sm:input-md" class="input join-item input-primary input-sm min-w-0 flex-1 sm:input-md"
placeholder={t('search')} placeholder={t('search')}
onInput={(e) => setGlobalFilter(e.target.value)} onInput={(e) => setGlobalFilter(e.target.value)}
/> />
<Button <Button
class="join-item sm:btn-md" class="join-item btn-sm sm:btn-md"
onClick={() => setPaused((paused) => !paused)} onClick={() => setPaused((paused) => !paused)}
> >
{paused() ? <IconPlayerPlay /> : <IconPlayerPause />} {paused() ? <IconPlayerPlay /> : <IconPlayerPause />}
</Button> </Button>
<Button <Button
class="join-item sm:btn-md" class="join-item btn-sm sm:btn-md"
onClick={() => { onClick={() => {
if (table.getState().globalFilter) { if (table.getState().globalFilter) {
table table
@ -362,7 +362,7 @@ export default () => {
</Button> </Button>
<Button <Button
class="btn join-item sm:btn-md" class="btn join-item btn-sm sm:btn-md"
onClick={() => { onClick={() => {
const modal = document.querySelector( const modal = document.querySelector(
'#connections-table-ordering-modal', '#connections-table-ordering-modal',

View File

@ -82,7 +82,7 @@ export default () => {
<div class="flex h-full flex-col gap-4 p-1"> <div class="flex h-full flex-col gap-4 p-1">
<input <input
type="search" type="search"
class="input input-primary flex-shrink-0" class="input input-primary input-sm flex-shrink-0 sm:input-md"
placeholder={t('search')} placeholder={t('search')}
onInput={(e) => setSearch(e.target.value)} onInput={(e) => setSearch(e.target.value)}
/> />

View File

@ -99,7 +99,7 @@ export default () => {
<button <button
class={twMerge( class={twMerge(
activeTab() === tab.type && 'tab-active', activeTab() === tab.type && 'tab-active',
'tab gap-2 px-2', 'tab tab-sm gap-2 px-2 sm:tab-md',
)} )}
onClick={() => setActiveTab(tab.type)} onClick={() => setActiveTab(tab.type)}
> >

View File

@ -63,13 +63,13 @@ export default () => {
<div class="flex h-full flex-col gap-2"> <div class="flex h-full flex-col gap-2">
<Show when={ruleProviders().length > 0}> <Show when={ruleProviders().length > 0}>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<div class="tabs-boxed tabs gap-2"> <div class="tabs tabs-boxed gap-2">
<For each={tabs()}> <For each={tabs()}>
{(tab) => ( {(tab) => (
<button <button
class={twMerge( class={twMerge(
activeTab() === tab.type && 'tab-active', activeTab() === tab.type && 'tab-active',
'tab gap-2 px-2', 'tab tab-sm gap-2 px-2 md:tab-md',
)} )}
onClick={() => setActiveTab(tab.type)} onClick={() => setActiveTab(tab.type)}
> >

View File

@ -1,5 +1,6 @@
import { makePersisted } from '@solid-primitives/storage' import { makePersisted } from '@solid-primitives/storage'
import { createSignal } from 'solid-js' import { createSignal } from 'solid-js'
import { toast } from 'solid-toast'
import { import {
LATENCY_QUALITY_MAP_HTTP, LATENCY_QUALITY_MAP_HTTP,
LATENCY_QUALITY_MAP_HTTPS, LATENCY_QUALITY_MAP_HTTPS,
@ -7,7 +8,8 @@ import {
PROXIES_PREVIEW_TYPE, PROXIES_PREVIEW_TYPE,
TAILWINDCSS_SIZE, TAILWINDCSS_SIZE,
} from '~/constants' } from '~/constants'
import { setCurTheme } from '~/signals' import { setCurTheme, useRequest } from '~/signals'
import { Config } from '~/types'
export const [proxiesPreviewType, setProxiesPreviewType] = makePersisted( export const [proxiesPreviewType, setProxiesPreviewType] = makePersisted(
createSignal(PROXIES_PREVIEW_TYPE.Auto), createSignal(PROXIES_PREVIEW_TYPE.Auto),
@ -103,3 +105,34 @@ export const useAutoSwitchTheme = () => {
.matchMedia('(prefers-color-scheme: dark)') .matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (event) => setTheme(event.matches)) .addEventListener('change', (event) => setTheme(event.matches))
} }
export const [backendConfig, setBackendConfig] = createSignal<Config>()
export const fetchBackendConfig = () => {
const request = useRequest()
return request.get('configs').json<Config>()
}
export const updateBackendConfig = async (
key: keyof Config,
value: Config[keyof Config],
) => {
try {
const request = useRequest()
await request
.patch('configs', {
body: JSON.stringify({
[key]: value,
}),
})
.json<Config>()
const updatedConfig = await fetchBackendConfig()
setBackendConfig(updatedConfig)
} catch (err) {
toast.error((err as Error).message)
}
}

View File

@ -111,6 +111,7 @@ export type Log = {
} }
export type Config = { export type Config = {
mode: 'global' | 'rule' | 'direct'
port: number port: number
'socks-port': number 'socks-port': number
'redir-port': number 'redir-port': number
@ -137,7 +138,6 @@ export type Config = {
'allow-lan': boolean 'allow-lan': boolean
'bind-address': string 'bind-address': string
'inbound-tfo': boolean 'inbound-tfo': boolean
mode: 'rule' | 'global'
UnifiedDelay: boolean UnifiedDelay: boolean
'log-level': string 'log-level': string
ipv6: boolean ipv6: boolean