Skip to content

Commit

Permalink
support for sorting sidebar items
Browse files Browse the repository at this point in the history
  • Loading branch information
pompurin404 committed Aug 11, 2024
1 parent a8e886b commit 5c7f3f4
Show file tree
Hide file tree
Showing 18 changed files with 662 additions and 359 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
"yaml": "^2.5.0"
},
"devDependencies": {
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
"@electron-toolkit/eslint-config-ts": "^2.0.0",
"@electron-toolkit/tsconfig": "^1.0.1",
Expand Down
56 changes: 56 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/main/utils/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ export const defaultConfig: IAppConfig = {
autoCloseConnection: true,
useNameserverPolicy: false,
nameserverPolicy: {},
siderOrder: [
'mode',
'sysproxy',
'tun',
'profile',
'proxy',
'mihomo',
'connection',
'dns',
'sniff',
'log',
'rule',
'resource',
'override'
],
sysProxy: { enable: false, mode: 'manual' }
}

Expand Down
118 changes: 79 additions & 39 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { useTheme } from 'next-themes'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useLocation, useNavigate, useRoutes } from 'react-router-dom'
import OutboundModeSwitcher from '@renderer/components/sider/outbound-mode-switcher'
import SysproxySwitcher from '@renderer/components/sider/sysproxy-switcher'
import TunSwitcher from '@renderer/components/sider/tun-switcher'
import { Button, Divider } from '@nextui-org/react'
import { IoSettings } from 'react-icons/io5'
import routes from '@renderer/routes'
import {
DndContext,
closestCenter,
PointerSensor,
useSensor,
useSensors,
DragEndEvent
} from '@dnd-kit/core'
import { SortableContext } from '@dnd-kit/sortable'
import ProfileCard from '@renderer/components/sider/profile-card'
import ProxyCard from '@renderer/components/sider/proxy-card'
import RuleCard from '@renderer/components/sider/rule-card'
Expand All @@ -21,8 +30,31 @@ import UpdaterButton from '@renderer/components/updater/updater-button'
import { useAppConfig } from './hooks/use-app-config'

const App: React.FC = () => {
const { appConfig } = useAppConfig()
const { appTheme = 'system' } = appConfig || {}
const { appConfig, patchAppConfig } = useAppConfig()
const {
appTheme = 'system',
siderOrder = [
'sysproxy',
'tun',
'profile',
'proxy',
'mihomo',
'connection',
'dns',
'sniff',
'log',
'rule',
'resource',
'override'
]
} = appConfig || {}
const [order, setOrder] = useState(siderOrder)
const sensors = useSensors(
useSensor(PointerSensor)
// useSensor(KeyboardSensor, {
// coordinateGetter: sortableKeyboardCoordinates
// })
)
const { setTheme } = useTheme()
const navigate = useNavigate()
const location = useLocation()
Expand All @@ -32,6 +64,36 @@ const App: React.FC = () => {
setTheme(appTheme)
}, [appTheme])

const onDragEnd = async (event: DragEndEvent): Promise<void> => {
const { active, over } = event
if (over) {
if (active.id !== over.id) {
const newOrder = order.slice()
const activeIndex = newOrder.indexOf(active.id as string)
const overIndex = newOrder.indexOf(over.id as string)
newOrder.splice(activeIndex, 1)
newOrder.splice(overIndex, 0, active.id as string)
setOrder(newOrder)
await patchAppConfig({ siderOrder: newOrder })
}
}
}

const componentMap = {
sysproxy: <SysproxySwitcher />,
tun: <TunSwitcher />,
profile: <ProfileCard />,
proxy: <ProxyCard />,
mihomo: <MihomoCoreCard />,
connection: <ConnCard />,
dns: <DNSCard />,
sniff: <SniffCard />,
log: <LogCard />,
rule: <RuleCard />,
resource: <ResourceCard />,
override: <OverrideCard />
}

