feat: Support Drag to Reorder the Profile (#29)

* feat: Support Drag to Reorder the Profile

* style: Remove unnecessary styles
This commit is contained in:
Pylogmon
2023-11-29 08:54:02 +08:00
committed by GitHub
parent 2680c1e8b3
commit 0775560ad2
8 changed files with 208 additions and 40 deletions

View File

@@ -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>