Fix dnd on touch devices

This commit is contained in:
schroda
2025-07-08 22:37:57 +02:00
parent 8783956fbc
commit 74f0fec02d
2 changed files with 38 additions and 4 deletions

View File

@@ -16,7 +16,7 @@ import {
SensorOptions, SensorOptions,
useSensors, useSensors,
} from '@dnd-kit/core'; } from '@dnd-kit/core';
import { AbstractPointerSensorOptions } from '@dnd-kit/core/dist/sensors'; import { AbstractPointerSensorOptions, PointerActivationConstraint } from '@dnd-kit/core/dist/sensors';
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx'; import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
export class DndKitUtil { export class DndKitUtil {
@@ -28,11 +28,38 @@ export class DndKitUtil {
return MouseSensor; return MouseSensor;
} }
static useGetSensorForDevice(): Sensor<PointerSensorOptions> {
MediaQuery.useIsTouchDevice();
return DndKitUtil.getSensorForDevice();
}
static useGetActivationConstraintForDevice(): PointerActivationConstraint {
const isTouchDevice = MediaQuery.useIsTouchDevice();
if (isTouchDevice) {
return {
delay: 300,
tolerance: 8,
};
}
return {
distance: 8,
};
}
static useSensorsForDevice(options?: AbstractPointerSensorOptions): SensorDescriptor<SensorOptions>[] { static useSensorsForDevice(options?: AbstractPointerSensorOptions): SensorDescriptor<SensorOptions>[] {
const sensor = DndKitUtil.useGetSensorForDevice();
const activationConstraint = DndKitUtil.useGetActivationConstraintForDevice();
return useSensors( return useSensors(
useSensor(DndKitUtil.getSensorForDevice(), { useSensor(sensor, {
...options, ...options,
activationConstraint: { distance: 15, ...options?.activationConstraint }, activationConstraint: {
...activationConstraint,
...options?.activationConstraint,
},
}), }),
); );
} }

View File

@@ -28,10 +28,12 @@ import { makeToast } from '@/modules/core/utils/Toast.ts';
import { requestManager } from '@/lib/requests/RequestManager.ts'; import { requestManager } from '@/lib/requests/RequestManager.ts';
import { DownloaderState } from '@/lib/graphql/generated/graphql.ts'; import { DownloaderState } from '@/lib/graphql/generated/graphql.ts';
import { ChapterDownloadStatus, ChapterIdInfo } from '@/modules/chapter/Chapter.types.ts'; import { ChapterDownloadStatus, ChapterIdInfo } from '@/modules/chapter/Chapter.types.ts';
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
export const DownloadQueueChapterCard = memo( export const DownloadQueueChapterCard = memo(
({ item, status }: { item: ChapterDownloadStatus; status: DownloaderState }) => { ({ item, status }: { item: ChapterDownloadStatus; status: DownloaderState }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const preventMobileContextMenu = MediaQuery.usePreventMobileContextMenu();
const handleDelete = useCallback( const handleDelete = useCallback(
async (chapter: ChapterIdInfo) => { async (chapter: ChapterIdInfo) => {
@@ -68,7 +70,12 @@ export const DownloadQueueChapterCard = memo(
return ( return (
<Box sx={{ p: 1, pb: 0 }}> <Box sx={{ p: 1, pb: 0 }}>
<Card> <Card>
<CardActionArea component={Link} to={AppRoutes.manga.path(item.manga.id)}> <CardActionArea
component={Link}
to={AppRoutes.manga.path(item.manga.id)}
onContextMenu={preventMobileContextMenu}
sx={MediaQuery.preventMobileContextMenuSx()}
>
<ListCardContent> <ListCardContent>
<IconButton {...MUIUtil.preventRippleProp()} sx={{ pointerEvents: 'none' }}> <IconButton {...MUIUtil.preventRippleProp()} sx={{ pointerEvents: 'none' }}>
<DragHandle /> <DragHandle />