diff --git a/apps/readest-app/src/app/library/components/BookshelfItem.tsx b/apps/readest-app/src/app/library/components/BookshelfItem.tsx index 8dccc445..c3e90e67 100644 --- a/apps/readest-app/src/app/library/components/BookshelfItem.tsx +++ b/apps/readest-app/src/app/library/components/BookshelfItem.tsx @@ -1,5 +1,5 @@ import clsx from 'clsx'; -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import { useRouter, useSearchParams } from 'next/navigation'; import { navigateToLibrary, navigateToReader, showReaderWindow } from '@/utils/nav'; import { useEnv } from '@/context/EnvContext'; @@ -105,6 +105,8 @@ const BookshelfItem: React.FC = ({ const { settings } = useSettingsStore(); const { updateBook } = useLibraryStore(); + const [keyboardFocused, setKeyboardFocused] = useState(false); + const showBookDetailsModal = useCallback(async (book: Book) => { if (await makeBookAvailable(book)) { handleShowDetailsBook(book); @@ -293,7 +295,7 @@ const BookshelfItem: React.FC = ({ [itemSelected], ); - const { pressing, handlers } = useLongPress( + const { pressing, hasPointerEventsRef, handlers } = useLongPress( { onLongPress: () => { handleSelectItem(); @@ -323,6 +325,16 @@ const BookshelfItem: React.FC = ({ } }; + const handleFocus = () => { + if (!hasPointerEventsRef.current) { + setKeyboardFocused(true); + } + }; + + const handleBlur = () => { + setKeyboardFocused(false); + }; + return (
= ({ 'group', mode === 'grid' && 'sm:hover:bg-base-300/50 flex h-full flex-col px-0 py-4 sm:px-4', mode === 'list' && 'border-base-300 flex flex-col border-b py-2', - 'focus-inset-2', + keyboardFocused && 'focus-inset-2', appService?.isMobileApp && 'no-context-menu', pressing && mode === 'grid' ? 'scale-95' : 'scale-100', )} @@ -341,6 +353,8 @@ const BookshelfItem: React.FC = ({ transition: 'transform 0.2s', }} onKeyDown={handleKeyDown} + onFocus={handleFocus} + onBlur={handleBlur} {...handlers} >
diff --git a/apps/readest-app/src/hooks/useLongPress.ts b/apps/readest-app/src/hooks/useLongPress.ts index f722d3c3..2fa899ec 100644 --- a/apps/readest-app/src/hooks/useLongPress.ts +++ b/apps/readest-app/src/hooks/useLongPress.ts @@ -11,12 +11,14 @@ interface UseLongPressOptions { interface UseLongPressResult { pressing: boolean; + hasPointerEventsRef: React.MutableRefObject; handlers: { onPointerDown: (e: React.PointerEvent) => void; onPointerUp: (e: React.PointerEvent) => void; onPointerMove: (e: React.PointerEvent) => void; onPointerCancel: (e: React.PointerEvent) => void; onPointerLeave: (e: React.PointerEvent) => void; + onClick: (e: React.MouseEvent) => void; onContextMenu: (e: React.MouseEvent) => void; }; } @@ -33,9 +35,11 @@ export const useLongPress = ( deps: React.DependencyList, ): UseLongPressResult => { const [pressing, setPressing] = useState(false); - const timerRef = useRef(); + const timerRef = useRef>(); const startPosRef = useRef<{ x: number; y: number } | null>(null); const pointerId = useRef(null); + const hasPointerEventsRef = useRef(false); + const pointerEventTimeoutRef = useRef>(); const isLongPressTriggered = useRef(false); const reset = useCallback(() => { @@ -52,6 +56,9 @@ export const useLongPress = ( return; } + hasPointerEventsRef.current = true; + clearTimeout(pointerEventTimeoutRef.current); + pointerId.current = e.pointerId; startPosRef.current = { x: e.clientX, y: e.clientY }; isLongPressTriggered.current = false; @@ -97,6 +104,10 @@ export const useLongPress = ( } reset(); + + pointerEventTimeoutRef.current = setTimeout(() => { + hasPointerEventsRef.current = false; + }, 100); }, [onTap, moveThreshold, reset], ); @@ -106,10 +117,20 @@ export const useLongPress = ( if (e.pointerId !== pointerId.current) return; onCancel?.(); reset(); + + pointerEventTimeoutRef.current = setTimeout(() => { + hasPointerEventsRef.current = false; + }, 100); }, [onCancel, reset], ); + const handleClick = useCallback(() => { + if (!hasPointerEventsRef.current) { + onTap?.(); + } + }, [onTap]); + const handleContextMenu = useCallback( (e: React.MouseEvent) => { if (onContextMenu) { @@ -131,12 +152,14 @@ export const useLongPress = ( return { pressing, + hasPointerEventsRef, handlers: { onPointerDown: handlePointerDown, onPointerUp: handlePointerUp, onPointerMove: handlePointerMove, onPointerCancel: handleCancel, onPointerLeave: handleCancel, + onClick: handleClick, onContextMenu: handleContextMenu, }, };