optimized rule page performance

This commit is contained in:
pompurin404 2024-09-01 16:00:31 +08:00
parent 704a322c25
commit 449597f941
No known key found for this signature in database
11 changed files with 115 additions and 26 deletions

View File

@ -2,10 +2,6 @@
- 1.2.x YAML覆写语法有所变动请更新后参考文档进行修改
### New Features
### Performance Improvements
- 支持使用外部编辑器打开文件
- 支持新建订阅/覆写
- 添加窗口置顶按钮
- 允许禁用系统标题栏
- 重写连接页面
- 优化规则/代理页面性能

View File

@ -8,17 +8,22 @@ import {
} from '../config'
import { mihomoWorkConfigPath, overridePath } from '../utils/dirs'
import yaml from 'yaml'
import { readFile, writeFile } from 'fs/promises'
import { writeFile } from 'fs/promises'
import { deepMerge } from '../utils/merge'
import vm from 'vm'
import { writeFileSync } from 'fs'
let runtimeConfigStr: string
let runtimeConfig: IMihomoConfig
export async function generateProfile(): Promise<void> {
const { current } = await getProfileConfig()
const currentProfile = await overrideProfile(current, await getProfile(current))
const controledMihomoConfig = await getControledMihomoConfig()
const profile = deepMerge(currentProfile, controledMihomoConfig)
await writeFile(mihomoWorkConfigPath(), yaml.stringify(profile))
runtimeConfig = profile
runtimeConfigStr = yaml.stringify(profile)
await writeFile(mihomoWorkConfigPath(), runtimeConfigStr)
}
async function overrideProfile(
@ -87,9 +92,9 @@ function runOverrideScript(
}
export async function getRuntimeConfigStr(): Promise<string> {
return await readFile(mihomoWorkConfigPath(), 'utf8')
return runtimeConfigStr
}
export async function getRuntimeConfig(): Promise<IMihomoConfig> {
return yaml.parse(await getRuntimeConfigStr())
return runtimeConfig
}

View File

@ -60,6 +60,7 @@ export async function startCore(): Promise<void> {
}
if (data.toString().includes('RESTful API listening at')) {
await startMihomoTraffic()
mainWindow?.webContents.send('coreRestart')
retry = 10
resolve()
}

View File

@ -71,8 +71,11 @@ export const mihomoRules = async (): Promise<IMihomoRulesInfo> => {
export const mihomoProxies = async (): Promise<IMihomoProxies> => {
const instance = await getAxios()
return await instance.get('/proxies')
const proxies = (await instance.get('/proxies')) as IMihomoProxies
if (!proxies.proxies['GLOBAL']) {
throw new Error('GLOBAL proxy not found')
}
return proxies
}
export const mihomoGroups = async (): Promise<IMihomoMixedGroup[]> => {

View File

@ -3,14 +3,13 @@ import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { LuGroup } from 'react-icons/lu'
import { useLocation, useNavigate } from 'react-router-dom'
import useSWR from 'swr'
import { mihomoGroups } from '@renderer/utils/ipc'
import { useGroups } from '@renderer/hooks/use-groups'
const ProxyCard: React.FC = () => {
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/proxies')
const { data: groups = [] } = useSWR('mihomoGroups', mihomoGroups)
const { groups = [] } = useGroups()
const {
attributes,
listeners,

View File

@ -1,16 +1,15 @@
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
import { mihomoRules } from '@renderer/utils/ipc'
import { MdOutlineAltRoute } from 'react-icons/md'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import useSWR from 'swr'
import { useRules } from '@renderer/hooks/use-rules'
const RuleCard: React.FC = () => {
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/rules')
const { data: rules } = useSWR<IMihomoRulesInfo>('mihomoRules', mihomoRules)
const { rules } = useRules()
const {
attributes,
listeners,

View File

@ -0,0 +1,36 @@
import React, { createContext, useContext, ReactNode } from 'react'
import useSWR from 'swr'
import { mihomoGroups } from '@renderer/utils/ipc'
interface GroupsContextType {
groups: IMihomoMixedGroup[] | undefined
mutate: () => void
}
const GroupsContext = createContext<GroupsContextType | undefined>(undefined)
export const GroupsProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { data: groups, mutate } = useSWR<IMihomoMixedGroup[]>('mihomoGroups', mihomoGroups, {
errorRetryInterval: 200,
errorRetryCount: 10
})
React.useEffect(() => {
window.electron.ipcRenderer.on('coreRestart', () => {
mutate()
})
return (): void => {
window.electron.ipcRenderer.removeAllListeners('coreRestart')
}
}, [])
return <GroupsContext.Provider value={{ groups, mutate }}>{children}</GroupsContext.Provider>
}
export const useGroups = (): GroupsContextType => {
const context = useContext(GroupsContext)
if (context === undefined) {
throw new Error('useGroups must be used within an GroupsProvider')
}
return context
}

View File

@ -0,0 +1,47 @@
import React, { createContext, useContext, ReactNode } from 'react'
import useSWR from 'swr'
import { mihomoRules } from '@renderer/utils/ipc'
interface RulesContextType {
rules: IMihomoRulesInfo | undefined
mutate: () => void
}
const RulesContext = createContext<RulesContextType | undefined>(undefined)
let emptyRetry = 10
export const RulesProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { data: rules, mutate } = useSWR<IMihomoRulesInfo>('mihomoRules', mihomoRules, {
errorRetryInterval: 200,
errorRetryCount: 10,
onSuccess: (data) => {
if (data.rules.length === 0 && emptyRetry) {
emptyRetry--
setTimeout(() => {
mutate()
}, 200)
} else {
emptyRetry = 10
}
}
})
React.useEffect(() => {
window.electron.ipcRenderer.on('coreRestart', () => {
mutate()
})
return (): void => {
window.electron.ipcRenderer.removeAllListeners('coreRestart')
}
}, [])
return <RulesContext.Provider value={{ rules, mutate }}>{children}</RulesContext.Provider>
}
export const useRules = (): RulesContextType => {
const context = useContext(RulesContext)
if (context === undefined) {
throw new Error('useRules must be used within an RulesProvider')
}
return context
}

View File

@ -12,6 +12,8 @@ import { AppConfigProvider } from './hooks/use-app-config'
import { ControledMihomoConfigProvider } from './hooks/use-controled-mihomo-config'
import { OverrideConfigProvider } from './hooks/use-override-config'
import { ProfileConfigProvider } from './hooks/use-profile-config'
import { RulesProvider } from './hooks/use-rules'
import { GroupsProvider } from './hooks/use-groups'
init().then(() => {
document.addEventListener('keydown', (e) => {
@ -53,7 +55,11 @@ init().then(() => {
<ControledMihomoConfigProvider>
<ProfileConfigProvider>
<OverrideConfigProvider>
<GroupsProvider>
<RulesProvider>
<App />
</RulesProvider>
</GroupsProvider>
</OverrideConfigProvider>
</ProfileConfigProvider>
</ControledMihomoConfigProvider>

View File

@ -5,7 +5,6 @@ import {
mihomoChangeProxy,
mihomoCloseAllConnections,
mihomoGroupDelay,
mihomoGroups,
mihomoProxyDelay
} from '@renderer/utils/ipc'
import { CgDetailsLess, CgDetailsMore } from 'react-icons/cg'
@ -14,14 +13,14 @@ import { TbCircleLetterD } from 'react-icons/tb'
import { FaLocationCrosshairs } from 'react-icons/fa6'
import { RxLetterCaseCapitalize } from 'react-icons/rx'
import { useEffect, useMemo, useRef, useState } from 'react'
import useSWR from 'swr'
import { GroupedVirtuoso, GroupedVirtuosoHandle } from 'react-virtuoso'
import ProxyItem from '@renderer/components/proxies/proxy-item'
import { IoIosArrowBack } from 'react-icons/io'
import { MdOutlineSpeed } from 'react-icons/md'
import { useGroups } from '@renderer/hooks/use-groups'
const Proxies: React.FC = () => {
const { data: groups = [], mutate } = useSWR('mihomoGroups', mihomoGroups)
const { groups = [], mutate } = useGroups()
const { appConfig, patchAppConfig } = useAppConfig()
const {
proxyDisplayMode = 'simple',
@ -190,7 +189,6 @@ const Proxies: React.FC = () => {
canvas.height = img.height
ctx?.drawImage(img, 0, 0)
const data = canvas.toDataURL('image/png')
console.log('set')
localStorage.setItem(groups[index].icon, data)
}
img.src = groups[index].icon

View File

@ -3,11 +3,10 @@ import RuleItem from '@renderer/components/rules/rule-item'
import { Virtuoso } from 'react-virtuoso'
import { useMemo, useState } from 'react'
import { Divider, Input } from '@nextui-org/react'
import useSWR from 'swr'
import { mihomoRules } from '@renderer/utils/ipc'
import { useRules } from '@renderer/hooks/use-rules'
const Rules: React.FC = () => {
const { data: rules } = useSWR<IMihomoRulesInfo>('mihomoRules', mihomoRules)
const { rules } = useRules()
const [filter, setFilter] = useState('')
const filteredRules = useMemo(() => {