Skip to content
This repository was archived by the owner on Mar 10, 2026. It is now read-only.

Commit 2ba78fa

Browse files
committed
chore: clean up gesture files
1 parent 50b118d commit 2ba78fa

9 files changed

Lines changed: 31 additions & 77 deletions

File tree

src/app/components/BackRouteHandler.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ReactNode } from 'react';
2-
import { useBackRoute } from './useBackRoute';
2+
import { useBackRoute } from '$hooks/useBackRoute';
33

44
type BackRouteHandlerProps = {
55
children: (onBack: () => void) => ReactNode;

src/app/components/SwipeContext.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/app/components/SwipeableChatWrapper.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
import { ReactNode } from 'react';
2-
import { animate, motion, useMotionValue } from 'motion/react';
1+
import { ReactNode, createContext } from 'react';
2+
import { animate, motion, useMotionValue, MotionValue } from 'motion/react';
33
import { useDrag } from '@use-gesture/react';
44
import { useAtomValue } from 'jotai';
55
import { settingsAtom, RightSwipeAction } from '$state/settings';
66
import { useIsMobile } from '$hooks/useIsMobile';
7-
import { SwipeContext } from './SwipeContext';
87

98
const SWIPE_DISTANCE = 80;
109
const SWIPE_VELOCITY = 0.4;
1110
const SNAP_SPRING = { type: 'spring' as const, stiffness: 600, damping: 50, mass: 0.6 };
1211

12+
const SwipeContext = createContext<MotionValue<number> | null>(null);
13+
1314
interface SwipeableChatWrapperProps {
1415
children: ReactNode;
1516
onOpenSidebar?: () => void;

src/app/components/SwipeableOverlayWrapper.tsx

Lines changed: 22 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
import { ReactNode, useRef, useCallback } from 'react';
1+
import { ReactNode } from 'react';
22
import { useAtomValue } from 'jotai';
33
import { settingsAtom } from '$state/settings';
44
import { useIsMobile } from '$hooks/useIsMobile';
5+
import { useDrag } from '@use-gesture/react';
56
import { createLogger } from '$utils/debug';
67

78
const log = createLogger('SwipeableOverlayWrapper');
89

910
const SWIPE_DISTANCE = 60;
10-
const AXIS_LOCK_RATIO = 1.5;
1111
const SWIPE_VELOCITY = 0.3;
12+
const AXIS_LOCK_RATIO = 1.5;
1213

1314
interface SwipeableOverlayWrapperProps {
1415
children: ReactNode;
@@ -23,85 +24,43 @@ export function SwipeableOverlayWrapper({
2324
}: SwipeableOverlayWrapperProps) {
2425
const settings = useAtomValue(settingsAtom);
2526
const isMobile = useIsMobile();
27+
const gesturesEnabled = settings.mobileGestures && isMobile;
2628

27-
const startX = useRef<number | null>(null);
28-
const startY = useRef<number | null>(null);
29-
const startTime = useRef<number | null>(null);
30-
31-
const handleTouchStart = useCallback(
32-
(e: React.TouchEvent) => {
33-
if (!settings.mobileGestures || !isMobile) return;
34-
const t = e.touches[0];
35-
startX.current = t.clientX;
36-
startY.current = t.clientY;
37-
startTime.current = Date.now();
38-
},
39-
[settings.mobileGestures, isMobile]
40-
);
41-
42-
const handleTouchEnd = useCallback(
43-
(e: React.TouchEvent) => {
44-
if (!settings.mobileGestures || !isMobile) return;
45-
if (startX.current === null || startY.current === null || startTime.current === null) return;
29+
const bind = useDrag(
30+
({ active, movement: [mx, my], velocity: [vx], direction: [dx] }) => {
31+
if (active) return;
4632

47-
const t = e.changedTouches[0];
48-
const dx = t.clientX - startX.current;
49-
const dy = t.clientY - startY.current;
50-
const dt = Date.now() - startTime.current;
51-
const velocity = Math.abs(dx) / dt;
33+
const axisBlocked = Math.abs(my) * AXIS_LOCK_RATIO > Math.abs(mx);
34+
if (axisBlocked) return;
5235

53-
const axisBlocked = Math.abs(dy) * AXIS_LOCK_RATIO > Math.abs(dx);
54-
const swipedLeft =
55-
direction === 'left' &&
56-
dx < 0 &&
57-
(Math.abs(dx) > SWIPE_DISTANCE || velocity > SWIPE_VELOCITY);
58-
const swipedRight =
59-
direction === 'right' &&
60-
dx > 0 &&
61-
(Math.abs(dx) > SWIPE_DISTANCE || velocity > SWIPE_VELOCITY);
36+
const thresholdMet =
37+
direction === 'left'
38+
? mx < -SWIPE_DISTANCE || (vx > SWIPE_VELOCITY && dx < 0 && mx < 0)
39+
: mx > SWIPE_DISTANCE || (vx > SWIPE_VELOCITY && dx > 0 && mx > 0);
6240

63-
log.log(
64-
`touchend — dx:${dx.toFixed(1)} dy:${dy.toFixed(1)} dt:${dt}ms vel:${velocity.toFixed(3)}`,
65-
`| axisBlocked:${axisBlocked} swipedLeft:${swipedLeft} swipedRight:${swipedRight}`,
66-
`| direction:${direction}`
67-
);
68-
69-
startX.current = null;
70-
startY.current = null;
71-
startTime.current = null;
72-
73-
if (axisBlocked) {
74-
log.log('axis blocked — ignoring (vertical scroll)');
75-
return;
76-
}
77-
78-
if (swipedLeft || swipedRight) {
41+
if (thresholdMet) {
7942
log.log('swipe detected — calling onClose');
8043
onClose();
81-
} else {
82-
log.log('not a swipe — ignoring');
8344
}
8445
},
85-
[settings.mobileGestures, isMobile, direction, onClose]
46+
{
47+
axis: 'x',
48+
filterTaps: true,
49+
pointer: { capture: false },
50+
enabled: gesturesEnabled,
51+
}
8652
);
8753

88-
const handleTouchCancel = useCallback(() => {
89-
startX.current = null;
90-
startY.current = null;
91-
startTime.current = null;
92-
}, []);
93-
9454
return (
9555
<div
96-
onTouchStart={handleTouchStart}
97-
onTouchEnd={handleTouchEnd}
98-
onTouchCancel={handleTouchCancel}
56+
{...(gesturesEnabled ? bind() : {})}
9957
style={{
10058
display: 'flex',
10159
flexDirection: 'column',
10260
flexGrow: 1,
10361
height: '100%',
10462
width: '100%',
63+
touchAction: 'pan-y',
10564
}}
10665
>
10766
{children}

src/app/pages/MobileRoomOverlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useDrag } from '@use-gesture/react';
44
import { useAtomValue } from 'jotai';
55
import { settingsAtom } from '$state/settings';
66
import { mobileOrTablet } from '$utils/user-agent';
7-
import { useBackRoute } from '$components/useBackRoute';
7+
import { useBackRoute } from '$hooks/useBackRoute';
88
import { createLogger } from '$utils/debug';
99

1010
const log = createLogger('MobileRoomOverlay');

src/app/pages/client/direct/Direct.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import { useDirectCreateSelected } from '$hooks/router/useDirectSelected';
6161
import { mobileOrTablet } from '$utils/user-agent';
6262
import { useLastFocusedRoom } from '$hooks/useLastFocusedRooms';
6363
import { SwipeableOverlayWrapper } from '$components/SwipeableOverlayWrapper';
64-
import { BACK_ROOM_PARAM } from '$components/useBackRoute';
64+
import { BACK_ROOM_PARAM } from '$hooks/useBackRoute';
6565
import { createLogger } from '$utils/debug';
6666
import { resolveSwipeTargetRoom } from '$utils/resolveSwipeTargetRoom';
6767
import { useDirectRooms } from './useDirectRooms';

src/app/pages/client/home/Home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ import { RoomSearchParams } from '$pages/paths';
7272
import { mobileOrTablet } from '$utils/user-agent';
7373
import { useLastFocusedRoom } from '$hooks/useLastFocusedRooms';
7474
import { SwipeableOverlayWrapper } from '$components/SwipeableOverlayWrapper';
75-
import { BACK_ROOM_PARAM } from '$components/useBackRoute';
75+
import { BACK_ROOM_PARAM } from '$hooks/useBackRoute';
7676
import { createLogger } from '$utils/debug';
7777
import { resolveSwipeTargetRoom } from '$utils/resolveSwipeTargetRoom';
7878
import { useHomeRooms } from './useHomeRooms';

src/app/pages/client/space/Space.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import { useCallEmbed } from '$hooks/useCallEmbed';
8080
import { mobileOrTablet } from '$utils/user-agent';
8181
import { useLastFocusedRoom } from '$hooks/useLastFocusedRooms';
8282
import { SwipeableOverlayWrapper } from '$components/SwipeableOverlayWrapper';
83-
import { BACK_ROOM_PARAM } from '$components/useBackRoute';
83+
import { BACK_ROOM_PARAM } from '$hooks/useBackRoute';
8484
import { createLogger } from '$utils/debug';
8585
import { resolveSwipeTargetRoom } from '$utils/resolveSwipeTargetRoom';
8686

0 commit comments

Comments
 (0)