mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 17:15:38 +08:00
feat: Support Drag to Reorder the Profile (#29)
* feat: Support Drag to Reorder the Profile * style: Remove unnecessary styles
This commit is contained in:
@@ -3,6 +3,19 @@ import { useMemo, useRef, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { useSetRecoilState } from "recoil";
|
||||
import { Box, Button, Grid, IconButton, Stack, TextField } from "@mui/material";
|
||||
import {
|
||||
DndContext,
|
||||
closestCenter,
|
||||
KeyboardSensor,
|
||||
PointerSensor,
|
||||
useSensor,
|
||||
useSensors,
|
||||
DragEndEvent,
|
||||
} from "@dnd-kit/core";
|
||||
import {
|
||||
SortableContext,
|
||||
sortableKeyboardCoordinates,
|
||||
} from "@dnd-kit/sortable";
|
||||
import { LoadingButton } from "@mui/lab";
|
||||
import {
|
||||
ClearRounded,
|
||||
@@ -19,6 +32,7 @@ import {
|
||||
getRuntimeLogs,
|
||||
deleteProfile,
|
||||
updateProfile,
|
||||
reorderProfile,
|
||||
} from "@/services/cmds";
|
||||
import { atomLoadingCache } from "@/services/states";
|
||||
import { closeAllConnections } from "@/services/api";
|
||||
@@ -40,7 +54,12 @@ const ProfilePage = () => {
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [activating, setActivating] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
})
|
||||
);
|
||||
const {
|
||||
profiles = {},
|
||||
activateSelected,
|
||||
@@ -106,6 +125,16 @@ const ProfilePage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onDragEnd = async (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
if (over) {
|
||||
if (active.id !== over.id) {
|
||||
await reorderProfile(active.id.toString(), over.id.toString());
|
||||
mutateProfiles();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onSelect = useLockFn(async (current: string, force: boolean) => {
|
||||
if (!force && current === profiles.current) return;
|
||||
// 避免大多数情况下loading态闪烁
|
||||
@@ -293,22 +322,34 @@ const ProfilePage = () => {
|
||||
{t("New")}
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Box sx={{ mb: 4.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
{regularItems.map((item) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileItem
|
||||
selected={profiles.current === item.uid}
|
||||
activating={activating === item.uid}
|
||||
itemData={item}
|
||||
onSelect={(f) => onSelect(item.uid, f)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={onDragEnd}
|
||||
>
|
||||
<Box sx={{ mb: 4.5 }}>
|
||||
<Grid container spacing={{ xs: 1, lg: 1 }}>
|
||||
<SortableContext
|
||||
items={regularItems.map((x) => {
|
||||
return x.uid;
|
||||
})}
|
||||
>
|
||||
{regularItems.map((item) => (
|
||||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileItem
|
||||
id={item.uid}
|
||||
selected={profiles.current === item.uid}
|
||||
activating={activating === item.uid}
|
||||
itemData={item}
|
||||
onSelect={(f) => onSelect(item.uid, f)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</SortableContext>
|
||||
</Grid>
|
||||
</Box>
|
||||
</DndContext>
|
||||
|
||||
{enhanceItems.length > 0 && (
|
||||
<Grid container spacing={{ xs: 2, lg: 2 }}>
|
||||
@@ -330,7 +371,6 @@ const ProfilePage = () => {
|
||||
))}
|
||||
</Grid>
|
||||
)}
|
||||
|
||||
<ProfileViewer ref={viewerRef} onChange={() => mutateProfiles()} />
|
||||
<ConfigViewer ref={configRef} />
|
||||
</BasePage>
|
||||
|
||||
Reference in New Issue
Block a user