RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/voip/modal/DialPad/hooks/useLongPress.tsx

Summary

Maintainability
A
3 hrs
Test Coverage
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import type { MouseEvent, MouseEventHandler, TouchEvent, TouchEventHandler } from 'react';
import { useRef } from 'react';

type UseLongPressResult = {
    onClick: MouseEventHandler<HTMLButtonElement>;
    onMouseDown: MouseEventHandler<HTMLButtonElement>;
    onMouseUp: MouseEventHandler<HTMLButtonElement>;
    onTouchStart: TouchEventHandler<HTMLButtonElement>;
    onTouchEnd: TouchEventHandler<HTMLButtonElement>;
};

export function useLongPress(
    onLongPress: () => void,
    options?: Partial<UseLongPressResult> & {
        threshold?: number;
    },
): UseLongPressResult {
    const isLongPress = useRef(false);
    const timerRef = useRef<NodeJS.Timeout>();

    const startPressTimer = useMutableCallback((): void => {
        isLongPress.current = false;
        timerRef.current = setTimeout(() => {
            isLongPress.current = true;
            onLongPress();
        }, options?.threshold ?? 700);
    });

    const handleOnClick = useMutableCallback((e: MouseEvent<HTMLButtonElement>): void => {
        if (isLongPress.current || !options?.onClick) {
            return;
        }

        options.onClick(e);
    });

    const handleOnMouseDown = useMutableCallback((e: MouseEvent<HTMLButtonElement>): void => {
        startPressTimer();

        options?.onMouseDown?.(e);
    });

    const handleOnMouseUp = useMutableCallback((e: MouseEvent<HTMLButtonElement>): void => {
        clearTimeout(timerRef.current);

        options?.onMouseUp?.(e);
    });

    const handleOnTouchStart = useMutableCallback((e: TouchEvent<HTMLButtonElement>): void => {
        startPressTimer();

        options?.onTouchStart?.(e);
    });

    const handleOnTouchEnd = useMutableCallback((e: TouchEvent<HTMLButtonElement>): void => {
        clearTimeout(timerRef.current);

        if (options?.onTouchEnd) {
            options.onTouchEnd(e);
        }
    });

    return {
        onClick: handleOnClick,
        onMouseDown: handleOnMouseDown,
        onMouseUp: handleOnMouseUp,
        onTouchStart: handleOnTouchStart,
        onTouchEnd: handleOnTouchEnd,
    };
}