Skip to content

Commit

Permalink
optimize proxy list performance
Browse files Browse the repository at this point in the history
  • Loading branch information
pompurin404 committed Aug 4, 2024
1 parent c2e1d67 commit 67f38bc
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 125 deletions.
2 changes: 2 additions & 0 deletions src/renderer/src/components/base/base-page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Divider } from '@nextui-org/react'
import React from 'react'
interface Props {
title?: React.ReactNode
Expand All @@ -14,6 +15,7 @@ const BasePage: React.FC<Props> = (props) => {
<div className="select-none title h-full text-lg leading-[32px]">{props.title}</div>
<div className="header h-full">{props.header}</div>
</div>
<Divider />
</div>
<div className="content">{props.children}</div>
</div>
Expand Down
61 changes: 29 additions & 32 deletions src/renderer/src/components/proxies/proxy-item.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Button, Card, CardBody, Divider } from '@nextui-org/react'
import { Button, Card, CardBody } from '@nextui-org/react'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import PubSub from 'pubsub-js'
import React, { useEffect, useState } from 'react'

interface Props {
onProxyDelay: (proxy: string) => Promise<IMihomoDelay>
onProxyDelay: (proxy: string, url?: string) => Promise<IMihomoDelay>
proxyDisplayMode: 'simple' | 'full'
proxy: IMihomoProxy | IMihomoGroup
group: string
onSelect: (proxy: string) => void
onSelect: (group: string, proxy: string) => void
selected: boolean
}

Expand Down Expand Up @@ -61,36 +61,33 @@ const ProxyItem: React.FC<Props> = (props) => {
}
}, [])
return (
<>
<Divider />
<Card
onPress={() => onSelect(proxy.name)}
isPressable
fullWidth
className={`my-1 ${selected ? 'bg-primary/30' : ''}`}
radius="sm"
>
<CardBody className="p-1">
<div className="flex justify-between items-center">
<div>
<div className="inline">{proxy.name}</div>
{proxyDisplayMode === 'full' && (
<div className="inline ml-2 text-default-500">{proxy.type}</div>
)}
</div>
<Button
isLoading={loading}
color={delayColor(delay)}
onPress={onDelay}
variant="light"
className="h-full min-w-[50px] p-0 mx-2 text-sm hover:bg-content"
>
{delayText(delay)}
</Button>
<Card
onPress={() => onSelect(group, proxy.name)}
isPressable
fullWidth
className={`${selected ? 'bg-primary/30' : ''}`}
radius="sm"
>
<CardBody className="p-1">
<div className="flex justify-between items-center">
<div>
<div className="inline">{proxy.name}</div>
{proxyDisplayMode === 'full' && (
<div className="inline ml-2 text-default-500">{proxy.type}</div>
)}
</div>
</CardBody>
</Card>
</>
<Button
isLoading={loading}
color={delayColor(delay)}
onPress={onDelay}
variant="light"
className="h-full min-w-[50px] p-0 mx-2 text-sm hover:bg-content"
>
{delayText(delay)}
</Button>
</div>
</CardBody>
</Card>
)
}

Expand Down
36 changes: 0 additions & 36 deletions src/renderer/src/components/proxies/proxy-list.tsx

This file was deleted.

152 changes: 95 additions & 57 deletions src/renderer/src/pages/proxies.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Accordion, AccordionItem, Avatar, Button } from '@nextui-org/react'
import { Avatar, Button, Card, CardBody } from '@nextui-org/react'
import BasePage from '@renderer/components/base/base-page'
import ProxyList from '@renderer/components/proxies/proxy-list'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { MdOutlineSpeed } from 'react-icons/md'
import { mihomoChangeProxy, mihomoProxies, mihomoProxyDelay } from '@renderer/utils/ipc'
import { CgDetailsLess, CgDetailsMore } from 'react-icons/cg'
import { useEffect, useMemo } from 'react'
import PubSub from 'pubsub-js'
import { useMemo, useState } from 'react'
import useSWR from 'swr'
import { GroupedVirtuoso } from 'react-virtuoso'
import ProxyItem from '@renderer/components/proxies/proxy-item'
import { IoIosArrowBack } from 'react-icons/io'
import { MdOutlineSpeed } from 'react-icons/md'

const Proxies: React.FC = () => {
const { data: proxies, mutate } = useSWR('mihomoProxies', mihomoProxies)
Expand All @@ -34,15 +35,21 @@ const Proxies: React.FC = () => {
return groups
}, [proxies])

