Skip to content

ipad long press fix#1766

Merged
simo6529 merged 1 commit intomainfrom
simo6529/ipad-longpress
Jan 20, 2026
Merged

ipad long press fix#1766
simo6529 merged 1 commit intomainfrom
simo6529/ipad-longpress

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Jan 20, 2026

Summary by CodeRabbit

  • New Features

    • Enhanced touch device detection and gesture support across wave components
    • Improved long-press, touch start, and swipe event handling for better mobile interactions
  • Bug Fixes

    • Refined distinction between mobile-only and touch-capable devices for accurate gesture handling
  • Tests

    • Standardized formatting, quote usage, and test prop configuration for consistency

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Simo <simo@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 20, 2026

📝 Walkthrough

Walkthrough

Touch-device detection is unified across the wave drop component hierarchy by introducing a hasTouch flag that combines mobile status with touch device capability. This flag is imported via useIsTouchDevice hook, computed in parent components, and propagated down to child components as an optional prop to consistently gate touch-dependent behaviors like long-press handling.

Changes

Cohort / File(s) Summary
Test Suite
__tests__/components/waves/drops/WaveDropPart.test.tsx
Standardized all quotes to double quotes for consistency; added hasTouch: true to defaultProps to align with new touch-awareness prop requirements. No semantic logic changes.
Drop Handlers
components/waves/drops/DropMobileMenuHandler.tsx
Integrated useIsTouchDevice hook; replaced isMobile checks with combined hasTouch flag in long-press and touch handlers. Updated touch start/move/cancel event guards to respect hasTouch state; refined movement threshold logic to check timeout existence.
Core Drop Components
components/waves/drops/WaveDrop.tsx, components/waves/drops/WaveDropContent.tsx, components/waves/drops/WaveDropPart.tsx
Introduced useIsTouchDevice hook across components; added hasTouch prop to propagate touch capability through the component tree. Replaced mobile-only checks with unified hasTouch flag in long-press and touch-start logic; updated dependency arrays and effect triggers. Removed local state derivation for activePart in WaveDropPart.
Participation Drops
components/waves/drops/participation/EndedParticipationDrop.tsx, components/waves/drops/participation/OngoingParticipationDrop.tsx, components/waves/drops/participation/ParticipationDropContent.tsx
Added useIsTouchDevice hook and computed hasTouch in parent components; propagated flag to child components. Refined long-press guards to use hasTouch. Introduced background styling logic in EndedParticipationDrop via getDropLocationBackground and consolidated class application. Updated hook dependencies and minor class ordering.
Winner Drop
components/waves/drops/winner/DefaultWinnerDrop.tsx
Imported useIsTouchDevice and computed hasTouch; refactored rank color conditional logic from chained else-if to separate statements. Added background color selection logic; replaced inline className construction with bgColorClass variable. Updated long-press guard to use hasTouch; propagated hasTouch prop to WaveDropContent. Minor className reordering and wave link route refinement.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #1718: Both PRs modify touch-detection and long-press handling in the waves/drops area using useIsTouchDevice hook to gate interactive behaviors.
  • PR #1715: Both PRs refactor touch/gesture handling in WaveDrop.tsx components to improve touch-device awareness and event handling.

Suggested reviewers

  • prxt6529
  • ragnep

Poem

🐰 A touch-aware whisker twitch,
Fingers now the drop can catch,
Mobile, touch, or screen so wide—
The waves know where to ride,
boing! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ipad long press fix' is partially related to the changeset but does not capture the main architectural change of introducing comprehensive touch device detection beyond just iPad.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jan 20, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
3.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/waves/drops/participation/ParticipationDropContent.tsx (1)

4-41: Add an optional hasTouch prop to avoid a TS prop mismatch.
OngoingParticipationDrop now passes hasTouch, but ParticipationDropContentProps doesn’t accept it, which will fail type-checking and ignore the parent-derived value. Accept it and prefer hasTouch ?? useIsTouchDevice().

🐛 Proposed fix
 interface ParticipationDropContentProps {
   readonly drop: ExtendedDrop;
   readonly activePartIndex: number;
   readonly setActivePartIndex: (index: number) => void;
   readonly onLongPress: () => void;
   readonly onDropContentClick?: ((drop: ExtendedDrop) => void) | undefined;
   readonly onQuoteClick: (drop: ApiDrop) => void;
   readonly setLongPressTriggered: (triggered: boolean) => void;
   readonly isCompetitionDrop?: boolean | undefined;
+  readonly hasTouch?: boolean | undefined;
 }

 export default function ParticipationDropContent({
   drop,
   activePartIndex,
   setActivePartIndex,
   onLongPress,
   onDropContentClick,
   onQuoteClick,
   setLongPressTriggered,
   isCompetitionDrop = false,
+  hasTouch,
 }: ParticipationDropContentProps) {
-  const hasTouch = useIsTouchDevice();
+  const isTouchDevice = useIsTouchDevice();
+  const effectiveHasTouch = hasTouch ?? isTouchDevice;

   return (
     <div className="tw-mt-1">
       <WaveDropContent
         drop={drop}
         activePartIndex={activePartIndex}
         setActivePartIndex={setActivePartIndex}
         onLongPress={onLongPress}
         onDropContentClick={onDropContentClick}
         onQuoteClick={onQuoteClick}
         setLongPressTriggered={setLongPressTriggered}
         isCompetitionDrop={isCompetitionDrop}
-        hasTouch={hasTouch}
+        hasTouch={effectiveHasTouch}
       />
     </div>
   );
 }
🧹 Nitpick comments (1)
__tests__/components/waves/drops/WaveDropPart.test.tsx (1)

82-84: Consider adding test coverage for hasTouch: false.

The default props now include hasTouch: true, which is appropriate for testing touch behaviors. However, there's no test coverage verifying that long press handling is disabled when hasTouch is false. This would ensure the component correctly gates touch-specific behaviors on non-touch devices.

Example test to add
it("does not trigger long press when hasTouch is false", () => {
  render(<WaveDropPart {...defaultProps} hasTouch={false} />);

  const containers = screen.getAllByRole("button");
  const container = containers.find((el) =>
    el.className.includes("tw-cursor-pointer")
  )!;

  fireEvent.touchStart(container, {
    touches: [{ clientX: 100, clientY: 100 }],
  });

  act(() => {
    jest.advanceTimersByTime(500);
  });

  expect(mockSetLongPressTriggered).not.toHaveBeenCalledWith(true);
  expect(mockOnLongPress).not.toHaveBeenCalled();
});

@simo6529 simo6529 merged commit f48557a into main Jan 20, 2026
6 of 7 checks passed
@simo6529 simo6529 deleted the simo6529/ipad-longpress branch January 20, 2026 11:03
This was referenced Jan 28, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Feb 9, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants