diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/configs.ts | 6 | ||||
| -rw-r--r-- | src/components/Config.tsx | 100 | ||||
| -rw-r--r-- | src/store/configs.ts | 28 | ||||
| -rw-r--r-- | src/store/types.ts | 16 |
4 files changed, 109 insertions, 41 deletions
diff --git a/src/api/configs.ts b/src/api/configs.ts index e084261..ed2b1e9 100644 --- a/src/api/configs.ts +++ b/src/api/configs.ts @@ -1,5 +1,5 @@ import { getURLAndInit } from 'src/misc/request-helper'; -import { ClashGeneralConfig } from 'src/store/types'; +import { ClashGeneralConfig, TunPartial } from 'src/store/types'; import { ClashAPIConfig } from 'src/types'; const endpoint = '/configs'; @@ -14,7 +14,7 @@ export async function fetchConfigs(apiConfig: ClashAPIConfig) { // req body // { Path: string } -type ClashConfigPartial = Partial<ClashGeneralConfig>; +type ClashConfigPartial = TunPartial<ClashGeneralConfig>; function configsPatchWorkaround(o: ClashConfigPartial) { // backward compatibility for older clash using `socket-port` if ('socks-port' in o) { @@ -32,7 +32,7 @@ export async function updateConfigs( return await fetch(url + endpoint, { ...init, body, method: 'PATCH' }); } -export async function reloadConfigs( +export async function reloadConfigFile( apiConfig: ClashAPIConfig ) { const { url, init } = getURLAndInit(apiConfig); diff --git a/src/components/Config.tsx b/src/components/Config.tsx index 3d9e36e..808ffd9 100644 --- a/src/components/Config.tsx +++ b/src/components/Config.tsx @@ -11,7 +11,13 @@ import { getLatencyTestUrl, getSelectedChartStyleIndex, } from '../store/app'; -import { fetchConfigs, getConfigs, updateConfigs, reloadConfigs, flushFakeIPPool } from '../store/configs'; +import { + fetchConfigs, + flushFakeIPPool, + getConfigs, + reloadConfigFile, + updateConfigs, +} from '../store/configs'; import { openModal } from '../store/modals'; import Button from './Button'; import s0 from './Config.module.scss'; @@ -40,7 +46,7 @@ const portFields = [ { key: 'socks-port', label: 'SOCKS5 Proxy Port' }, { key: 'mixed-port', label: 'Mixed Port' }, { key: 'redir-port', label: 'Redir Port' }, - { key: 'tproxy-port', label: 'tProxy Port' }, + { key: 'tproxy-port', label: 'TProxy Port' }, { key: 'mitm-port', label: 'MITM Port' }, ]; @@ -50,10 +56,15 @@ const langOptions = [ ]; const modeOptions = [ - ['Global', 'Global'], - ['Rule', 'Rule'], - ['Script', 'Script'], - ['Direct', 'Direct'], + ['rule', 'Rule'], + ['script', 'Script'], + ['direct', 'Direct'], + ['global', 'Global'], +]; + +const tunStackOptions = [ + ['gVisor', 'gVisor'], + ['System', 'System'], ]; const mapState = (s: State) => ({ @@ -112,6 +123,14 @@ function ConfigImpl({ [configState] ); + const setTunConfigState = useCallback( + (name, val) => { + const tun = {...configState.tun, [name]: val } + setConfigStateInternal({ ...configState, tun: {...tun}}); + }, + [configState] + ); + const handleSwitchOnChange = useCallback( (checked: boolean) => { const name = 'allow-lan'; @@ -145,11 +164,15 @@ function ConfigImpl({ } setConfigState(name, value); break; + case 'stack': + setTunConfigState(name, value); + dispatch(updateConfigs(apiConfig, { 'tun': {[name]: value }})); + break; default: return; } }, - [apiConfig, dispatch, setConfigState] + [apiConfig, dispatch, setConfigState, setTunConfigState] ); const handleInputOnChange = useCallback( @@ -186,8 +209,8 @@ function ConfigImpl({ [apiConfig, dispatch, updateAppConfig] ); - const handleReloadConfigs = useCallback(() => { - dispatch(reloadConfigs(apiConfig)); + const handleReloadConfigFile = useCallback(() => { + dispatch(reloadConfigFile(apiConfig)); },[apiConfig, dispatch]); const handleFlushFakeIPPool = useCallback(() => { @@ -243,6 +266,17 @@ function ConfigImpl({ </div> <div> + <div className={s0.label}>TUN Stack</div> + <Select + options={tunStackOptions} + selected={configState['tun']['stack']} + onChange={(e) => + handleChangeValue({ name: 'stack', value: e.target.value }) + } + /> + </div> + + <div> <div className={s0.label}>Allow LAN</div> <div className={s0.wrapSwitch}> <Switch @@ -260,6 +294,30 @@ function ConfigImpl({ <div className={s0.section}> <div> + <div className={s0.label}>Reload</div> + <Button + start={<RotateCw size={16} />} + label={t('reload_config_file')} + onClick={handleReloadConfigFile} + /> + </div> + + <div> + <div className={s0.label}>FakeIP</div> + <Button + start={<Trash2 size={16} />} + label={t('flush_fake_ip_pool')} + onClick={handleFlushFakeIPPool} + /> + </div> + </div> + + <div className={s0.sep}> + <div /> + </div> + + <div className={s0.section}> + <div> <div className={s0.label}>{t('latency_test_url')}</div> <SelfControlledInput name="latencyTestUrl" @@ -298,30 +356,6 @@ function ConfigImpl({ /> </div> </div> - - <div className={s0.sep}> - <div /> - </div> - - <div className={s0.section}> - <div> - <div className={s0.label}>Reload</div> - <Button - start={<RotateCw size={16} />} - label={t('reload_config_file')} - onClick={handleReloadConfigs} - /> - </div> - - <div> - <div className={s0.label}>FakeIP</div> - <Button - start={<Trash2 size={16} />} - label={t('flush_fake_ip_pool')} - onClick={handleFlushFakeIPPool} - /> - </div> - </div> </div> ); } diff --git a/src/store/configs.ts b/src/store/configs.ts index b0ae2a7..c4b95de 100644 --- a/src/store/configs.ts +++ b/src/store/configs.ts @@ -4,6 +4,7 @@ import { GetStateFn, State, StateConfigs, + TunPartial, } from 'src/store/types'; import { ClashAPIConfig } from 'src/types'; @@ -59,9 +60,11 @@ function markHaveFetchedConfig() { }; } +type generalConfig = Omit<ClashGeneralConfig, 'tun'> + export function updateConfigs( apiConfig: ClashAPIConfig, - partialConfg: Partial<ClashGeneralConfig> + partialConfg: TunPartial<ClashGeneralConfig> ) { return async (dispatch: DispatchFn) => { configsAPI @@ -84,15 +87,20 @@ export function updateConfigs( }); dispatch('storeConfigsOptimisticUpdateConfigs', (s) => { - s.configs.configs = { ...s.configs.configs, ...partialConfg }; + if (partialConfg.tun != null) { + s.configs.configs.tun = { ...s.configs.configs.tun, ...partialConfg.tun }; + } else { + const config: generalConfig = {...s.configs.configs, ...partialConfg}; + s.configs.configs = config + } }); }; } -export function reloadConfigs(apiConfig: ClashAPIConfig) { +export function reloadConfigFile(apiConfig: ClashAPIConfig) { return async (dispatch: DispatchFn) => { configsAPI - .reloadConfigs(apiConfig) + .reloadConfigFile(apiConfig) .then( (res) => { if (res.ok === false) { @@ -139,10 +147,20 @@ export const initialState: StateConfigs = { configs: { port: 7890, 'socks-port': 7891, + 'mixed-port': 0, 'redir-port': 0, + 'tproxy-port': 0, + 'mitm-port': 0, 'allow-lan': false, - mode: 'Rule', + mode: 'rule', 'log-level': 'uninit', + tun: { + enable: false, + device: '', + stack: '', + 'dns-hijack': [], + 'auto-route': false, + }, }, haveFetchedConfig: false, }; diff --git a/src/store/types.ts b/src/store/types.ts index b9141ac..16402ae 100644 --- a/src/store/types.ts +++ b/src/store/types.ts @@ -16,15 +16,31 @@ export type StateApp = { logStreamingPaused: boolean; }; +export type ClashTunConfig = { + enable: boolean; + device?: string; + stack: string; + 'dns-hijack': string[]; + 'auto-route': boolean; +} + export type ClashGeneralConfig = { port: number; 'socks-port': number; + 'mixed-port': number; 'redir-port': number; + 'tproxy-port': number; + 'mitm-port'?: number; 'allow-lan': boolean; mode: string; 'log-level': string; + tun?: ClashTunConfig; }; +export type TunPartial<T> = { + [P in keyof T]?: T[P] extends ClashTunConfig ? TunPartial<T[P]> : T[P]; +} + ///// store.proxies type LatencyHistory = Array<{ time: string; delay: number }>; |
