Skip to content

Touch devices#1817

Closed
prxt6529 wants to merge 6 commits intomainfrom
touch-devices-fix-24-01
Closed

Touch devices#1817
prxt6529 wants to merge 6 commits intomainfrom
touch-devices-fix-24-01

Conversation

@prxt6529
Copy link
Copy Markdown
Collaborator

@prxt6529 prxt6529 commented Jan 24, 2026

Summary by CodeRabbit

  • New Features
    • Enhanced device detection to better identify when to use touch-optimized UI versus desktop interface. The app now more accurately determines touch device capabilities across various screens and input methods, improving UI responsiveness and interaction patterns on touch and non-touch devices.

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

Signed-off-by: prxt6529 <prxt@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 24, 2026

📝 Walkthrough

Walkthrough

This pull request consolidates touch device detection into useDeviceInfo by introducing a new shouldUseTouchUI boolean field. The deprecated useIsTouchDevice() hook is removed, and all components are migrated to use the new field from useDeviceInfo. Additionally, WaveDropMobileMenu gains text-copy functionality, and all tests are updated to mock the new field.

Changes

Cohort / File(s) Summary
Hook Core Changes
hooks/useDeviceInfo.ts, hooks/useIsTouchDevice.ts
Added shouldUseTouchUI boolean field to DeviceInfo with feature-detection logic via matchMedia; removed deprecated useIsTouchDevice hook entirely
Touch Detection Migration (useIsTouchDevice → useDeviceInfo)
components/brain/left-sidebar/web/WebDirectMessagesList.tsx, components/brain/left-sidebar/web/WebUnifiedWavesListWaves.tsx, components/waves/drops/DropMobileMenuHandler.tsx, components/waves/drops/WaveDrop.tsx, components/waves/drops/WaveDropContent.tsx, components/waves/drops/WaveDropReactions.tsx, components/waves/drops/participation/EndedParticipationDrop.tsx, components/waves/drops/participation/OngoingParticipationDrop.tsx, components/waves/drops/participation/ParticipationDropContent.tsx, components/waves/drops/winner/DefaultWinnerDrop.tsx
Replaced useIsTouchDevice() hook calls with useDeviceInfo() and derived shouldUseTouchUI flag for touch capability detection
Flag Migration (hasTouchScreen → shouldUseTouchUI)
components/brain/left-sidebar/waves/BrainLeftSidebarWave.tsx, components/brain/left-sidebar/web/WebBrainLeftSidebarWave/index.tsx, components/drops/view/item/content/media/MediaDisplayGLB.tsx, components/layout/sidebar/nav/WebSidebarNavItem.tsx, components/memes/drops/MemesLeaderboardDrop.tsx, components/memes/drops/MemesLeaderboardDropCard.tsx, components/providers/LayoutWrapper.tsx, components/utils/tooltip/UserProfileTooltipWrapper.tsx, components/waves/drops/WaveDropPart.tsx, components/waves/gallery/WaveGalleryItem.tsx, components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.tsx, components/waves/leaderboard/gallery/WaveLeaderboardGalleryItem.tsx, components/waves/winners/drops/DefaultWaveWinnerDrop.tsx, components/waves/winners/drops/MemesWaveWinnerDrop.tsx
Replaced hasTouchScreen with shouldUseTouchUI from useDeviceInfo across conditional rendering and class application
New Feature: Text Copy in Mobile Menu
components/waves/drops/WaveDropMobileMenu.tsx
Added extractTextFromDrop() and copyTextToClipboard() helpers to enable copying drop text content; introduces "Copy text" button with transient "Copied!" feedback state
Test File Updates: Mock Extensions
__tests__/FooterWrapper.test.tsx, __tests__/components/header/HeaderSearchModal.test.tsx, __tests__/components/header/HeaderSearchModalItem.test.tsx, __tests__/components/memes/drops/MemesLeaderboardDrop.test.tsx, __tests__/components/navigation/BackButton.test.tsx, __tests__/components/navigation/ViewContext.test.tsx, __tests__/components/network/NetworkPageLayout.test.tsx, __tests__/components/utils/tooltip/UserProfileTooltipWrapper.test.tsx, __tests__/components/waves/drop/SingleWaveDropChat.test.tsx, __tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.interaction.test.tsx, __tests__/components/waves/leaderboard/drops/DefaultWaveLeaderboardDrop.test.tsx, __tests__/components/waves/winners/drops/MemesWaveWinnerDrop.test.tsx, __tests__/contexts/wave/hooks/useActiveWaveManager.test.tsx
Extended useDeviceInfo mocks to include shouldUseTouchUI field across all test files
Test File Updates: Hook Migration
__tests__/components/waves/drops/DropMobileMenuHandler.test.tsx, __tests__/components/waves/drops/WaveDrop.test.tsx, __tests__/components/waves/drops/WaveDropReactions.test.tsx
Migrated mocks from useIsTouchDevice (boolean) to useDeviceInfo (object with shouldUseTouchUI property)
Test File Updates: Complex Refactors
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx, __tests__/components/waves/drops/WaveDropsAll.test.tsx
Added shouldUseTouchUI to DeviceInfo type and MockSetupOptions; refactored UnifiedWavesListWaves mock with container wrapper and useEffect-based sentinel assignment
Test Suite Removals & Extensions
__tests__/hooks/useIsTouchDevice.test.ts (removed), __tests__/hooks/useDeviceInfo.test.ts (extended)
Removed deprecated hook test suite; extended useDeviceInfo tests with new shouldUseTouchUI assertions across multiple pointer/hover detection scenarios

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • #1668: Modifies hooks/useDeviceInfo.ts and its state-update behavior for device detection.
  • #1710: Modifies components/waves/drops/WaveDropMobileMenu.tsx with additional UI features and imports.
  • #1718: Touches WaveDropReactions.tsx and related touch-detection hooks (useIsTouchDeviceuseDeviceInfo).

