support narrow sidebar style

This commit is contained in:
pompurin404 2024-10-19 12:13:20 +08:00
parent a5f825d5ca
commit f193dbe696
No known key found for this signature in database
14 changed files with 464 additions and 80 deletions

View File

@ -37,6 +37,7 @@ import { driver } from 'driver.js'
import 'driver.js/dist/driver.css'
let navigate: NavigateFunction
const narrowWidth = platform === 'darwin' ? 70 : 60
const App: React.FC = () => {
const { appConfig, patchAppConfig } = useAppConfig()
@ -142,19 +143,19 @@ const App: React.FC = () => {
}
const componentMap = {
sysproxy: <SysproxySwitcher key="sysproxy" />,
tun: <TunSwitcher key="tun" />,
profile: <ProfileCard key="profile" />,
proxy: <ProxyCard key="proxy" />,
mihomo: <MihomoCoreCard key="mihomo" />,
connection: <ConnCard key="connection" />,
dns: <DNSCard key="dns" />,
sniff: <SniffCard key="sniff" />,
log: <LogCard key="log" />,
rule: <RuleCard key="rule" />,
resource: <ResourceCard key="resource" />,
override: <OverrideCard key="override" />,
substore: <SubStoreCard key="substore" />
sysproxy: SysproxySwitcher,
tun: TunSwitcher,
profile: ProfileCard,
proxy: ProxyCard,
mihomo: MihomoCoreCard,
connection: ConnCard,
dns: DNSCard,
sniff: SniffCard,
log: LogCard,
rule: RuleCard,
resource: ResourceCard,
override: OverrideCard,
substore: SubStoreCard
}
return (
@ -167,7 +168,9 @@ const App: React.FC = () => {
}}
onMouseMove={(e) => {
if (!resizing) return
if (e.clientX <= 250) {
if (e.clientX <= 150) {
setSiderWidthValue(narrowWidth)
} else if (e.clientX <= 250) {
setSiderWidthValue(250)
} else if (e.clientX >= 400) {
setSiderWidthValue(400)
@ -177,6 +180,38 @@ const App: React.FC = () => {
}}
className={`w-full h-[100vh] flex ${resizing ? 'cursor-ew-resize' : ''}`}
>
{siderWidthValue === narrowWidth ? (
<div style={{ width: `${narrowWidth}px` }} className="side h-full">
<div className="app-drag flex justify-center items-center z-40 bg-transparent h-[49px]">
{platform !== 'darwin' && (
<MihomoIcon className="h-[32px] leading-[32px] text-lg mx-[1px]" />
)}
</div>
<div className="h-[calc(100%-110px)] overflow-y-auto no-scrollbar">
<div className="h-full w-full flex flex-col gap-2">
{order.map((key: string) => {
const Component = componentMap[key]
if (!Component) return null
return <Component key={key} iconOnly={true} />
})}
</div>
</div>
<div className="mt-2 flex justify-center items-center h-[48px]">
<Button
size="sm"
className="app-nodrag"
isIconOnly
color={location.pathname.includes('/settings') ? 'primary' : 'default'}
variant={location.pathname.includes('/settings') ? 'solid' : 'light'}
onPress={() => {
navigate('/settings')
}}
>
<IoSettings className="text-[20px]" />
</Button>
</div>
</div>
) : (
<div
style={{ width: `${siderWidthValue}px` }}
className="side h-full overflow-y-auto no-scrollbar"
@ -199,8 +234,9 @@ const App: React.FC = () => {
onPress={() => {
navigate('/settings')
}}
startContent={<IoSettings className="text-[20px]" />}
/>
>
<IoSettings className="text-[20px]" />
</Button>
</div>
</div>
<div className="mt-2 mx-2">
@ -210,12 +246,16 @@ const App: React.FC = () => {
<div className="grid grid-cols-2 gap-2 m-2">
<SortableContext items={order}>
{order.map((key: string) => {
return componentMap[key]
const Component = componentMap[key]
if (!Component) return null
return <Component key={key} />
})}
</SortableContext>
</div>
</DndContext>
</div>
)}
<div
onMouseDown={() => {
setResizing(true)

View File

@ -1,8 +1,8 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { FaCircleArrowDown, FaCircleArrowUp } from 'react-icons/fa6'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { calcTraffic } from '@renderer/utils/calc'
import { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { IoLink } from 'react-icons/io5'
@ -16,11 +16,16 @@ let currentDownload: number | undefined = undefined
let hasShowTraffic = false
let drawing = false
const ConnCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const ConnCard: React.FC<Props> = (props) => {
const { theme = 'system', systemTheme = 'dark' } = useTheme()
const { iconOnly } = props
const { appConfig } = useAppConfig()
const { showTraffic = false, connectionCardStatus = 'col-span-2', customTheme } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/connections')
const [upload, setUpload] = useState(0)
@ -87,6 +92,26 @@ const ConnCard: React.FC = () => {
}
}, [showTraffic])
if (iconOnly) {
return (
<div className={`${connectionCardStatus} flex justify-center`}>
<Tooltip content="连接" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/connections')
}}
>
<IoLink className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,16 +1,23 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { LuServer } from 'react-icons/lu'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { patchMihomoConfig } from '@renderer/utils/ipc'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const DNSCard: React.FC = () => {
import React from 'react'
interface Props {
iconOnly?: boolean
}
const DNSCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { dnsCardStatus = 'col-span-1', controlDns = true } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/dns')
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
const { dns, tun } = controledMihomoConfig || {}
@ -31,6 +38,26 @@ const DNSCard: React.FC = () => {
await patchMihomoConfig({ dns: { enable } })
}
if (iconOnly) {
return (
<div className={`${dnsCardStatus} ${!controlDns ? 'hidden' : ''} flex justify-center`}>
<Tooltip content="DNS" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/dns')
}}
>
<LuServer className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,13 +1,21 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { IoJournalOutline } from 'react-icons/io5'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const LogCard: React.FC = () => {
import React from 'react'
interface Props {
iconOnly?: boolean
}
const LogCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { logCardStatus = 'col-span-1' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/logs')
const {
attributes,
@ -20,6 +28,26 @@ const LogCard: React.FC = () => {
id: 'log'
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${logCardStatus} flex justify-center`}>
<Tooltip content="日志" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/logs')
}}
>
<IoJournalOutline className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,21 +1,27 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { calcTraffic } from '@renderer/utils/calc'
import { mihomoVersion, restartCore } from '@renderer/utils/ipc'
import { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { IoMdRefresh } from 'react-icons/io'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import PubSub from 'pubsub-js'
import useSWR from 'swr'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { LuCpu } from 'react-icons/lu'
const MihomoCoreCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const MihomoCoreCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { mihomoCoreCardStatus = 'col-span-2' } = appConfig || {}
const { data: version, mutate } = useSWR('mihomoVersion', mihomoVersion)
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/mihomo')
const {
attributes,
@ -43,6 +49,26 @@ const MihomoCoreCard: React.FC = () => {
}
}, [])
if (iconOnly) {
return (
<div className={`${mihomoCoreCardStatus} flex justify-center`}>
<Tooltip content="内核设置" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/mihomo')
}}
>
<LuCpu className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,15 +1,21 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import React from 'react'
import { MdFormatOverline } from 'react-icons/md'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const OverrideCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const OverrideCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { overrideCardStatus = 'col-span-1' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/override')
const {
attributes,
@ -22,6 +28,25 @@ const OverrideCard: React.FC = () => {
id: 'override'
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${overrideCardStatus} flex justify-center`}>
<Tooltip content="覆写" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/override')
}}
>
<MdFormatOverline className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter, Chip, Progress, Tooltip } from '@nextui-org/react'
import { useProfileConfig } from '@renderer/hooks/use-profile-config'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { calcTraffic, calcPercent } from '@renderer/utils/calc'
import { CgLoadbarDoc } from 'react-icons/cg'
import { IoMdRefresh } from 'react-icons/io'
@ -9,7 +9,7 @@ import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
import { useState } from 'react'
import React, { useState } from 'react'
import ConfigViewer from './config-viewer'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { TiFolder } from 'react-icons/ti'
@ -17,10 +17,16 @@ import { TiFolder } from 'react-icons/ti'
dayjs.extend(relativeTime)
dayjs.locale('zh-cn')
const ProfileCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const ProfileCard: React.FC<Props> = (props) => {
const { appConfig, patchAppConfig } = useAppConfig()
const { iconOnly } = props
const { profileCardStatus = 'col-span-2', profileDisplayDate = 'expire' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/profiles')
const [updating, setUpdating] = useState(false)
const [showRuntimeConfig, setShowRuntimeConfig] = useState(false)
@ -47,6 +53,26 @@ const ProfileCard: React.FC = () => {
const usage = (extra?.upload ?? 0) + (extra?.download ?? 0)
const total = extra?.total ?? 0
if (iconOnly) {
return (
<div className={`${profileCardStatus} flex justify-center`}>
<Tooltip content="订阅管理" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/profiles')
}}
>
<TiFolder className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,15 +1,22 @@
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Chip, Tooltip } from '@nextui-org/react'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { LuGroup } from 'react-icons/lu'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useGroups } from '@renderer/hooks/use-groups'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import React from 'react'
const ProxyCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const ProxyCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { proxyCardStatus = 'col-span-1' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/proxies')
const { groups = [] } = useGroups()
const {
@ -24,6 +31,25 @@ const ProxyCard: React.FC = () => {
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${proxyCardStatus} flex justify-center`}>
<Tooltip content="代理组" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/proxies')
}}
>
<LuGroup className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,14 +1,21 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import React from 'react'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { IoLayersOutline } from 'react-icons/io5'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const ResourceCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const ResourceCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { resourceCardStatus = 'col-span-1' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/resources')
const {
attributes,
@ -21,6 +28,26 @@ const ResourceCard: React.FC = () => {
id: 'resource'
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${resourceCardStatus} flex justify-center`}>
<Tooltip content="外部资源" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/resources')
}}
>
<IoLayersOutline className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,15 +1,22 @@
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Chip, Tooltip } from '@nextui-org/react'
import { MdOutlineAltRoute } from 'react-icons/md'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useRules } from '@renderer/hooks/use-rules'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import React from 'react'
const RuleCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const RuleCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { ruleCardStatus = 'col-span-1' } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/rules')
const { rules } = useRules()
const {
@ -23,6 +30,26 @@ const RuleCard: React.FC = () => {
id: 'rule'
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${ruleCardStatus} flex justify-center`}>
<Tooltip content="规则" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/rules')
}}
>
<MdOutlineAltRoute className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,17 +1,23 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { RiScan2Fill } from 'react-icons/ri'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { patchMihomoConfig } from '@renderer/utils/ipc'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import React from 'react'
const SniffCard: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const SniffCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { sniffCardStatus = 'col-span-1', controlSniff = true } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/sniffer')
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
const { sniffer } = controledMihomoConfig || {}
@ -32,6 +38,26 @@ const SniffCard: React.FC = () => {
await patchMihomoConfig({ sniffer: { enable } })
}
if (iconOnly) {
return (
<div className={`${sniffCardStatus} ${!controlSniff ? 'hidden' : ''} flex justify-center`}>
<Tooltip content="域名嗅探" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/sniffer')
}}
>
<RiScan2Fill className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,13 +1,21 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { useLocation } from 'react-router-dom'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { useLocation, useNavigate } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import SubStoreIcon from '../base/substore-icon'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const SubStoreCard: React.FC = () => {
import React from 'react'
interface Props {
iconOnly?: boolean
}
const SubStoreCard: React.FC<Props> = (props) => {
const { appConfig } = useAppConfig()
const { iconOnly } = props
const { substoreCardStatus = 'col-span-1', useSubStore = true } = appConfig || {}
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/substore')
const {
attributes,
@ -20,6 +28,27 @@ const SubStoreCard: React.FC = () => {
id: 'substore'
})
const transform = tf ? { x: tf.x, y: tf.y, scaleX: 1, scaleY: 1 } : null
if (iconOnly) {
return (
<div className={`${substoreCardStatus} flex justify-center`}>
<Tooltip content="Sub-Store" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/substore')
}}
>
<SubStoreIcon className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { triggerSysProxy } from '@renderer/utils/ipc'
import { AiOutlineGlobal } from 'react-icons/ai'
@ -8,8 +8,14 @@ import React from 'react'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
const SysproxySwitcher: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const SysproxySwitcher: React.FC<Props> = (props) => {
const { iconOnly } = props
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/sysproxy')
const { appConfig, patchAppConfig } = useAppConfig()
const { sysProxy, sysproxyCardStatus = 'col-span-1' } = appConfig || {}
@ -36,6 +42,26 @@ const SysproxySwitcher: React.FC = () => {
}
}
if (iconOnly) {
return (
<div className={`${sysproxyCardStatus} flex justify-center`}>
<Tooltip content="系统代理" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/sysproxy')
}}
>
<AiOutlineGlobal className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{

View File

@ -1,16 +1,22 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { Button, Card, CardBody, CardFooter, Tooltip } from '@nextui-org/react'
import { useControledMihomoConfig } from '@renderer/hooks/use-controled-mihomo-config'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { TbDeviceIpadHorizontalBolt } from 'react-icons/tb'
import { useLocation } from 'react-router-dom'
import { useLocation, useNavigate } from 'react-router-dom'
import { restartCore } from '@renderer/utils/ipc'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import React from 'react'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const TunSwitcher: React.FC = () => {
interface Props {
iconOnly?: boolean
}
const TunSwitcher: React.FC<Props> = (props) => {
const { iconOnly } = props
const location = useLocation()
const navigate = useNavigate()
const match = location.pathname.includes('/tun') || false
const { appConfig } = useAppConfig()
const { tunCardStatus = 'col-span-1' } = appConfig || {}
@ -39,6 +45,26 @@ const TunSwitcher: React.FC = () => {
window.electron.ipcRenderer.send('updateTrayMenu')
}
if (iconOnly) {
return (
<div className={`${tunCardStatus} flex justify-center`}>
<Tooltip content="虚拟网卡" placement="right">
<Button
size="sm"
isIconOnly
color={match ? 'primary' : 'default'}
variant={match ? 'solid' : 'light'}
onPress={() => {
navigate('/tun')
}}
>
<TbDeviceIpadHorizontalBolt className="text-[20px]" />
</Button>
</Tooltip>
</div>
)
}
return (
<div
style={{