chore: add strict: true to tsconfig

This commit is contained in:
Dreamacro 2020-08-11 12:14:48 +08:00
parent e1a8b559d1
commit 6265c5adb1
20 changed files with 736 additions and 513 deletions

1068
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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"
} }
} }

View File

@ -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>
)) ))

View File

@ -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) {

View File

@ -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!)
}
</> </>
) )
} }

View File

@ -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

View File

@ -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
) )

View File

@ -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)
} }
} }

View File

@ -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 (

View File

@ -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
} }

View File

@ -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>

View File

@ -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]
} }
} }

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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 })
} }

View File

@ -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",