mirror of
https://github.com/woodchen-ink/clash-and-dashboard.git
synced 2025-07-18 14:01:56 +08:00
chore: add strict: true
to tsconfig
This commit is contained in:
parent
e1a8b559d1
commit
6265c5adb1
1068
package-lock.json
generated
1068
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
41
package.json
41
package.json
@ -29,71 +29,72 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.10.5",
|
"@babel/cli": "^7.10.5",
|
||||||
"@babel/core": "^7.10.5",
|
"@babel/core": "^7.11.1",
|
||||||
"@babel/preset-env": "^7.10.4",
|
"@babel/preset-env": "^7.11.0",
|
||||||
"@babel/preset-react": "^7.10.4",
|
"@babel/preset-react": "^7.10.4",
|
||||||
"@hot-loader/react-dom": "^16.13.0",
|
"@hot-loader/react-dom": "^16.13.0",
|
||||||
"@types/classnames": "^2.2.10",
|
"@types/classnames": "^2.2.10",
|
||||||
"@types/lodash-es": "^4.17.3",
|
"@types/lodash-es": "^4.17.3",
|
||||||
"@types/node": "^14.0.23",
|
"@types/node": "^14.0.27",
|
||||||
"@types/react": "^16.9.43",
|
"@types/react": "^16.9.46",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/react-router-dom": "^5.1.5",
|
"@types/react-router-dom": "^5.1.5",
|
||||||
"@types/react-table": "^7.0.19",
|
"@types/react-table": "^7.0.22",
|
||||||
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
"@types/react-virtualized-auto-sizer": "^1.0.0",
|
||||||
"@types/react-window": "^1.8.2",
|
"@types/react-window": "^1.8.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^3.6.1",
|
"@typescript-eslint/eslint-plugin": "^3.9.0",
|
||||||
"@typescript-eslint/parser": "^3.6.1",
|
"@typescript-eslint/parser": "^3.9.0",
|
||||||
"autoprefixer": "^9.8.5",
|
"autoprefixer": "^9.8.6",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"babel-preset-minify": "^0.5.1",
|
"babel-preset-minify": "^0.5.1",
|
||||||
"css-loader": "^3.6.0",
|
"css-loader": "^4.2.1",
|
||||||
"eslint": "^7.4.0",
|
"eslint": "^7.6.0",
|
||||||
"eslint-config-standard": "^14.1.1",
|
"eslint-config-standard": "^14.1.1",
|
||||||
"eslint-loader": "^4.0.2",
|
"eslint-loader": "^4.0.2",
|
||||||
"eslint-plugin-import": "^2.22.0",
|
"eslint-plugin-import": "^2.22.0",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.20.3",
|
"eslint-plugin-react": "^7.20.5",
|
||||||
"eslint-plugin-standard": "^4.0.1",
|
"eslint-plugin-standard": "^4.0.1",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
"html-webpack-plugin": "^4.3.0",
|
"html-webpack-plugin": "^4.3.0",
|
||||||
"image-webpack-loader": "^6.0.0",
|
"image-webpack-loader": "^6.0.0",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.10.0",
|
||||||
"offline-plugin": "^5.0.7",
|
"offline-plugin": "^5.0.7",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"react-hot-loader": "^4.12.21",
|
"react-hot-loader": "^4.12.21",
|
||||||
"sass": "^1.26.10",
|
"sass": "^1.26.10",
|
||||||
"sass-loader": "^9.0.2",
|
"sass-loader": "^9.0.3",
|
||||||
"style-loader": "^1.2.1",
|
"style-loader": "^1.2.1",
|
||||||
"stylelint": "^13.6.1",
|
"stylelint": "^13.6.1",
|
||||||
"stylelint-config-standard": "^20.0.0",
|
"stylelint-config-standard": "^20.0.0",
|
||||||
"stylelint-webpack-plugin": "^2.1.0",
|
"stylelint-webpack-plugin": "^2.1.0",
|
||||||
"terser-webpack-plugin": "^3.0.7",
|
"terser-webpack-plugin": "^4.1.0",
|
||||||
|
"type-fest": "^0.16.0",
|
||||||
"typescript": "^3.9.7",
|
"typescript": "^3.9.7",
|
||||||
"webpack": "^4.43.0",
|
"webpack": "^4.44.1",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-dev-middleware": "^3.7.2",
|
"webpack-dev-middleware": "^3.7.2",
|
||||||
"webpack-dev-server": "^3.11.0",
|
"webpack-dev-server": "^3.11.0",
|
||||||
"webpack-merge": "^5.0.9",
|
"webpack-merge": "^5.1.1",
|
||||||
"webpack-pwa-manifest": "^4.2.0"
|
"webpack-pwa-manifest": "^4.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"dayjs": "^1.8.29",
|
"dayjs": "^1.8.33",
|
||||||
"eventemitter3": "^4.0.4",
|
"eventemitter3": "^4.0.4",
|
||||||
"immer": "^7.0.5",
|
"immer": "^7.0.7",
|
||||||
"lodash-es": "^4.17.15",
|
"lodash-es": "^4.17.15",
|
||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-table": "^7.3.0",
|
"react-table": "^7.5.0",
|
||||||
"react-virtualized-auto-sizer": "^1.0.2",
|
"react-virtualized-auto-sizer": "^1.0.2",
|
||||||
"react-window": "^1.8.5",
|
"react-window": "^1.8.5",
|
||||||
"recoil": "0.0.10",
|
"recoil": "0.0.10",
|
||||||
"swr": "^0.2.3",
|
"swr": "^0.3.0",
|
||||||
"use-immer": "^0.4.1"
|
"use-immer": "^0.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ export function ButtonSelect (props: ButtonSelectProps) {
|
|||||||
value={option.value}
|
value={option.value}
|
||||||
key={option.value}
|
key={option.value}
|
||||||
className={classnames('button-select-options', { actived: value === option.value })}
|
className={classnames('button-select-options', { actived: value === option.value })}
|
||||||
onClick={() => onSelect(option.value)}>
|
onClick={() => onSelect?.(option.value)}>
|
||||||
{ option.label }
|
{ option.label }
|
||||||
</button>
|
</button>
|
||||||
))
|
))
|
||||||
|
@ -52,11 +52,11 @@ export function Modal (props: ModalProps) {
|
|||||||
const { t } = useTranslation('Modal')
|
const { t } = useTranslation('Modal')
|
||||||
|
|
||||||
const portalRef = useRef<HTMLDivElement>(document.createElement('div'))
|
const portalRef = useRef<HTMLDivElement>(document.createElement('div'))
|
||||||
const maskRef = useRef<HTMLDivElement>()
|
const maskRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
document.body.appendChild(portalRef.current)
|
document.body.appendChild(portalRef.current)
|
||||||
return () => document.body.removeChild(portalRef.current)
|
return () => { document.body.removeChild(portalRef.current) }
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
function handleMaskClick (e: MouseEvent) {
|
function handleMaskClick (e: MouseEvent) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useRef, useLayoutEffect, useState, useMemo } from 'react'
|
import React, { useRef, useLayoutEffect, useState, useMemo, ReactElement } from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { Icon } from '@components'
|
import { Icon } from '@components'
|
||||||
import { BaseComponentProps } from '@models'
|
import { BaseComponentProps } from '@models'
|
||||||
@ -15,6 +15,8 @@ interface SelectProps extends BaseComponentProps {
|
|||||||
*/
|
*/
|
||||||
value: OptionValue
|
value: OptionValue
|
||||||
|
|
||||||
|
children?: ReactElement
|
||||||
|
|
||||||
onSelect?: (value: OptionValue, e: React.MouseEvent<HTMLLIElement>) => void
|
onSelect?: (value: OptionValue, e: React.MouseEvent<HTMLLIElement>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,8 +24,8 @@ export function Select (props: SelectProps) {
|
|||||||
const { value, onSelect, children, className: cn, style } = props
|
const { value, onSelect, children, className: cn, style } = props
|
||||||
|
|
||||||
const portalRef = useRef<HTMLDivElement>()
|
const portalRef = useRef<HTMLDivElement>()
|
||||||
const attachmentRef = useRef<HTMLDivElement>()
|
const attachmentRef = useRef<HTMLDivElement>(null)
|
||||||
const targetRef = useRef<HTMLDivElement>()
|
const targetRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const [showDropDownList, setShowDropDownList] = useState(false)
|
const [showDropDownList, setShowDropDownList] = useState(false)
|
||||||
const [hasCreateDropList, setHasCreateDropList] = useState(false)
|
const [hasCreateDropList, setHasCreateDropList] = useState(false)
|
||||||
@ -70,19 +72,19 @@ export function Select (props: SelectProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const matchChild = useMemo(() => {
|
const matchChild = useMemo(() => {
|
||||||
let matchChild: React.ReactElement<any> = null
|
let matchChild: React.ReactElement | null = null
|
||||||
|
|
||||||
React.Children.forEach(children, (child: React.ReactElement<any>) => {
|
React.Children.forEach(children, (child) => {
|
||||||
if (child.props && child.props.value === value) {
|
if (child?.props?.value === value) {
|
||||||
matchChild = child
|
matchChild = child
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return matchChild
|
return matchChild as React.ReactElement | null
|
||||||
}, [value, children])
|
}, [value, children])
|
||||||
|
|
||||||
const hookedChildren = useMemo(() => {
|
const hookedChildren = useMemo(() => {
|
||||||
return React.Children.map(children, (child: React.ReactElement<any>) => {
|
return React.Children.map(children ?? [], (child: React.ReactElement<any>) => {
|
||||||
if (!child.props || !child.type) {
|
if (!child.props || !child.type) {
|
||||||
return child
|
return child
|
||||||
}
|
}
|
||||||
@ -96,7 +98,7 @@ export function Select (props: SelectProps) {
|
|||||||
const rawOnClickEvent = child.props.onClick
|
const rawOnClickEvent = child.props.onClick
|
||||||
return React.cloneElement(child, Object.assign({}, child.props, {
|
return React.cloneElement(child, Object.assign({}, child.props, {
|
||||||
onClick: (e: React.MouseEvent<HTMLLIElement>) => {
|
onClick: (e: React.MouseEvent<HTMLLIElement>) => {
|
||||||
onSelect(child.props.value, e)
|
onSelect?.(child.props.value, e)
|
||||||
setShowDropDownList(false)
|
setShowDropDownList(false)
|
||||||
rawOnClickEvent && rawOnClickEvent(e)
|
rawOnClickEvent && rawOnClickEvent(e)
|
||||||
},
|
},
|
||||||
@ -125,10 +127,13 @@ export function Select (props: SelectProps) {
|
|||||||
ref={targetRef}
|
ref={targetRef}
|
||||||
onClick={handleShowDropList}
|
onClick={handleShowDropList}
|
||||||
>
|
>
|
||||||
{matchChild && matchChild.props && matchChild.props.children}
|
{matchChild?.props?.children}
|
||||||
<Icon type="triangle-down" />
|
<Icon type="triangle-down" />
|
||||||
</div>
|
</div>
|
||||||
{hasCreateDropList && createPortal(dropDownList, portalRef.current)}
|
{
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion,@typescript-eslint/no-non-null-asserted-optional-chain
|
||||||
|
hasCreateDropList && createPortal(dropDownList, portalRef?.current!)
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ export function Tags (props: TagsProps) {
|
|||||||
const [expand, setExpand] = useState(false)
|
const [expand, setExpand] = useState(false)
|
||||||
const [showExtend, setShowExtend] = useState(false)
|
const [showExtend, setShowExtend] = useState(false)
|
||||||
|
|
||||||
const ulRef = useRef<HTMLUListElement>()
|
const ulRef = useRef<HTMLUListElement>(null)
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setShowExtend(ulRef.current.offsetHeight > 30)
|
setShowExtend((ulRef?.current?.offsetHeight ?? 0) > 30)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const rowHeight = expand ? 'auto' : rawHeight
|
const rowHeight = expand ? 'auto' : rawHeight
|
||||||
|
@ -142,7 +142,7 @@ export default function Connections () {
|
|||||||
), [t])
|
), [t])
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const streamReader: StreamReader<API.Snapshot> = null
|
let streamReader: StreamReader<API.Snapshot> | null = null
|
||||||
|
|
||||||
function handleConnection (snapshots: API.Snapshot[]) {
|
function handleConnection (snapshots: API.Snapshot[]) {
|
||||||
for (const snapshot of snapshots) {
|
for (const snapshot of snapshots) {
|
||||||
@ -156,7 +156,7 @@ export default function Connections () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
const streamReader = await API.getConnectionStreamReader()
|
streamReader = await API.getConnectionStreamReader()
|
||||||
streamReader.subscribe('data', handleConnection)
|
streamReader.subscribe('data', handleConnection)
|
||||||
}())
|
}())
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ export default function Connections () {
|
|||||||
rows,
|
rows,
|
||||||
prepareRow
|
prepareRow
|
||||||
} = useTable(
|
} = useTable(
|
||||||
{ columns, data },
|
{ columns: columns as any, data },
|
||||||
useBlockLayout,
|
useBlockLayout,
|
||||||
useResizeColumns
|
useResizeColumns
|
||||||
)
|
)
|
||||||
|
@ -18,21 +18,26 @@ class Store {
|
|||||||
this.connections.delete(id)
|
this.connections.delete(id)
|
||||||
} else {
|
} else {
|
||||||
const connection = this.connections.get(id)
|
const connection = this.connections.get(id)
|
||||||
|
if (connection) {
|
||||||
connection.completed = true
|
connection.completed = true
|
||||||
connection.speed = { upload: 0, download: 0 }
|
connection.speed = { upload: 0, download: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const id of mapping.keys()) {
|
for (const id of mapping.keys()) {
|
||||||
if (!this.connections.has(id)) {
|
if (!this.connections.has(id)) {
|
||||||
this.connections.set(id, { ...mapping.get(id), speed: { upload: 0, download: 0 } })
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
this.connections.set(id, { ...mapping.get(id)!, speed: { upload: 0, download: 0 } })
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const c = this.connections.get(id)
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const n = mapping.get(id)
|
const c = this.connections.get(id)!
|
||||||
this.connections.set(id, { ...n, speed: { upload: n.upload - c.upload, download: n.download - c.download } })
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const n = mapping.get(id)!
|
||||||
|
this.connections?.set(id, { ...n, speed: { upload: n.upload - c.upload, download: n.download - c.download } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +45,7 @@ class Store {
|
|||||||
if (this.saveDisconnection) {
|
if (this.saveDisconnection) {
|
||||||
this.saveDisconnection = false
|
this.saveDisconnection = false
|
||||||
for (const id of this.connections.keys()) {
|
for (const id of this.connections.keys()) {
|
||||||
if (this.connections.get(id).completed) {
|
if (this.connections?.get(id)?.completed) {
|
||||||
this.connections.delete(id)
|
this.connections.delete(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { Log } from '@models/Log'
|
|||||||
import './style.scss'
|
import './style.scss'
|
||||||
|
|
||||||
export default function Logs () {
|
export default function Logs () {
|
||||||
const listRef = useRef<HTMLUListElement>()
|
const listRef = useRef<HTMLUListElement>(null)
|
||||||
const logsRef = useRef<Log[]>([])
|
const logsRef = useRef<Log[]>([])
|
||||||
const [logs, setLogs] = useState<Log[]>([])
|
const [logs, setLogs] = useState<Log[]>([])
|
||||||
const { useTranslation } = useI18n()
|
const { useTranslation } = useI18n()
|
||||||
@ -16,11 +16,13 @@ export default function Logs () {
|
|||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const ul = listRef.current
|
const ul = listRef.current
|
||||||
|
if (ul) {
|
||||||
ul.scrollTop = ul.scrollHeight
|
ul.scrollTop = ul.scrollHeight
|
||||||
|
}
|
||||||
}, [logsRef.current])
|
}, [logsRef.current])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const streamReader: StreamReader<Log> = null
|
let streamReader: StreamReader<Log> | null = null
|
||||||
|
|
||||||
function handleLog (newLogs: Log[]) {
|
function handleLog (newLogs: Log[]) {
|
||||||
logsRef.current = logsRef.current.slice().concat(newLogs.map(d => ({ ...d, time: new Date() })))
|
logsRef.current = logsRef.current.slice().concat(newLogs.map(d => ({ ...d, time: new Date() })))
|
||||||
@ -28,13 +30,13 @@ export default function Logs () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(async function () {
|
(async function () {
|
||||||
const streamReader = await getLogsStreamReader()
|
streamReader = await getLogsStreamReader()
|
||||||
logsRef.current = streamReader.buffer()
|
logsRef.current = streamReader.buffer()
|
||||||
setLogs(logsRef.current)
|
setLogs(logsRef.current)
|
||||||
streamReader.subscribe('data', handleLog)
|
streamReader.subscribe('data', handleLog)
|
||||||
}())
|
}())
|
||||||
|
|
||||||
return () => streamReader && streamReader.unsubscribe('data', handleLog)
|
return () => streamReader?.unsubscribe('data', handleLog)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -21,7 +21,7 @@ const TagColors = {
|
|||||||
|
|
||||||
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) ?? 0
|
||||||
return delay
|
return delay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ export default function Settings () {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
set('socks5ProxyPort', general.socksPort)
|
set('socks5ProxyPort', general?.socksPort ?? 0)
|
||||||
set('httpProxyPort', general.port)
|
set('httpProxyPort', general?.port ?? 0)
|
||||||
set('mixedProxyPort', general.mixedPort ?? 0)
|
set('mixedProxyPort', general?.mixedPort ?? 0)
|
||||||
}, [general])
|
}, [general])
|
||||||
|
|
||||||
async function handleProxyModeChange (mode: string) {
|
async function handleProxyModeChange (mode: string) {
|
||||||
@ -42,12 +42,12 @@ export default function Settings () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function handleStartAtLoginChange (state: boolean) {
|
async function handleStartAtLoginChange (state: boolean) {
|
||||||
await jsBridge.setStartAtLogin(state)
|
await jsBridge?.setStartAtLogin(state)
|
||||||
fetchClashXData()
|
fetchClashXData()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSetSystemProxy (state: boolean) {
|
async function handleSetSystemProxy (state: boolean) {
|
||||||
await jsBridge.setSystemProxy(state)
|
await jsBridge?.setSystemProxy(state)
|
||||||
fetchClashXData()
|
fetchClashXData()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ export default function Settings () {
|
|||||||
<span className="label">{t('labels.language')}</span>
|
<span className="label">{t('labels.language')}</span>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={14} className="value-column">
|
<Col span={14} className="value-column">
|
||||||
<ButtonSelect options={languageOptions} value={lang} onSelect={changeLanguage} />
|
<ButtonSelect options={languageOptions} value={lang} onSelect={(lang) => changeLanguage(lang as Lang)} />
|
||||||
</Col>
|
</Col>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -20,9 +20,9 @@ export function noop () {}
|
|||||||
export async function to <T, E = Error> (promise: Promise<T>): Promise<[T, E]> {
|
export async function to <T, E = Error> (promise: Promise<T>): Promise<[T, E]> {
|
||||||
try {
|
try {
|
||||||
const ret = await promise
|
const ret = await promise
|
||||||
return [ret, null as E]
|
return [ret, null as unknown as E]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return [null as T, e]
|
return [null as unknown as T, e]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Draft } from 'immer'
|
import { Draft } from 'immer'
|
||||||
import { useImmer } from 'use-immer'
|
import { useImmer } from 'use-immer'
|
||||||
import { useRef, useEffect, useState, useMemo } from 'react'
|
import { useRef, useEffect, useState, useMemo, useCallback } from 'react'
|
||||||
|
|
||||||
import { noop } from '@lib/helper'
|
import { noop } from '@lib/helper'
|
||||||
|
|
||||||
@ -15,7 +15,8 @@ export function useObject<T extends Record<string, unknown>> (initialValue: T) {
|
|||||||
rawSet(draft => {
|
rawSet(draft => {
|
||||||
const key = data as K
|
const key = data as K
|
||||||
const v = value
|
const v = value
|
||||||
draft[key] = v
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
draft[key] = v!
|
||||||
})
|
})
|
||||||
} else if (typeof data === 'function') {
|
} else if (typeof data === 'function') {
|
||||||
rawSet(data)
|
rawSet(data)
|
||||||
@ -30,7 +31,7 @@ export function useObject<T extends Record<string, unknown>> (initialValue: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [copy, set] as [T, typeof set]
|
return [copy, useCallback(set, [rawSet])] as [T, typeof set]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useInterval (callback: () => void, delay: number) {
|
export function useInterval (callback: () => void, delay: number) {
|
||||||
|
@ -52,7 +52,7 @@ declare global {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type JsBridgeCallback = (jsbridge: JsBridgeAPI) => void
|
type JsBridgeCallback = (jsbridge: JsBridgeAPI | null) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if perched in ClashX Runtime
|
* Check if perched in ClashX Runtime
|
||||||
@ -64,13 +64,13 @@ export function isClashX () {
|
|||||||
/**
|
/**
|
||||||
* Closure save jsbridge instance
|
* Closure save jsbridge instance
|
||||||
*/
|
*/
|
||||||
export let jsBridge: JsBridge = null
|
export let jsBridge: JsBridge | null = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JsBridge class
|
* JsBridge class
|
||||||
*/
|
*/
|
||||||
export class JsBridge {
|
export class JsBridge {
|
||||||
instance: JsBridgeAPI = null
|
instance: JsBridgeAPI | null = null
|
||||||
|
|
||||||
constructor (callback: JsBridgeCallback) {
|
constructor (callback: JsBridgeCallback) {
|
||||||
if (window.WebViewJavascriptBridge) {
|
if (window.WebViewJavascriptBridge) {
|
||||||
@ -95,7 +95,7 @@ export class JsBridge {
|
|||||||
* You need check if inClashX first
|
* You need check if inClashX first
|
||||||
*/
|
*/
|
||||||
if (!isClashX()) {
|
if (!isClashX()) {
|
||||||
return callback(null)
|
return callback?.(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.WebViewJavascriptBridge) {
|
if (window.WebViewJavascriptBridge) {
|
||||||
@ -118,7 +118,7 @@ export class JsBridge {
|
|||||||
|
|
||||||
public callHandler<T> (handleName: string, data?: any) {
|
public callHandler<T> (handleName: string, data?: any) {
|
||||||
return new Promise<T>((resolve) => {
|
return new Promise<T>((resolve) => {
|
||||||
this.instance.callHandler(
|
this.instance?.callHandler(
|
||||||
handleName,
|
handleName,
|
||||||
data,
|
data,
|
||||||
resolve
|
resolve
|
||||||
|
@ -13,7 +13,8 @@ export function useRecoilObjectWithImmer<T> (value: RecoilState<T>) {
|
|||||||
rawSet(pre => produce(pre, (draft: Draft<T>) => {
|
rawSet(pre => produce(pre, (draft: Draft<T>) => {
|
||||||
const key = data as K
|
const key = data as K
|
||||||
const v = value
|
const v = value
|
||||||
draft[key] = v
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
draft[key] = v!
|
||||||
}))
|
}))
|
||||||
} else if (typeof data === 'function') {
|
} else if (typeof data === 'function') {
|
||||||
const fn = data as (draft: Draft<T>) => void | T
|
const fn = data as (draft: Draft<T>) => void | T
|
||||||
|
@ -100,7 +100,8 @@ export interface Connections {
|
|||||||
|
|
||||||
export async function getExternalControllerConfig () {
|
export async function getExternalControllerConfig () {
|
||||||
if (isClashX()) {
|
if (isClashX()) {
|
||||||
const info = await jsBridge.getAPIInfo()
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const info = await jsBridge!.getAPIInfo()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: info.host,
|
hostname: info.host,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { to } from '@lib/helper'
|
|
||||||
import EventEmitter from 'eventemitter3'
|
import EventEmitter from 'eventemitter3'
|
||||||
|
import { SetRequired } from 'type-fest'
|
||||||
|
import { to } from '@lib/helper'
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
url: string
|
url: string
|
||||||
@ -11,7 +12,7 @@ export interface Config {
|
|||||||
|
|
||||||
export class StreamReader<T> {
|
export class StreamReader<T> {
|
||||||
protected EE = new EventEmitter()
|
protected EE = new EventEmitter()
|
||||||
protected config: Config
|
protected config: SetRequired<Config, 'bufferLength' | 'retryInterval'>
|
||||||
protected innerBuffer: T[] = []
|
protected innerBuffer: T[] = []
|
||||||
protected isClose = false
|
protected isClose = false
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ export class StreamReader<T> {
|
|||||||
protected websocketLoop () {
|
protected websocketLoop () {
|
||||||
const url = new URL(this.config.url)
|
const url = new URL(this.config.url)
|
||||||
url.protocol = location.protocol === 'http:' ? 'ws:' : 'wss:'
|
url.protocol = location.protocol === 'http:' ? 'ws:' : 'wss:'
|
||||||
url.searchParams.set('token', this.config.token)
|
url.searchParams.set('token', this.config.token ?? '')
|
||||||
|
|
||||||
const connection = new WebSocket(url.toString())
|
const connection = new WebSocket(url.toString())
|
||||||
connection.addEventListener('message', msg => {
|
connection.addEventListener('message', msg => {
|
||||||
@ -62,7 +63,7 @@ export class StreamReader<T> {
|
|||||||
headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}
|
headers: this.config.token ? { Authorization: `Bearer ${this.config.token}` } : {}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
if (err) {
|
if (err || !resp.body) {
|
||||||
this.retry(err)
|
this.retry(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -74,7 +75,7 @@ export class StreamReader<T> {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const [{ value }, err] = await to(reader.read())
|
const [{ value }, err] = await to(reader?.read())
|
||||||
if (err) {
|
if (err) {
|
||||||
this.retry(err)
|
this.retry(err)
|
||||||
break
|
break
|
||||||
@ -83,7 +84,8 @@ export class StreamReader<T> {
|
|||||||
const lines = decoder.decode(value).trim().split('\n')
|
const lines = decoder.decode(value).trim().split('\n')
|
||||||
const data = lines.map(l => JSON.parse(l))
|
const data = lines.map(l => JSON.parse(l))
|
||||||
this.EE.emit('data', data)
|
this.EE.emit('data', data)
|
||||||
if (this.config.bufferLength > 0) {
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
if (this.config.bufferLength! > 0) {
|
||||||
this.innerBuffer.push(...data)
|
this.innerBuffer.push(...data)
|
||||||
if (this.innerBuffer.length > this.config.bufferLength) {
|
if (this.innerBuffer.length > this.config.bufferLength) {
|
||||||
this.innerBuffer.splice(0, this.innerBuffer.length - this.config.bufferLength)
|
this.innerBuffer.splice(0, this.innerBuffer.length - this.config.bufferLength)
|
||||||
|
@ -67,7 +67,7 @@ export interface Config {
|
|||||||
export interface Data {
|
export interface Data {
|
||||||
version?: string
|
version?: string
|
||||||
|
|
||||||
general?: {
|
general: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http proxy port
|
* http proxy port
|
||||||
@ -92,12 +92,12 @@ export interface Data {
|
|||||||
/**
|
/**
|
||||||
* proxy is allow lan
|
* proxy is allow lan
|
||||||
*/
|
*/
|
||||||
allowLan?: boolean
|
allowLan: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clash proxy mode
|
* clash proxy mode
|
||||||
*/
|
*/
|
||||||
mode?: 'script' | 'rule' | 'direct' | 'global'
|
mode: 'script' | 'rule' | 'direct' | 'global'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clash tty log level
|
* clash tty log level
|
||||||
|
@ -249,8 +249,8 @@ export function useClashXData () {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const startAtLogin = await jsBridge.getStartAtLogin()
|
const startAtLogin = await jsBridge?.getStartAtLogin() ?? false
|
||||||
const systemProxy = await jsBridge.isSystemProxySet()
|
const systemProxy = await jsBridge?.isSystemProxySet() ?? false
|
||||||
|
|
||||||
set({ startAtLogin, systemProxy, isClashX: true })
|
set({ startAtLogin, systemProxy, isClashX: true })
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
"strict": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user