return (
<div className="w-full h-[100vh] flex">
<div className="side w-[250px] h-full overflow-y-auto no-scrollbar">
Expand All @@ -51,44 +113,22 @@ const App: React.FC = () => {
/>
</div>
</div>
<div className="grid grid-cols-2 gap-2 mx-2">
<div className="mt-2 mx-2">
<OutboundModeSwitcher />
<SysproxySwitcher />
<TunSwitcher />
<ProfileCard />
<ProxyCard />
<MihomoCoreCard />
<ConnCard />
<DNSCard />
<SniffCard />
<LogCard />
<RuleCard />
<ResourceCard />
<OverrideCard />
</div>
{/* <div className="flex justify-between mx-2 mb-2">
<SysproxySwitcher />
<TunSwitcher />
</div>
<div className="mx-2">
<ProfileCard />
<ProxyCard />
<MihomoCoreCard />
<ConnCard />
</div>
<div className="flex justify-between mx-2">
<DNSCard />
<SniffCard />
</div>
<div className="flex justify-between mx-2">
<LogCard />
<RuleCard />
</div>
<div className="flex justify-between mx-2">
<ResourceCard />
<OverrideCard />
</div> */}
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={onDragEnd}>
<div className="grid grid-cols-2 gap-2 m-2">
<SortableContext
items={order.map((x) => {
return x
})}
>
{order.map((key: string) => {
return componentMap[key]
})}
</SortableContext>
</div>
</DndContext>
</div>
<Divider orientation="vertical" />
<div className="main w-[calc(100%-251px)] h-full overflow-y-auto">{page}</div>
Expand Down
77 changes: 46 additions & 31 deletions src/renderer/src/components/sider/conn-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { FaCircleArrowDown, FaCircleArrowUp } from 'react-icons/fa6'
import { useLocation, useNavigate } from 'react-router-dom'
import { calcTraffic } from '@renderer/utils/calc'
import { useEffect, useState } from 'react'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { IoLink } from 'react-icons/io5'

const ConnCard: React.FC = () => {
Expand All @@ -12,6 +14,9 @@ const ConnCard: React.FC = () => {

const [upload, setUpload] = useState(0)
const [download, setDownload] = useState(0)
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: 'connection'
})

useEffect(() => {
window.electron.ipcRenderer.on('mihomoTraffic', (_e, info: IMihomoTrafficInfo) => {
Expand All @@ -24,41 +29,51 @@ const ConnCard: React.FC = () => {
}, [])

return (
<Card
fullWidth
className={`col-span-2 ${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/connections')}
<div
style={{
position: 'relative',
transform: CSS.Transform.toString(transform),
transition,
zIndex: isDragging ? 'calc(infinity)' : undefined
}}
className="col-span-2"
>
<CardBody className="pb-1 pt-0 px-0">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"
variant="flat"
color="default"
>
<IoLink
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/connections')}
>
<CardBody className="pb-0 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"
variant="flat"
color="default"
className={`${match ? 'text-white' : 'text-foreground'} text-[24px]`}
/>
</Button>
<div className={`p-2 w-full ${match ? 'text-white' : 'text-foreground'} `}>
<div className="flex justify-between">
<div className="w-full text-right mr-2">{calcTraffic(upload)}/s</div>
<FaCircleArrowUp className="h-[24px] leading-[24px]" />
</div>
<div className="flex justify-between">
<div className="w-full text-right mr-2">{calcTraffic(download)}/s</div>
<FaCircleArrowDown className="h-[24px] leading-[24px]" />
>
<IoLink
color="default"
className={`${match ? 'text-white' : 'text-foreground'} text-[24px]`}
/>
</Button>
<div className={`p-2 w-full ${match ? 'text-white' : 'text-foreground'} `}>
<div className="flex justify-between">
<div className="w-full text-right mr-2">{calcTraffic(upload)}/s</div>
<FaCircleArrowUp className="h-[24px] leading-[24px]" />
</div>
<div className="flex justify-between">
<div className="w-full text-right mr-2">{calcTraffic(download)}/s</div>
<FaCircleArrowDown className="h-[24px] leading-[24px]" />
</div>
</div>
</div>
</div>
</CardBody>
<CardFooter className="pt-1">
<h3 className={`text-md font-bold ${match ? 'text-white' : 'text-foreground'}`}>连接</h3>
</CardFooter>
</Card>
</CardBody>
<CardFooter className="pt-1">
<h3 className={`text-md font-bold ${match ? 'text-white' : 'text-foreground'}`}>连接</h3>
</CardFooter>
</Card>
</div>
)
}

Expand Down
Loading

0 comments on commit 5c7f3f4

Please sign in to comment.