From 8deca2fa5bf1da2ba76191616d4a1638d1d79f9d Mon Sep 17 00:00:00 2001 From: c0mrade Date: Sun, 1 Feb 2026 22:46:16 +0300 Subject: [PATCH] fix: disable Telegram vertical swipes during drag operations - Add useTelegramDnd hook for @dnd-kit integration - Update Sheet components to disable swipes when open - Update AdminPaymentMethods to use the new hook - Prevents conflict between app drag gestures and Telegram swipe-to-close --- src/components/primitives/Sheet/Sheet.tsx | 18 ++++++++ src/components/ui/Sheet.tsx | 17 +++++++ src/hooks/useTelegramDnd.ts | 55 +++++++++++++++++++++++ src/pages/AdminPaymentMethods.tsx | 55 +++++++++++++++++------ 4 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 src/hooks/useTelegramDnd.ts diff --git a/src/components/primitives/Sheet/Sheet.tsx b/src/components/primitives/Sheet/Sheet.tsx index a88b994..3d0f50e 100644 --- a/src/components/primitives/Sheet/Sheet.tsx +++ b/src/components/primitives/Sheet/Sheet.tsx @@ -7,10 +7,12 @@ import { useContext, useState, useCallback, + useEffect, } from 'react'; import { cn } from '@/lib/utils'; import { usePlatform } from '@/platform'; import { useBackButton } from '@/platform'; +import { useTelegramSDK } from '@/hooks/useTelegramSDK'; import { backdrop, backdropTransition, @@ -138,10 +140,26 @@ export const SheetContent = forwardRef( const { open, onClose } = useContext(SheetContext); const { haptic } = usePlatform(); const dragControls = useDragControls(); + const { disableVerticalSwipes, enableVerticalSwipes, isTelegramWebApp } = useTelegramSDK(); // Back button integration useBackButton(open ? onClose : null); + // Disable Telegram vertical swipes when sheet is open (prevents conflict with drag gestures) + useEffect(() => { + if (!isTelegramWebApp) return; + + if (open) { + disableVerticalSwipes(); + } + + return () => { + if (open) { + enableVerticalSwipes(); + } + }; + }, [open, isTelegramWebApp, disableVerticalSwipes, enableVerticalSwipes]); + const handleDragEnd = useCallback( (_: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => { const velocity = info.velocity.y; diff --git a/src/components/ui/Sheet.tsx b/src/components/ui/Sheet.tsx index 3ee4874..7b2bf42 100644 --- a/src/components/ui/Sheet.tsx +++ b/src/components/ui/Sheet.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef, useCallback, useState, type ReactNode } from 'react' import { createPortal } from 'react-dom'; import { useBackButton } from '@/platform'; import { useHaptic } from '@/platform'; +import { useTelegramSDK } from '@/hooks/useTelegramSDK'; export interface SheetProps { isOpen: boolean; @@ -104,10 +105,26 @@ export function Sheet({ const [isVisible, setIsVisible] = useState(false); const haptic = useHaptic(); + const { disableVerticalSwipes, enableVerticalSwipes, isTelegramWebApp } = useTelegramSDK(); // BackButton integration useBackButton(isOpen ? onClose : null); + // Disable Telegram vertical swipes when sheet is open (prevents conflict with drag gestures) + useEffect(() => { + if (!isTelegramWebApp) return; + + if (isOpen) { + disableVerticalSwipes(); + } + + return () => { + if (isOpen) { + enableVerticalSwipes(); + } + }; + }, [isOpen, isTelegramWebApp, disableVerticalSwipes, enableVerticalSwipes]); + // Calculate current height based on snap point const currentHeight = `${snapPoints[currentSnapIndex] * 100}vh`; diff --git a/src/hooks/useTelegramDnd.ts b/src/hooks/useTelegramDnd.ts new file mode 100644 index 0000000..8f20e1f --- /dev/null +++ b/src/hooks/useTelegramDnd.ts @@ -0,0 +1,55 @@ +import { useCallback, useRef } from 'react'; +import { useTelegramSDK } from './useTelegramSDK'; + +/** + * Hook to manage Telegram vertical swipes during drag-and-drop operations. + * Disables Telegram's swipe-to-close gesture while dragging to prevent conflicts. + * + * Usage with @dnd-kit: + * ```tsx + * const { onDragStart, onDragEnd } = useTelegramDnd(); + * + * { + * onDragStart(); + * // your drag start logic + * }} + * onDragEnd={(e) => { + * onDragEnd(); + * // your drag end logic + * }} + * > + * ``` + */ +export function useTelegramDnd() { + const { disableVerticalSwipes, enableVerticalSwipes, isTelegramWebApp } = useTelegramSDK(); + const isDraggingRef = useRef(false); + + const onDragStart = useCallback(() => { + if (isTelegramWebApp && !isDraggingRef.current) { + isDraggingRef.current = true; + disableVerticalSwipes(); + } + }, [isTelegramWebApp, disableVerticalSwipes]); + + const onDragEnd = useCallback(() => { + if (isTelegramWebApp && isDraggingRef.current) { + isDraggingRef.current = false; + enableVerticalSwipes(); + } + }, [isTelegramWebApp, enableVerticalSwipes]); + + const onDragCancel = useCallback(() => { + if (isTelegramWebApp && isDraggingRef.current) { + isDraggingRef.current = false; + enableVerticalSwipes(); + } + }, [isTelegramWebApp, enableVerticalSwipes]); + + return { + onDragStart, + onDragEnd, + onDragCancel, + isTelegramWebApp, + }; +} diff --git a/src/pages/AdminPaymentMethods.tsx b/src/pages/AdminPaymentMethods.tsx index b30d299..456f087 100644 --- a/src/pages/AdminPaymentMethods.tsx +++ b/src/pages/AdminPaymentMethods.tsx @@ -8,7 +8,9 @@ import { useSensor, useSensors, type DragEndEvent, + type DragStartEvent, } from '@dnd-kit/core'; +import { useTelegramDnd } from '../hooks/useTelegramDnd'; import { arrayMove, SortableContext, @@ -674,18 +676,40 @@ export default function AdminPaymentMethods() { useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }), ); - const handleDragEnd = useCallback((event: DragEndEvent) => { - const { active, over } = event; - if (over && active.id !== over.id) { - setMethods((prev) => { - const oldIndex = prev.findIndex((m) => m.method_id === active.id); - const newIndex = prev.findIndex((m) => m.method_id === over.id); - if (oldIndex === -1 || newIndex === -1) return prev; - return arrayMove(prev, oldIndex, newIndex); - }); - setOrderChanged(true); - } - }, []); + // Telegram swipe behavior for drag-and-drop + const { + onDragStart: onTelegramDragStart, + onDragEnd: onTelegramDragEnd, + onDragCancel: onTelegramDragCancel, + } = useTelegramDnd(); + + const handleDragStart = useCallback( + (_event: DragStartEvent) => { + onTelegramDragStart(); + }, + [onTelegramDragStart], + ); + + const handleDragEnd = useCallback( + (event: DragEndEvent) => { + onTelegramDragEnd(); + const { active, over } = event; + if (over && active.id !== over.id) { + setMethods((prev) => { + const oldIndex = prev.findIndex((m) => m.method_id === active.id); + const newIndex = prev.findIndex((m) => m.method_id === over.id); + if (oldIndex === -1 || newIndex === -1) return prev; + return arrayMove(prev, oldIndex, newIndex); + }); + setOrderChanged(true); + } + }, + [onTelegramDragEnd], + ); + + const handleDragCancel = useCallback(() => { + onTelegramDragCancel(); + }, [onTelegramDragCancel]); const handleSaveOrder = () => { saveOrderMutation.mutate(methods.map((m) => m.method_id)); @@ -737,7 +761,12 @@ export default function AdminPaymentMethods() {
) : methods.length > 0 ? ( - + m.method_id)} strategy={verticalListSortingStrategy}