Suggested reviewers

  • simo6529
  • ragnep

Poem

🐰 Touch detection, now consolidated with care,
shouldUseTouchUI flags everywhere,
Old hooks retire, new logic flows,
From fingers to pointers—the refactoring goes!
Copy buttons hop, with feedback so bright,
A cleaner device-aware codebase in sight. ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Touch devices' is vague and generic, using non-descriptive language that doesn't convey meaningful information about the specific changes in the changeset. Consider a more specific title such as 'Replace hasTouchScreen with shouldUseTouchUI hook' or 'Migrate touch detection to useDeviceInfo' to clearly communicate the main change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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.

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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: 1

Caution

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

⚠️ Outside diff range comments (4)
components/memes/drops/MemesLeaderboardDropCard.tsx (1)

1-38: Add "use client" directive—this component uses the useDeviceInfo hook.

In Next.js App Router, only Client Components can call React hooks. Since useDeviceInfo is a custom hook from a Client Component and MemesLeaderboardDropCard calls it on line 33, the component must be marked as a client component. Without this directive, the build will fail.

Proposed fix
+ "use client";
+
 import type { ReactNode } from "react";
 import React from "react";
 import type { ExtendedDrop } from "@/helpers/waves/drop.helpers";
 import useDeviceInfo from "@/hooks/useDeviceInfo";
__tests__/components/utils/tooltip/UserProfileTooltipWrapper.test.tsx (1)

75-88: Fix the doMock module id to match the component import. The component imports @/hooks/useDeviceInfo (line 4 of UserProfileTooltipWrapper.tsx), and while the relative path ../../../../hooks/useDeviceInfo resolves to the same physical file, Jest matches modules by their identifiers. Since the earlier mock on line 38 uses the alias path, this doMock must also use @/hooks/useDeviceInfo to properly override it.