const groupProxies = useMemo(() => {
const groupProxies: Record<string, (IMihomoProxy | IMihomoGroup)[]> = {}
if (proxies) {
for (const group of groups) {
groupProxies[group.name] = group.all.map((name) => proxies.proxies[name])
const [isOpen, setIsOpen] = useState(Array(groups.length).fill(false))

const { groupCounts, allProxies } = useMemo(() => {
const groupCounts = groups.map((group, index) => {
return isOpen[index] ? group.all.length : 0
})
const allProxies: (IMihomoProxy | IMihomoGroup)[] = []
groups.forEach((group, index) => {
if (isOpen[index] && proxies) {
allProxies.push(...group.all.map((name) => proxies.proxies[name]))
}
}
return groupProxies
}, [proxies])
})

return { groupCounts, allProxies }
}, [groups, isOpen])

const onChangeProxy = (group: string, proxy: string): void => {
mihomoChangeProxy(group, proxy).then(() => {
Expand All @@ -54,7 +61,6 @@ const Proxies: React.FC = () => {
return await mihomoProxyDelay(proxy, url)
}

useEffect(() => {}, [])
return (
<BasePage
title="代理组"
Expand All @@ -74,54 +80,86 @@ const Proxies: React.FC = () => {
</Button>
}
>
<Accordion variant="splitted" className="p-2">
{groups.map((group) => {
<GroupedVirtuoso
style={{ height: 'calc(100vh - 50px)' }}
groupCounts={groupCounts}
groupContent={(index) => {
return (
<AccordionItem
textValue={group.name}
key={group.name}
title={
<div className="flex justify-between">
<div className="">
<div className="inline">{group.name}</div>
{proxyDisplayMode === 'full' && (
<>
<div className="inline ml-2 text-sm text-default-500">{group.type}</div>
<div className="inline ml-2 text-sm text-default-500">{group.now}</div>
</>
)}
<div className={`w-full pt-2 ${index === groupCounts.length - 1 ? 'pb-2' : ''} px-2`}>
<Card
isPressable
fullWidth
onPress={() => {
setIsOpen((prev) => {
const newOpen = [...prev]
newOpen[index] = !prev[index]
return newOpen
})
}}
>
<CardBody>
<div className="flex justify-between">
<div className="flex">
{groups[index].icon.length > 0 ? (
<Avatar
className="bg-transparent mr-2"
size="sm"
radius="sm"
src={groups[index].icon}
/>
) : null}
<div className="h-[32px] text-md leading-[32px]">
{groups[index].name}
{proxyDisplayMode === 'full' && (
<>
<div className="inline ml-2 text-sm text-default-500">
{groups[index].type}
</div>
<div className="inline ml-2 text-sm text-default-500">
{groups[index].now}
</div>
</>
)}
</div>
</div>
<div className="flex">
<Button
variant="light"
size="sm"
isIconOnly
onPress={() => {
PubSub.publish(`${groups[index].name}-delay`)
}}
>
<MdOutlineSpeed className="text-lg text-default-500" />
</Button>
<IoIosArrowBack
className={`transition duration-200 ml-2 h-[32px] text-lg text-default-500 ${isOpen[index] ? '-rotate-90' : ''}`}
/>
</div>
</div>
<Button
variant="light"
size="sm"
isIconOnly
onPress={() => {
PubSub.publish(`${group.name}-delay`)
}}
>
<MdOutlineSpeed className="text-lg text-default-500" />
</Button>
</div>
}
classNames={{ title: 'select-none', base: 'px-2', content: 'pt-2', trigger: 'py-2' }}
startContent={
group.icon.length > 0 ? (
<Avatar className="bg-transparent" size="sm" radius="sm" src={group.icon} />
) : null
}
>
<ProxyList
onProxyDelay={(proxy) => onProxyDelay(proxy, group.testUrl)}
onChangeProxy={(proxy) => onChangeProxy(group.name, proxy)}
</CardBody>
</Card>
</div>
)
}}
itemContent={(index, groupIndex) => {
return allProxies[index] ? (
<div className="pt-2 mx-2">
<ProxyItem
onProxyDelay={onProxyDelay}
onSelect={onChangeProxy}
proxy={allProxies[index]}
group={groups[groupIndex].name}
proxyDisplayMode={proxyDisplayMode}
proxies={groupProxies[group.name]}
group={group.name}
now={group.now}
selected={allProxies[index]?.name === groups[groupIndex].now}
/>
</AccordionItem>
</div>
) : (
<div>Never See This</div>
)
})}
</Accordion>
}}
/>
</BasePage>
)
}
Expand Down

0 comments on commit 67f38bc

Please sign in to comment.