mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
208 lines
8.0 KiB
TypeScript
208 lines
8.0 KiB
TypeScript
import React, { useEffect } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import i18next from 'i18next'
|
|
import { Header, Card, Row, Col, Switch, ButtonSelect, ButtonSelectOptions, Input, Icon } from '@components'
|
|
import { APIInfo, Data, ClashXData } from '@stores'
|
|
import { updateConfig } from '@lib/request'
|
|
import { useObject } from '@lib/hook'
|
|
import { to } from '@lib/helper'
|
|
import { isClashX, jsBridge } from '@lib/jsBridge'
|
|
import './style.scss'
|
|
|
|
const languageOptions: ButtonSelectOptions[] = [{ label: '中文', value: 'zh' }, { label: 'English', value: 'en' }]
|
|
|
|
function changeLanguage (language: string) {
|
|
i18next.changeLanguage(language)
|
|
}
|
|
|
|
async function handleStartAtLoginChange (state: boolean) {
|
|
await jsBridge.setStartAtLogin(state)
|
|
}
|
|
|
|
async function handleSetSystemProxy (state: boolean) {
|
|
await jsBridge.setSystemProxy(state)
|
|
}
|
|
|
|
export default function Settings () {
|
|
const { data: clashXData, fetch: fetchClashXData } = ClashXData.useContainer()
|
|
const { data, fetch, unauthorized: { show } } = Data.useContainer()
|
|
const { data: apiInfo } = APIInfo.useContainer()
|
|
const { t, i18n } = useTranslation(['Settings'])
|
|
const { value: info, change } = useObject({
|
|
socks5ProxyPort: 7891,
|
|
httpProxyPort: 7890,
|
|
isClashX: false
|
|
})
|
|
|
|
useEffect(() => {
|
|
fetch()
|
|
if (isClashX()) {
|
|
fetchClashXData().then(() => change('isClashX', true))
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
change('socks5ProxyPort', data.general.socksPort)
|
|
change('httpProxyPort', data.general.port)
|
|
}, [data])
|
|
|
|
async function handleProxyModeChange (mode: string) {
|
|
const [, err] = await to(updateConfig({ mode }))
|
|
if (!err) {
|
|
fetch()
|
|
}
|
|
}
|
|
|
|
async function handleHttpPortSave () {
|
|
const [, err] = await to(updateConfig({ 'port': info.httpProxyPort }))
|
|
if (!err) {
|
|
await fetch()
|
|
change('httpProxyPort', data.general.port)
|
|
}
|
|
}
|
|
|
|
async function handleSocksPortSave () {
|
|
const [, err] = await to(updateConfig({ 'socks-port': info.socks5ProxyPort }))
|
|
if (!err) {
|
|
await fetch()
|
|
change('socks5ProxyPort', data.general.socksPort)
|
|
}
|
|
}
|
|
|
|
async function handleAllowLanChange (state: boolean) {
|
|
const [, err] = await to(updateConfig({ 'allow-lan': state }))
|
|
if (!err) {
|
|
await fetch()
|
|
}
|
|
}
|
|
|
|
const {
|
|
hostname: externalControllerHost,
|
|
port: externalControllerPort
|
|
} = apiInfo
|
|
|
|
const { allowLan, mode } = data.general
|
|
const {
|
|
startAtLogin,
|
|
systemProxy
|
|
} = clashXData
|
|
|
|
const proxyModeOptions: ButtonSelectOptions[] = [
|
|
{ label: t('values.global'), value: 'Global' },
|
|
{ label: t('values.rules'), value: 'Rule' },
|
|
{ label: t('values.direct'), value: 'Direct' }
|
|
]
|
|
|
|
return (
|
|
<div className="page">
|
|
<Header title={t('title')} />
|
|
<Card className="settings-card">
|
|
<Row gutter={24} align="middle">
|
|
<Col span={12}>
|
|
<Col span={14} offset={1}>
|
|
<span className="label">{t('labels.startAtLogin')}</span>
|
|
</Col>
|
|
<Col span={8} className="value-column">
|
|
<Switch disabled={!isClashX} checked={startAtLogin} onChange={handleStartAtLoginChange} />
|
|
</Col>
|
|
</Col>
|
|
<Col span={12}>
|
|
<Col span={8} offset={1}>
|
|
<span className="label">{t('labels.language')}</span>
|
|
</Col>
|
|
<Col span={14} className="value-column">
|
|
<ButtonSelect options={languageOptions} value={i18n.language.replace(/-.+$/, '')} onSelect={changeLanguage} />
|
|
</Col>
|
|
</Col>
|
|
</Row>
|
|
<Row gutter={24} align="middle">
|
|
<Col span={12}>
|
|
<Col span={14} offset={1}>
|
|
<span className="label">{t('labels.setAsSystemProxy')}</span>
|
|
</Col>
|
|
<Col span={8} className="value-column">
|
|
<Switch
|
|
disabled={!isClashX}
|
|
checked={systemProxy}
|
|
onChange={handleSetSystemProxy}
|
|
/>
|
|
</Col>
|
|
</Col>
|
|
<Col span={12}>
|
|
<Col span={14} offset={1}>
|
|
<span className="label">{t('labels.allowConnectFromLan')}</span>
|
|
</Col>
|
|
<Col span={8} className="value-column">
|
|
<Switch
|
|
checked={allowLan}
|
|
onChange={handleAllowLanChange}
|
|
/>
|
|
</Col>
|
|
</Col>
|
|
</Row>
|
|
</Card>
|
|
|
|
<Card className="settings-card">
|
|
<Row gutter={24} align="middle">
|
|
<Col span={12}>
|
|
<Col span={8} offset={1}>
|
|
<span className="label">{t('labels.proxyMode')}</span>
|
|
</Col>
|
|
<Col span={14} className="value-column">
|
|
<ButtonSelect
|
|
options={proxyModeOptions}
|
|
value={mode}
|
|
onSelect={handleProxyModeChange}
|
|
/>
|
|
</Col>
|
|
</Col>
|
|
<Col span={12}>
|
|
<Col span={14} offset={1}>
|
|
<span className="label">{t('labels.socks5ProxyPort')}</span>
|
|
</Col>
|
|
<Col span={8}>
|
|
<Input
|
|
value={info.socks5ProxyPort}
|
|
onChange={socks5ProxyPort => change('socks5ProxyPort', parseInt(socks5ProxyPort, 10))}
|
|
onBlur={handleSocksPortSave}
|
|
/>
|
|
</Col>
|
|
</Col>
|
|
</Row>
|
|
<Row gutter={24} align="middle">
|
|
<Col span={12}>
|
|
<Col span={14} offset={1}>
|
|
<span className="label">{t('labels.httpProxyPort')}</span>
|
|
</Col>
|
|
<Col span={8}>
|
|
<Input
|
|
value={info.httpProxyPort}
|
|
onChange={httpProxyPort => change('httpProxyPort', parseInt(httpProxyPort, 10))}
|
|
onBlur={handleHttpPortSave}
|
|
/>
|
|
</Col>
|
|
</Col>
|
|
<Col span={12}>
|
|
<Col span={12} offset={1}>
|
|
<span className="label">{t('labels.externalController')}</span>
|
|
</Col>
|
|
<Col className="external-controller" span={10}>
|
|
<span className="modify-btn" onClick={show}>
|
|
{`${externalControllerHost}:${externalControllerPort}`}
|
|
</span>
|
|
</Col>
|
|
</Col>
|
|
</Row>
|
|
</Card>
|
|
|
|
<Card className="clash-version" style={{ display: 'none' }}>
|
|
<span className="check-icon">
|
|
<Icon type="check" size={20} />
|
|
</span>
|
|
<p className="version-info">{t('versionString', { version: 'unknown' })}</p>
|
|
<span className="check-update-btn">{t('checkUpdate')}</span>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|