🧩 Proposed fix
-    jest.doMock('../../../../hooks/useDeviceInfo', () => ({
+    jest.doMock('@/hooks/useDeviceInfo', () => ({
       __esModule: true,
       default: mockUseDeviceInfo,
     }));
__tests__/components/brain/left-sidebar/waves/UnifiedWavesList.test.tsx (1)

73-79: Remove the duplicate shouldUseTouchUI key.

The object literal defines shouldUseTouchUI twice, which is ignored/overwritten and can fail lint. Keep a single entry.

🧹 Proposed fix
     useDeviceInfoMock.mockReturnValue({
       isApp: true,
       isMobileDevice: false,
       hasTouchScreen: false,
       shouldUseTouchUI: false,
-      shouldUseTouchUI: false,
       isAppleMobile: false,
     } as DeviceInfo);
components/waves/drops/WaveDropContent.tsx (1)

1-7: Add "use client" to enable client hooks in this App Router component.

This module calls useDeviceInfo() (a client hook), but lacks a "use client" directive. In Next.js App Router, client hook directives are not inherited through imports—each file using a client hook must declare it explicitly. Without this directive, the build will fail.

Proposed fix
+ "use client";
+
 import React from "react";
 import type { ApiDrop } from "@/generated/models/ApiDrop";
 import WaveDropPart from "./WaveDropPart";
🤖 Fix all issues with AI agents
In `@components/waves/drops/WaveDrop.tsx`:
- Around line 176-179: Replace the mixed detection logic that computes hasTouch
using useIsMobileDevice() and shouldUseTouchUI with a single source of truth
from useDeviceInfo(): remove useIsMobileDevice() and derive hasTouch from the
hasTouchScreen property returned by useDeviceInfo (i.e., const { hasTouchScreen
} = useDeviceInfo(); const hasTouch = hasTouchScreen;), leaving
useCompactMode()/compact unchanged; update any references to shouldUseTouchUI or
isMobile in WaveDrop.tsx to use hasTouchScreen/hasTouch instead.
🧹 Nitpick comments (9)
components/waves/drops/WaveDropMobileMenu.tsx (2)

71-91: Memoize extractTextFromDrop result to avoid repeated computation.

This function is called directly in the render (line 298) on every render cycle. Since it processes drop.parts with multiple regex operations, consider memoizing the result.

♻️ Suggested refactor
- const extractTextFromDrop = (): string => {
+ const extractedText = useMemo(() => {
    if (!drop.parts || drop.parts.length === 0) {
      return "";
    }

    const textParts = drop.parts
      .map((part) => {
        if (!part.content) return "";
        let text = part.content;
        text = text.replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1");
        text = text.replace(/\*\*([^\*]+)\*\*/g, "$1");
        text = text.replace(/\*([^\*]+)\*/g, "$1");
        text = text.replace(/`([^`]+)`/g, "$1");
        text = text.replace(/#{1,6}\s+/g, "");
        text = text.replace(/\n{3,}/g, "\n\n");
        return text.trim();
      })
      .filter((text) => text.length > 0);

    return textParts.join("\n\n");
- };
+ }, [drop.parts]);

Then update usages:

  • Line 97-98: const text = extractedText; if (!text) return;
  • Line 298: {extractedText && (

100-104: Add error handling for clipboard write failure.

The promise rejection from writeText() is not handled. If clipboard access is denied or fails, the user gets no feedback.

♻️ Suggested fix
    if (navigator?.clipboard?.writeText) {
-     navigator.clipboard.writeText(text).then(() => {
-       setCopiedText(true);
-       setTimeout(() => setCopiedText(false), 2000);
-     });
+     navigator.clipboard.writeText(text)
+       .then(() => {
+         setCopiedText(true);
+         setTimeout(() => setCopiedText(false), 2000);
+       })
+       .catch(() => {
+         // Fallback on failure
+         fallbackCopyToClipboard(text);
+       });
    }

Note: The existing copyToClipboard function has the same pattern. Consider addressing both together if you refactor.

components/waves/drops/participation/ParticipationDropContent.tsx (1)

27-28: Consider removing the redundant intermediate variable.

The assignment const hasTouch = shouldUseTouchUI; creates an unnecessary alias. You could either destructure with a rename or use shouldUseTouchUI directly.

♻️ Suggested simplification
-  const { shouldUseTouchUI } = useDeviceInfo();
-  const hasTouch = shouldUseTouchUI;
+  const { shouldUseTouchUI: hasTouch } = useDeviceInfo();
components/waves/drops/ArtistSubmissionBadge.tsx (2)

39-40: Redundant condition – inconsistent with other components.

The !isMobile && !shouldUseTouchUI check appears redundant. shouldUseTouchUI should already account for mobile scenarios. Other components in this PR (e.g., WebSidebarNavItem) use only !shouldUseTouchUI for the same tooltip-hiding logic.

Consider simplifying for consistency:

♻️ Suggested simplification
-  const isMobile = useIsMobileDevice();
   const { shouldUseTouchUI } = useDeviceInfo();
   const id = useId();
   const uniqueTooltipId = `${tooltipId}-${id}`;
   const [isTooltipOpen, setIsTooltipOpen] = React.useState(false);

   if (submissionCount === 0) return null;

   const dataTooltipId =
-    !isMobile && !shouldUseTouchUI ? uniqueTooltipId : undefined;
+    !shouldUseTouchUI ? uniqueTooltipId : undefined;

And similarly on line 77:

-      {!isMobile && !shouldUseTouchUI && (
+      {!shouldUseTouchUI && (

If there's a specific edge case requiring both checks, please document it with a comment.


7-8: Remove unused import if isMobile check is eliminated.

If you simplify the tooltip conditions to use only shouldUseTouchUI, the useIsMobileDevice import on line 7 can be removed.

__tests__/components/waves/drops/WaveDropsAll.test.tsx (1)

38-46: Consider adding shouldUseTouchUI to the base mock for consistency.

The base mock at lines 38-46 doesn't include shouldUseTouchUI, while setupMocks() (line 262) does provide it. Since beforeEach calls setupMocks(), this works in practice, but adding the field to the base mock would improve consistency and prevent subtle issues if tests are added that don't use setupMocks().

Suggested fix
 jest.mock('@/hooks/useDeviceInfo', () => ({
   __esModule: true,
   default: jest.fn(() => ({
     isAppleMobile: false,
     isMobileDevice: false,
     hasTouchScreen: false,
+    shouldUseTouchUI: false,
     isApp: false
   }))
 }));
__tests__/components/waves/drops/WaveDropReactions.test.tsx (1)

347-382: Consider removing the redundant mock reset at line 381.

The mock reset at line 381 is unnecessary since beforeEach already calls jest.clearAllMocks() and the base mock defaults to shouldUseTouchUI: false. This cleanup is harmless but adds noise.

Suggested cleanup
     const reactionButton = screen.getAllByRole("button")[0];
     expect(reactionButton).toBeInTheDocument();
-
-    mockUseDeviceInfo.mockReturnValue({ shouldUseTouchUI: false });
   });
components/waves/drops/participation/OngoingParticipationDrop.tsx (1)

43-45: Consolidate device hooks for better detection logic.

The component uses both useIsMobileDevice() and useDeviceInfo(), but useDeviceInfo already provides isMobileDevice with more comprehensive detection (including modern userAgentData API and Capacitor app handling). Consolidate them into a single hook call:

Suggested consolidation
- const isMobile = useIsMobileDevice();
- const { shouldUseTouchUI } = useDeviceInfo();
+ const { shouldUseTouchUI, isMobileDevice: isMobile } = useDeviceInfo();

This eliminates the redundant hook and improves detection accuracy by using the more sophisticated device identification logic.

components/waves/drops/winner/DefaultWinnerDrop.tsx (1)

6-8: Consolidate mobile/touch detection into a single hook.

You’re now calling two device hooks, which can diverge. useDeviceInfo already exposes isMobileDevice, so you can avoid duplicate detection and keep a single source of truth.

♻️ Suggested refactor
-import useIsMobileDevice from "@/hooks/isMobileDevice";
 import useDeviceInfo from "@/hooks/useDeviceInfo";
@@
-  const isMobile = useIsMobileDevice();
-  const { shouldUseTouchUI } = useDeviceInfo();
-  const hasTouch = shouldUseTouchUI || isMobile;
+  const { shouldUseTouchUI, isMobileDevice } = useDeviceInfo();
+  const hasTouch = shouldUseTouchUI || isMobileDevice;
@@
-        {!isMobile && showReplyAndQuote && (
+        {!isMobileDevice && showReplyAndQuote && (

Also applies to: 108-110, 237-237

Comment on lines 176 to 179
const isMobile = useIsMobileDevice();
const hasTouch = useIsTouchDevice() || isMobile;
const { shouldUseTouchUI } = useDeviceInfo();
const hasTouch = shouldUseTouchUI || isMobile;
const compact = useCompactMode();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find the hooks and their implementations
find . -type f \( -name "*.ts" -o -name "*.tsx" \) | xargs grep -l "useIsMobileDevice\|useDeviceInfo" | head -20

Repository: 6529-Collections/6529seize-frontend

Length of output: 1628


🏁 Script executed:

# Search for hook definitions
rg "export.*useIsMobileDevice|export.*useDeviceInfo" -t tsx -t ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 106


🏁 Script executed:

# Also check for the file structure
fd -t f -e ts -e tsx | grep -i "hook\|device" | head -20

Repository: 6529-Collections/6529seize-frontend

Length of output: 625


🏁 Script executed:

# Find the exact hook implementations
rg "useIsMobileDevice|useDeviceInfo" --type-list | head -5

Repository: 6529-Collections/6529seize-frontend

Length of output: 468


🏁 Script executed:

# Search more broadly for these hooks
rg "useIsMobileDevice|useDeviceInfo" -g "*.ts" -g "*.tsx" -l

Repository: 6529-Collections/6529seize-frontend

Length of output: 7722


🏁 Script executed:

# Check the WaveDrop.tsx file to understand context
cat -n components/waves/drops/WaveDrop.tsx | sed -n '170,190p'

Repository: 6529-Collections/6529seize-frontend

Length of output: 931


🏁 Script executed:

# Examine the useDeviceInfo implementation
cat -n hooks/useDeviceInfo.ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 5107


🏁 Script executed:

# Examine the isMobileDevice implementation
cat -n hooks/isMobileDevice.ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 674


🏁 Script executed:

# Check how hasTouch is used in WaveDrop.tsx
rg "hasTouch" components/waves/drops/WaveDrop.tsx -B 2 -A 2

Repository: 6529-Collections/6529seize-frontend

Length of output: 1330


🏁 Script executed:

# Check if there are any viewport/media query listeners in useIsMobileDevice or if it updates on resize
rg "matchMedia|resize|viewport" hooks/isMobileDevice.ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 61


🏁 Script executed:

# Verify how hasTouch is actually used - check for touch event listeners
rg "onTouchStart|onTouchEnd|@media|matchMedia" components/waves/drops/WaveDrop.tsx -A 2

Repository: 6529-Collections/6529seize-frontend

Length of output: 200


🏁 Script executed:

# Check if there are tests that clarify the intended behavior
cat -n __tests__/hooks/useIsMobileDevice.test.ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 1093


🏁 Script executed:

# Double-check if useIsMobileDevice is updated on any browser events
grep -r "useIsMobileDevice" hooks/ -A 15 -B 2

Repository: 6529-Collections/6529seize-frontend

Length of output: 917


🏁 Script executed:

# Verify the actual touch event handlers and their guards
cat -n components/waves/drops/WaveDrop.tsx | sed -n '195,225p'

Repository: 6529-Collections/6529seize-frontend

Length of output: 1257


🏁 Script executed:

# Check if useIsMobileDevice updates on window resize or any other event
rg "isMobile|setIsMobile" hooks/isMobileDevice.ts

Repository: 6529-Collections/6529seize-frontend

Length of output: 173


🏁 Script executed:

# Verify the actual full implementation of useDeviceInfo's shouldUseTouchUI logic more carefully
cat -n hooks/useDeviceInfo.ts | sed -n '50,70p'

Repository: 6529-Collections/6529seize-frontend

Length of output: 1106


🏁 Script executed:

# Check if there are any other references to useIsMobileDevice to see if it's used elsewhere for touch detection
rg "hasTouch|useIsMobileDevice.*touch|isMobile.*touch" components/ -B 2 -A 2 | head -50

Repository: 6529-Collections/6529seize-frontend

Length of output: 3644


🏁 Script executed:

# Check the useDeviceInfo test to see if it clarifies the intended behavior
cat -n __tests__/hooks/useDeviceInfo.test.ts | head -100

Repository: 6529-Collections/6529seize-frontend

Length of output: 5151


🏁 Script executed:

# Check if there are other usages of hasTouch = shouldUseTouchUI || isMobile pattern
rg "hasTouch.*shouldUseTouchUI.*isMobile|shouldUseTouchUI.*isMobile" -B 2 -A 2

Repository: 6529-Collections/6529seize-frontend

Length of output: 8932


🏁 Script executed:

# Look at similar components that use touch detection to see the pattern
cat -n components/waves/winners/drops/DefaultWaveWinnerDrop.tsx | sed -n '1,50p'

Repository: 6529-Collections/6529seize-frontend

Length of output: 3135


Use hasTouchScreen instead of mixing isMobile with shouldUseTouchUI.

The useIsMobileDevice hook detects only the user agent and doesn't respond to viewport changes. However, combining it with shouldUseTouchUI mixes two different detection strategies. For consistency and accuracy, derive hasTouch solely from useDeviceInfo using hasTouchScreen, which is based on actual touch capability (maxTouchPoints + runtime touch event detection) rather than user agent alone.

Suggested change
-  const isMobile = useIsMobileDevice();
-  const { shouldUseTouchUI } = useDeviceInfo();
-  const hasTouch = shouldUseTouchUI || isMobile;
+  const { hasTouchScreen } = useDeviceInfo();
+  const hasTouch = hasTouchScreen;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isMobile = useIsMobileDevice();
const hasTouch = useIsTouchDevice() || isMobile;
const { shouldUseTouchUI } = useDeviceInfo();
const hasTouch = shouldUseTouchUI || isMobile;
const compact = useCompactMode();
const { hasTouchScreen } = useDeviceInfo();
const hasTouch = hasTouchScreen;
const compact = useCompactMode();
🤖 Prompt for AI Agents
In `@components/waves/drops/WaveDrop.tsx` around lines 176 - 179, Replace the
mixed detection logic that computes hasTouch using useIsMobileDevice() and
shouldUseTouchUI with a single source of truth from useDeviceInfo(): remove
useIsMobileDevice() and derive hasTouch from the hasTouchScreen property
returned by useDeviceInfo (i.e., const { hasTouchScreen } = useDeviceInfo();
const hasTouch = hasTouchScreen;), leaving useCompactMode()/compact unchanged;
update any references to shouldUseTouchUI or isMobile in WaveDrop.tsx to use
hasTouchScreen/hasTouch instead.

Signed-off-by: prxt6529 <prxt@6529.io>
Signed-off-by: prxt6529 <prxt@6529.io>
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)
hooks/useDeviceInfo.ts (1)

45-72: shouldUseTouchUI ignores userAgentData.mobile, creating inconsistency with isMobileDevice on UA-reduced browsers.

On modern browsers that reduce the UA string, the classic UA regex may fail to detect mobile devices while userAgentData.mobile correctly identifies them. This causes shouldUseTouchUI to be false while isMobileDevice is true—an inconsistency that impacts touch UI logic. Consolidate mobile detection to use userAgentData.mobile as the primary source, consistent with how isMobileDevice is calculated.

🔧 Suggested fix
-      let shouldUseTouchUI = false;
-      if (!(hasFinePointer || hasHover) && maxTouchPoints > 0) {
-        const ua = nav.userAgent ?? "";
-        const isMobileUA = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
-        shouldUseTouchUI = isMobileUA;
-      }
-
-      const ua = nav.userAgent;
-      const uaDataMobile = nav.userAgentData?.mobile;
+      const ua = nav.userAgent ?? "";
+      const uaDataMobile = nav.userAgentData?.mobile;
+      const isMobileUA =
+        uaDataMobile ??
+        /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
+
+      let shouldUseTouchUI = false;
+      if (!(hasFinePointer || hasHover) && maxTouchPoints > 0) {
+        shouldUseTouchUI = isMobileUA;
+      }

Signed-off-by: prxt6529 <prxt@6529.io>
@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot

See analysis details on SonarQube Cloud

@prxt6529 prxt6529 closed this Feb 26, 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.

1 participant