fix card drag behavior (#135)

Co-authored-by: 布丁狗~ <pompurin404@mihomo.party>
This commit is contained in:
DtHnAme 2024-09-06 20:27:23 +08:00 committed by GitHub
parent 79b3da1da6
commit c46a26192a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 75 additions and 89 deletions

View File

@ -9,7 +9,7 @@ import { IoSettings } from 'react-icons/io5'
import routes from '@renderer/routes'
import {
DndContext,
closestCenter,
closestCorners,
PointerSensor,
useSensor,
useSensors,
@ -111,8 +111,25 @@ const App: React.FC = () => {
newOrder.splice(overIndex, 0, active.id as string)
setOrder(newOrder)
await patchAppConfig({ siderOrder: newOrder })
return
}
}
navigate(navigateMap[active.id as string])
}
const navigateMap = {
sysproxy: "sysproxy",
tun: "tun",
profile: "profiles",
proxy: "proxies",
mihomo: "mihomo",
connection: "connections",
dns: "dns",
sniff: "sniffer",
log: "logs",
rule: "rules",
resource: "resources",
override: "override"
}
const componentMap = {
@ -158,13 +175,9 @@ const App: React.FC = () => {
<div className="mt-2 mx-2">
<OutboundModeSwitcher />
</div>
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={onDragEnd}>
<DndContext sensors={sensors} collisionDetection={closestCorners} onDragEnd={onDragEnd}>
<div className="grid grid-cols-2 gap-2 m-2">
<SortableContext
items={order.map((x) => {
return x
})}
>
<SortableContext items={order}>
{order.map((key: string) => {
return componentMap[key]
})}

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { FaCircleArrowDown, FaCircleArrowUp } from 'react-icons/fa6'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { calcTraffic } from '@renderer/utils/calc'
import { useEffect, useState } from 'react'
import { useSortable } from '@dnd-kit/sortable'
@ -21,7 +21,6 @@ const ConnCard: React.FC = () => {
const { theme = 'system', systemTheme = 'dark' } = useTheme()
const { appConfig } = useAppConfig()
const { showTraffic, connectionCardStatus = 'col-span-2' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/connections')
@ -178,12 +177,11 @@ const ConnCard: React.FC = () => {
<>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/connections')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"
@ -226,12 +224,11 @@ const ConnCard: React.FC = () => {
) : (
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/logs')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter } 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, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { patchMihomoConfig } from '@renderer/utils/ipc'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
@ -10,7 +10,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
const DNSCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { dnsCardStatus = 'col-span-1', controlDns = true } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/dns')
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
@ -44,12 +43,11 @@ const DNSCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/dns')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,13 +1,12 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import { IoJournalOutline } from 'react-icons/io5'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } 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 = () => {
const { appConfig } = useAppConfig()
const { logCardStatus = 'col-span-1' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/logs')
const {
@ -33,12 +32,11 @@ const LogCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/logs')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -5,7 +5,7 @@ import { useEffect, useState } from 'react'
import { IoMdRefresh } from 'react-icons/io'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import PubSub from 'pubsub-js'
import useSWR from 'swr'
import { useAppConfig } from '@renderer/hooks/use-app-config'
@ -15,7 +15,6 @@ const MihomoCoreCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { mihomoCoreCardStatus = 'col-span-2' } = appConfig || {}
const { data: version, mutate } = useSWR('mihomoVersion', mihomoVersion)
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/mihomo')
const {
@ -57,9 +56,8 @@ const MihomoCoreCard: React.FC = () => {
{mihomoCoreCardStatus === 'col-span-2' ? (
<Card
fullWidth
isPressable
onPress={() => navigate('/mihomo')}
className={`${match ? 'bg-primary' : ''}`}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody>
<div
@ -107,12 +105,11 @@ const MihomoCoreCard: React.FC = () => {
) : (
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/mihomo')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,7 +1,7 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import React from 'react'
import { MdFormatOverline } from 'react-icons/md'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useAppConfig } from '@renderer/hooks/use-app-config'
@ -9,7 +9,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
const OverrideCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { overrideCardStatus = 'col-span-1' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/override')
const {
@ -35,12 +34,11 @@ const OverrideCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/override')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter, Chip, Progress } from '@nextui-org/react'
import { useProfileConfig } from '@renderer/hooks/use-profile-config'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { calcTraffic, calcPercent } from '@renderer/utils/calc'
import { CgLoadbarDoc } from 'react-icons/cg'
import { IoMdRefresh } from 'react-icons/io'
@ -20,7 +20,6 @@ dayjs.locale('zh-cn')
const ProfileCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { profileCardStatus = 'col-span-2' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/profiles')
const [updating, setUpdating] = useState(false)
@ -62,9 +61,8 @@ const ProfileCard: React.FC = () => {
{profileCardStatus === 'col-span-2' ? (
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/profiles')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1">
<div
@ -152,12 +150,11 @@ const ProfileCard: React.FC = () => {
) : (
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/profiles')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -2,14 +2,13 @@ import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
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 { useLocation } from 'react-router-dom'
import { useGroups } from '@renderer/hooks/use-groups'
import { useAppConfig } from '@renderer/hooks/use-app-config'
const ProxyCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { proxyCardStatus = 'col-span-1' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/proxies')
const { groups = [] } = useGroups()
@ -37,12 +36,11 @@ const ProxyCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/proxies')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import React from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { IoLayersOutline } from 'react-icons/io5'
@ -8,7 +8,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
const ResourceCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { resourceCardStatus = 'col-span-1' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/resources')
const {
@ -34,12 +33,11 @@ const ResourceCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/resources')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter, Chip } from '@nextui-org/react'
import { MdOutlineAltRoute } from 'react-icons/md'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useRules } from '@renderer/hooks/use-rules'
@ -9,7 +9,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
const RuleCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { ruleCardStatus = 'col-span-1' } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/rules')
const { rules } = useRules()
@ -36,12 +35,11 @@ const RuleCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/rules')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,7 +1,7 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { RiScan2Fill } from 'react-icons/ri'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } 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'
@ -11,7 +11,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
const SniffCard: React.FC = () => {
const { appConfig } = useAppConfig()
const { sniffCardStatus = 'col-span-1', controlSniff = true } = appConfig || {}
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/sniffer')
const { controledMihomoConfig, patchControledMihomoConfig } = useControledMihomoConfig()
@ -45,12 +44,11 @@ const SniffCard: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/sniffer')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -1,6 +1,6 @@
import { Button, Card, CardBody, CardFooter } from '@nextui-org/react'
import BorderSwitch from '@renderer/components/base/border-swtich'
import { useLocation, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { useAppConfig } from '@renderer/hooks/use-app-config'
import { triggerSysProxy } from '@renderer/utils/ipc'
import { AiOutlineGlobal } from 'react-icons/ai'
@ -9,7 +9,6 @@ import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
const SysproxySwitcher: React.FC = () => {
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/sysproxy')
const { appConfig, patchAppConfig } = useAppConfig()
@ -48,12 +47,11 @@ const SysproxySwitcher: React.FC = () => {
>
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/sysproxy')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"

View File

@ -2,7 +2,7 @@ import { Button, Card, CardBody, CardFooter } 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, useNavigate } from 'react-router-dom'
import { useLocation } from 'react-router-dom'
import { encryptString, isEncryptionAvailable, restartCore } from '@renderer/utils/ipc'
import { useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
@ -12,7 +12,6 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
import BasePasswordModal from '../base/base-password-modal'
const TunSwitcher: React.FC = () => {
const navigate = useNavigate()
const location = useLocation()
const match = location.pathname.includes('/tun') || false
const [openPasswordModal, setOpenPasswordModal] = useState(false)
@ -85,12 +84,11 @@ const TunSwitcher: React.FC = () => {
<Card
fullWidth
className={`${match ? 'bg-primary' : ''}`}
isPressable
onPress={() => navigate('/tun')}
ref={setNodeRef} {...attributes} {...listeners}
className={`${match ? 'bg-primary' : 'hover:bg-primary/30'} ${isDragging ? 'scale-[0.97] tap-highlight-transparent' : ''}`}
>
<CardBody className="pb-1 pt-0 px-0">
<div ref={setNodeRef} {...attributes} {...listeners} className="flex justify-between">
<div className="flex justify-between">
<Button
isIconOnly
className="bg-transparent pointer-events-none"