Live video on the AT Protocol
1import { useEffect, useState } from "react";
2import { Platform } from "react-native";
3
4export interface PointerDevice {
5 hasHover: boolean;
6 hasFinePointer: boolean;
7 isMouseDriven: boolean;
8 isTouchDriven: boolean;
9}
10
11/**
12 * Hook to detect if the device is primarily mouse-driven vs touch-driven
13 * Uses CSS media queries to detect hover and pointer capabilities
14 */
15export function usePointerDevice(): PointerDevice {
16 const [pointerDevice, setPointerDevice] = useState<PointerDevice>(() => {
17 // Default values for non-web platforms
18 if (Platform.OS !== "web") {
19 return {
20 hasHover: false,
21 hasFinePointer: false,
22 isMouseDriven: false,
23 isTouchDriven: true,
24 };
25 }
26
27 // Initial web detection
28 if (typeof window !== "undefined" && window.matchMedia) {
29 const hasHover = window.matchMedia("(hover: hover)").matches;
30 const hasFinePointer = window.matchMedia("(pointer: fine)").matches;
31
32 return {
33 hasHover,
34 hasFinePointer,
35 isMouseDriven: hasHover && hasFinePointer,
36 isTouchDriven: !hasHover || !hasFinePointer,
37 };
38 }
39
40 // Fallback for SSR or environments without matchMedia
41 return {
42 hasHover: false,
43 hasFinePointer: false,
44 isMouseDriven: false,
45 isTouchDriven: true,
46 };
47 });
48
49 useEffect(() => {
50 // Only run on web platforms
51 if (
52 Platform.OS !== "web" ||
53 typeof window === "undefined" ||
54 !window.matchMedia
55 ) {
56 return;
57 }
58
59 const hoverQuery = window.matchMedia("(hover: hover)");
60 const pointerQuery = window.matchMedia("(pointer: fine)");
61
62 const updatePointerDevice = () => {
63 const hasHover = hoverQuery.matches;
64 const hasFinePointer = pointerQuery.matches;
65
66 setPointerDevice({
67 hasHover,
68 hasFinePointer,
69 isMouseDriven: hasHover && hasFinePointer,
70 isTouchDriven: !hasHover || !hasFinePointer,
71 });
72 };
73
74 // Set up listeners for media query changes
75 hoverQuery.addEventListener("change", updatePointerDevice);
76 pointerQuery.addEventListener("change", updatePointerDevice);
77
78 // Initial update
79 updatePointerDevice();
80
81 // Cleanup
82 return () => {
83 hoverQuery.removeEventListener("change", updatePointerDevice);
84 pointerQuery.removeEventListener("change", updatePointerDevice);
85 };
86 }, []);
87
88 return pointerDevice;
89}