mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-21 00:44:41 +08:00
feat: videocard mobile action optimize
This commit is contained in:
153
src/hooks/useLongPress.ts
Normal file
153
src/hooks/useLongPress.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
|
||||
interface UseLongPressOptions {
|
||||
onLongPress: () => void;
|
||||
onClick?: () => void;
|
||||
longPressDelay?: number;
|
||||
moveThreshold?: number;
|
||||
}
|
||||
|
||||
interface TouchPosition {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export const useLongPress = ({
|
||||
onLongPress,
|
||||
onClick,
|
||||
longPressDelay = 500,
|
||||
moveThreshold = 10,
|
||||
}: UseLongPressOptions) => {
|
||||
const isLongPress = useRef(false);
|
||||
const pressTimer = useRef<NodeJS.Timeout | null>(null);
|
||||
const startPosition = useRef<TouchPosition | null>(null);
|
||||
const isActive = useRef(false); // 防止重复触发
|
||||
|
||||
const clearTimer = useCallback(() => {
|
||||
if (pressTimer.current) {
|
||||
clearTimeout(pressTimer.current);
|
||||
pressTimer.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleStart = useCallback(
|
||||
(clientX: number, clientY: number) => {
|
||||
// 如果已经有活跃的手势,忽略新的开始
|
||||
if (isActive.current) return;
|
||||
|
||||
isActive.current = true;
|
||||
isLongPress.current = false;
|
||||
startPosition.current = { x: clientX, y: clientY };
|
||||
|
||||
pressTimer.current = setTimeout(() => {
|
||||
// 再次检查是否仍然活跃
|
||||
if (!isActive.current) return;
|
||||
|
||||
isLongPress.current = true;
|
||||
|
||||
// 添加触觉反馈(如果支持)
|
||||
if (navigator.vibrate) {
|
||||
navigator.vibrate(50);
|
||||
}
|
||||
|
||||
// 触发长按事件
|
||||
onLongPress();
|
||||
}, longPressDelay);
|
||||
},
|
||||
[onLongPress, longPressDelay]
|
||||
);
|
||||
|
||||
const handleMove = useCallback(
|
||||
(clientX: number, clientY: number) => {
|
||||
if (!startPosition.current || !isActive.current) return;
|
||||
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(clientX - startPosition.current.x, 2) +
|
||||
Math.pow(clientY - startPosition.current.y, 2)
|
||||
);
|
||||
|
||||
// 如果移动距离超过阈值,取消长按
|
||||
if (distance > moveThreshold) {
|
||||
clearTimer();
|
||||
isActive.current = false;
|
||||
}
|
||||
},
|
||||
[clearTimer, moveThreshold]
|
||||
);
|
||||
|
||||
const handleEnd = useCallback(() => {
|
||||
clearTimer();
|
||||
|
||||
// 如果不是长按且手势仍然活跃,则触发点击事件
|
||||
if (!isLongPress.current && onClick && isActive.current) {
|
||||
onClick();
|
||||
}
|
||||
|
||||
// 重置所有状态
|
||||
isLongPress.current = false;
|
||||
startPosition.current = null;
|
||||
isActive.current = false;
|
||||
}, [clearTimer, onClick]);
|
||||
|
||||
// 触摸事件处理器
|
||||
const onTouchStart = useCallback(
|
||||
(e: React.TouchEvent) => {
|
||||
// 阻止默认的长按行为,但不阻止触摸开始事件
|
||||
const touch = e.touches[0];
|
||||
handleStart(touch.clientX, touch.clientY);
|
||||
},
|
||||
[handleStart]
|
||||
);
|
||||
|
||||
const onTouchMove = useCallback(
|
||||
(e: React.TouchEvent) => {
|
||||
const touch = e.touches[0];
|
||||
handleMove(touch.clientX, touch.clientY);
|
||||
},
|
||||
[handleMove]
|
||||
);
|
||||
|
||||
const onTouchEnd = useCallback(
|
||||
(e: React.TouchEvent) => {
|
||||
// 始终阻止默认行为,避免任何系统长按菜单
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleEnd();
|
||||
},
|
||||
[handleEnd]
|
||||
);
|
||||
|
||||
// 鼠标事件处理器(用于桌面端测试)
|
||||
const onMouseDown = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
handleStart(e.clientX, e.clientY);
|
||||
},
|
||||
[handleStart]
|
||||
);
|
||||
|
||||
const onMouseMove = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
handleMove(e.clientX, e.clientY);
|
||||
},
|
||||
[handleMove]
|
||||
);
|
||||
|
||||
const onMouseUp = useCallback(() => {
|
||||
handleEnd();
|
||||
}, [handleEnd]);
|
||||
|
||||
const onMouseLeave = useCallback(() => {
|
||||
clearTimer();
|
||||
isActive.current = false;
|
||||
}, [clearTimer]);
|
||||
|
||||
return {
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd,
|
||||
onMouseDown,
|
||||
onMouseMove,
|
||||
onMouseUp,
|
||||
onMouseLeave,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user