Skip to content

Commit cbb530e

Browse files
committed
fix: rm onPointerDown (#9471)
1 parent 12fd7e6 commit cbb530e

2 files changed

Lines changed: 63 additions & 9 deletions

File tree

packages/vkui/src/components/Touch/Touch.tsx

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,53 @@ import { coordX, coordY, touchEnabled, type VKUITouchEvent } from '../../lib/tou
88
import { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';
99
import type { HasComponent, HasRootRef } from '../../types';
1010

11+
interface EventWithType {
12+
/**
13+
* Тип события.
14+
*/
15+
readonly type: string;
16+
}
17+
18+
function isTouchEvent(event: EventWithType) {
19+
return event.type.startsWith('touch');
20+
}
21+
22+
type CheckEvent = (event: EventWithType) => void;
23+
24+
type IsEventLock = (event: EventWithType) => boolean;
25+
26+
/**
27+
* Телефоны после touch событий могут отправлять события мыши,
28+
* Это может происходить при обычном нажатии.
29+
*
30+
* Нельзя использовать хук во время рендеринга.
31+
*/
32+
function useMouseEventLock(): [IsEventLock, CheckEvent] {
33+
const isMouseEventLockRef = React.useRef<boolean>(false);
34+
const timerRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
35+
36+
const isEventLock: IsEventLock = React.useCallback((event: EventWithType) => {
37+
return !isTouchEvent(event) && isMouseEventLockRef.current === true;
38+
}, []);
39+
40+
const checkEvent: CheckEvent = React.useCallback((event: EventWithType) => {
41+
if (!isTouchEvent(event)) {
42+
return;
43+
}
44+
45+
isMouseEventLockRef.current = true;
46+
47+
clearTimeout(timerRef.current);
48+
timerRef.current = setTimeout(() => {
49+
isMouseEventLockRef.current = false;
50+
}, 1000);
51+
}, []);
52+
53+
React.useEffect(() => () => clearTimeout(timerRef.current), []);
54+
55+
return [isEventLock, checkEvent];
56+
}
57+
1158
/**
1259
* Костыль для правильной работы тайпскрипта.
1360
*/
@@ -236,6 +283,8 @@ export const Touch = ({
236283
const didSlide = React.useRef(false);
237284
const disposeTargetNativeGestureEvents = React.useRef<VoidFunction | null>(null);
238285

286+
const [isEventLock, checkEventForLock] = useMouseEventLock();
287+
239288
const cleanupTargetNativeGestureEvents = () => {
240289
gestureRef.current = null;
241290
if (disposeTargetNativeGestureEvents.current) {
@@ -246,10 +295,6 @@ export const Touch = ({
246295

247296
React.useEffect(() => cleanupTargetNativeGestureEvents, []);
248297

249-
const isTouchEvent = (event: MouseEvent | TouchEvent) => {
250-
return event.type.startsWith('touch');
251-
};
252-
253298
/**
254299
* Note: используем `useStableCallback()`, чтобы не терялась область видимости `onEnd`/`onEndX`/`onEndY`.
255300
*/
@@ -339,6 +384,13 @@ export const Touch = ({
339384
const handlePointerDown = useStableCallback(
340385
(event: React.MouseEvent<HTMLElement> | React.TouchEvent<HTMLElement> | TouchEvent) => {
341386
// Если touchstart сэмулировало mousedown, то заканчиваем обработку
387+
if (isEventLock(event)) {
388+
return;
389+
}
390+
391+
// Помечаем что произошло touch событие
392+
checkEventForLock(event);
393+
342394
if (gestureRef.current !== null) {
343395
return;
344396
}
@@ -465,11 +517,6 @@ export const Touch = ({
465517
// handlePointerDown(onTouchStart устанавливается отдельно через initializeNativeTouchEventStartWithPassiveFalse)
466518
onMouseDownCapture={useCapture ? handlePointerDown : undefined}
467519
onMouseDown={!useCapture ? handlePointerDown : undefined}
468-
onPointerDown={(event: PointerEvent) => {
469-
if (event.pointerType === 'touch' || event.pointerType === 'pen') {
470-
event.preventDefault();
471-
}
472-
}}
473520
/>
474521
);
475522
};

packages/vkui/src/components/View/View.stories.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { Panel } from '../Panel/Panel';
1919
import { PanelHeader } from '../PanelHeader/PanelHeader';
2020
import { PanelHeaderBack } from '../PanelHeaderBack/PanelHeaderBack';
2121
import { Placeholder } from '../Placeholder/Placeholder';
22+
import { WriteBar } from '../WriteBar/WriteBar';
2223
import { View, type ViewProps } from './View';
2324

2425
const story: Meta<ViewProps> = {
@@ -84,6 +85,12 @@ const ProfilePanelContent = ({
8485
))}
8586
</HorizontalScroll>
8687
</Group>
88+
<Group
89+
header={<Header>WriteBar</Header>}
90+
description="Свайпбэк не мешает фокусироваться на элементах форм"
91+
>
92+
<WriteBar />
93+
</Group>
8794
</React.Fragment>
8895
);
8996
};

0 commit comments

Comments
 (0)