mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
Fix: ExternalControllerModal bug
This commit is contained in:
parent
541d36a8e2
commit
213c5dabe3
@ -2,13 +2,13 @@ import React, { useEffect } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useObject } from '@lib/hook'
|
import { useObject } from '@lib/hook'
|
||||||
import { Modal, Input, Row, Col, Alert } from '@components'
|
import { Modal, Input, Row, Col, Alert } from '@components'
|
||||||
import { APIInfo, ExternalControllerModal } from '@stores'
|
import { APIInfo, Data } from '@stores'
|
||||||
import './style.scss'
|
import './style.scss'
|
||||||
|
|
||||||
export default function ExternalController () {
|
export default function ExternalController () {
|
||||||
const { t } = useTranslation(['Settings'])
|
const { t } = useTranslation(['Settings'])
|
||||||
const { data: info, update, fetch } = APIInfo.useContainer()
|
const { data: info, update, fetch } = APIInfo.useContainer()
|
||||||
const { hidden, visible } = ExternalControllerModal.useContainer()
|
const { unauthorized: { hidden, visible } } = Data.useContainer()
|
||||||
const { value, set, change } = useObject({
|
const { value, set, change } = useObject({
|
||||||
hostname: '',
|
hostname: '',
|
||||||
port: '',
|
port: '',
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
import React, { useState, useMemo, useLayoutEffect, useEffect } from 'react'
|
import React, { useState, useMemo, useLayoutEffect, useEffect } from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { BaseComponentProps, TagColors } from '@models'
|
import { BaseComponentProps } from '@models'
|
||||||
import { getProxyDelay, Proxy as IProxy } from '@lib/request'
|
import { getProxyDelay, Proxy as IProxy } from '@lib/request'
|
||||||
import EE, { Action } from '@lib/event'
|
import EE, { Action } from '@lib/event'
|
||||||
import { isClashX, jsBridge } from '@lib/jsBridge'
|
import { isClashX, jsBridge } from '@lib/jsBridge'
|
||||||
import { to, getLocalStorageItem, setLocalStorageItem, sample } from '@lib/helper'
|
import { to } from '@lib/helper'
|
||||||
import './style.scss'
|
import './style.scss'
|
||||||
|
|
||||||
interface ProxyProps extends BaseComponentProps {
|
interface ProxyProps extends BaseComponentProps {
|
||||||
config: IProxy
|
config: IProxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TagColors = {
|
||||||
|
'#909399': 0,
|
||||||
|
'#00c520': 150,
|
||||||
|
'#ff9a28': 500,
|
||||||
|
'#ff3e5e': Infinity
|
||||||
|
}
|
||||||
|
|
||||||
async function getDelay (name: string) {
|
async function getDelay (name: string) {
|
||||||
if (isClashX()) {
|
if (isClashX()) {
|
||||||
const delay = await jsBridge.getProxyDelay(name)
|
const delay = await jsBridge.getProxyDelay(name)
|
||||||
@ -40,16 +47,7 @@ export function Proxy (props: ProxyProps) {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const hasError = useMemo(() => delay === 0, [delay])
|
const hasError = useMemo(() => delay === 0, [delay])
|
||||||
const color = useMemo(() => {
|
const color = useMemo(() => Object.keys(TagColors).find(threshold => delay <= TagColors[threshold]), [delay])
|
||||||
let color = getLocalStorageItem(config.name)
|
|
||||||
|
|
||||||
if (!color) {
|
|
||||||
color = sample(TagColors)
|
|
||||||
setLocalStorageItem(name, color)
|
|
||||||
}
|
|
||||||
|
|
||||||
return color
|
|
||||||
}, [config])
|
|
||||||
|
|
||||||
const backgroundColor = hasError ? undefined : color
|
const backgroundColor = hasError ? undefined : color
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,7 @@ import React, { useEffect } from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import i18next from 'i18next'
|
import i18next from 'i18next'
|
||||||
import { Header, Card, Row, Col, Switch, ButtonSelect, ButtonSelectOptions, Input, Icon } from '@components'
|
import { Header, Card, Row, Col, Switch, ButtonSelect, ButtonSelectOptions, Input, Icon } from '@components'
|
||||||
import { APIInfo, Data, ClashXData, ExternalControllerModal } from '@stores'
|
import { APIInfo, Data, ClashXData } from '@stores'
|
||||||
import { updateConfig } from '@lib/request'
|
import { updateConfig } from '@lib/request'
|
||||||
import { useObject } from '@lib/hook'
|
import { useObject } from '@lib/hook'
|
||||||
import { to } from '@lib/helper'
|
import { to } from '@lib/helper'
|
||||||
@ -25,9 +25,8 @@ async function handleSetSystemProxy (state: boolean) {
|
|||||||
|
|
||||||
export default function Settings () {
|
export default function Settings () {
|
||||||
const { data: clashXData, fetch: fetchClashXData } = ClashXData.useContainer()
|
const { data: clashXData, fetch: fetchClashXData } = ClashXData.useContainer()
|
||||||
const { data, fetch } = Data.useContainer()
|
const { data, fetch, unauthorized: { show } } = Data.useContainer()
|
||||||
const { data: apiInfo } = APIInfo.useContainer()
|
const { data: apiInfo } = APIInfo.useContainer()
|
||||||
const { show } = ExternalControllerModal.useContainer()
|
|
||||||
const { t, i18n } = useTranslation(['Settings'])
|
const { t, i18n } = useTranslation(['Settings'])
|
||||||
const { value: info, change } = useObject({
|
const { value: info, change } = useObject({
|
||||||
socks5ProxyPort: 7891,
|
socks5ProxyPort: 7891,
|
||||||
|
@ -10,14 +10,6 @@ export function removeLocalStorageItem (key: string) {
|
|||||||
return window.localStorage.removeItem(key)
|
return window.localStorage.removeItem(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function randomNumber (min: number, max: number) {
|
|
||||||
return (min + Math.random() * (max - min)) >> 0
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sample<T> (arr: T[]) {
|
|
||||||
return arr[randomNumber(0, arr.length)]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function noop () {}
|
export function noop () {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import axios, { AxiosInstance } from 'axios'
|
import axios, { AxiosInstance } from 'axios'
|
||||||
import { Partial, getLocalStorageItem } from '@lib/helper'
|
import { Partial, getLocalStorageItem } from '@lib/helper'
|
||||||
import { isClashX, jsBridge } from '@lib/jsBridge'
|
import { isClashX, jsBridge } from '@lib/jsBridge'
|
||||||
import { ExternalControllerModal } from '@stores'
|
|
||||||
import { Log } from '@models/Log'
|
import { Log } from '@models/Log'
|
||||||
import { StreamReader } from './streamer'
|
import { StreamReader } from './streamer'
|
||||||
|
|
||||||
@ -113,17 +112,6 @@ export async function getInstance () {
|
|||||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {}
|
headers: secret ? { Authorization: `Bearer ${secret}` } : {}
|
||||||
})
|
})
|
||||||
|
|
||||||
instance.interceptors.response.use(
|
|
||||||
resp => resp,
|
|
||||||
err => {
|
|
||||||
if (!err.response || err.response.status === 401) {
|
|
||||||
const { show } = ExternalControllerModal.useContainer()
|
|
||||||
show()
|
|
||||||
}
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
export const TagColors = [
|
|
||||||
'#ff3e5e',
|
|
||||||
'#686fff',
|
|
||||||
'#ff9a28',
|
|
||||||
'#b83fe6',
|
|
||||||
'#00c520'
|
|
||||||
]
|
|
@ -3,5 +3,4 @@ export * from './Config'
|
|||||||
export * from './Proxy'
|
export * from './Proxy'
|
||||||
export * from './Rule'
|
export * from './Rule'
|
||||||
export * from './I18n'
|
export * from './I18n'
|
||||||
export * from './TagColors'
|
|
||||||
export * from './Cipher'
|
export * from './Cipher'
|
||||||
|
@ -3,7 +3,7 @@ import { render } from 'react-dom'
|
|||||||
import { HashRouter } from 'react-router-dom'
|
import { HashRouter } from 'react-router-dom'
|
||||||
import { I18nextProvider } from 'react-i18next'
|
import { I18nextProvider } from 'react-i18next'
|
||||||
import { BaseComponentProps } from '@models/BaseProps'
|
import { BaseComponentProps } from '@models/BaseProps'
|
||||||
import { APIInfo, Data, ClashXData, ExternalControllerModal } from '@stores'
|
import { APIInfo, Data, ClashXData } from '@stores'
|
||||||
import App from '@containers/App'
|
import App from '@containers/App'
|
||||||
import i18n from '@i18n'
|
import i18n from '@i18n'
|
||||||
|
|
||||||
@ -12,9 +12,7 @@ function Store (props: BaseComponentProps) {
|
|||||||
<APIInfo.Provider>
|
<APIInfo.Provider>
|
||||||
<Data.Provider>
|
<Data.Provider>
|
||||||
<ClashXData.Provider>
|
<ClashXData.Provider>
|
||||||
<ExternalControllerModal.Provider>
|
|
||||||
{ props.children }
|
{ props.children }
|
||||||
</ExternalControllerModal.Provider>
|
|
||||||
</ClashXData.Provider>
|
</ClashXData.Provider>
|
||||||
</Data.Provider>
|
</Data.Provider>
|
||||||
</APIInfo.Provider>
|
</APIInfo.Provider>
|
||||||
|
@ -4,7 +4,7 @@ import { createContainer } from 'unstated-next'
|
|||||||
import * as API from '@lib/request'
|
import * as API from '@lib/request'
|
||||||
import { useObject } from '@lib/hook'
|
import { useObject } from '@lib/hook'
|
||||||
import { jsBridge, isClashX } from '@lib/jsBridge'
|
import { jsBridge, isClashX } from '@lib/jsBridge'
|
||||||
import { setLocalStorageItem, partition } from '@lib/helper'
|
import { setLocalStorageItem, partition, to } from '@lib/helper'
|
||||||
|
|
||||||
function useData () {
|
function useData () {
|
||||||
const { value: data, change } = useObject<Models.Data>({
|
const { value: data, change } = useObject<Models.Data>({
|
||||||
@ -14,8 +14,23 @@ function useData () {
|
|||||||
rules: []
|
rules: []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(false)
|
||||||
|
|
||||||
|
function show () {
|
||||||
|
setVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function hidden () {
|
||||||
|
setVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
async function fetch () {
|
async function fetch () {
|
||||||
const [{ data: general }, rawProxies, rules] = await Promise.all([API.getConfig(), API.getProxies(), API.getRules()])
|
const [resp, err] = await to(Promise.all([API.getConfig(), API.getProxies(), API.getRules()]))
|
||||||
|
if (err && (!err.response || err.response.status === 401)) {
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
|
||||||
|
const [{ data: general }, rawProxies, rules] = resp
|
||||||
|
|
||||||
change('general', {
|
change('general', {
|
||||||
port: general.port,
|
port: general.port,
|
||||||
@ -39,7 +54,7 @@ function useData () {
|
|||||||
change('rules', rules.data.rules)
|
change('rules', rules.data.rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data, fetch }
|
return { data, fetch, unauthorized: { visible, show, hidden } }
|
||||||
}
|
}
|
||||||
|
|
||||||
function useAPIInfo () {
|
function useAPIInfo () {
|
||||||
@ -86,21 +101,6 @@ function useClashXData () {
|
|||||||
return { data, fetch }
|
return { data, fetch }
|
||||||
}
|
}
|
||||||
|
|
||||||
function useExternalControllerModal () {
|
|
||||||
const [visible, setVisible] = useState(false)
|
|
||||||
|
|
||||||
function show () {
|
|
||||||
setVisible(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
function hidden () {
|
|
||||||
setVisible(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return { visible, show, hidden }
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Data = createContainer(useData)
|
export const Data = createContainer(useData)
|
||||||
export const APIInfo = createContainer(useAPIInfo)
|
export const APIInfo = createContainer(useAPIInfo)
|
||||||
export const ClashXData = createContainer(useClashXData)
|
export const ClashXData = createContainer(useClashXData)
|
||||||
export const ExternalControllerModal = createContainer(useExternalControllerModal)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user