1+ import { useCallback , useRef } from "react" ;
2+ import { useSyncExternalStore } from "."
3+ import { DeviceMotionProps } from "../models" ;
4+
5+ const listeners = new Set < ( evt :DeviceMotionEvent ) => void > ( ) ;
6+ const handler = ( evt : DeviceMotionEvent ) => listeners . forEach ( l => l ( evt ) ) ;
7+
8+ /**
9+ * **`useDeviceMotion`**: Hook to handle [device motion](https://developer.mozilla.org/en-US/docs/Web/API/Window/devicemotion_event).
10+ * @returns {DeviceMotionProps } props - device motion properties.
11+ */
12+ export const useDeviceMotion = ( ) : DeviceMotionProps => {
13+ const prev = useRef < DeviceMotionProps > ( {
14+ isSupported : "DeviceMotionEvent" in window ,
15+ acceleration : null ,
16+ accelerationIncludingGravity : null ,
17+ interval : null ,
18+ rotationRate : null
19+ } ) ;
20+ const curr = useRef < DeviceMotionProps > ( ) ;
21+
22+
23+ return useSyncExternalStore (
24+ useCallback ( notif => {
25+ const listener = ( evt : DeviceMotionEvent ) => {
26+ const { acceleration, accelerationIncludingGravity, interval, rotationRate } = evt ;
27+ curr . current = {
28+ isSupported : true ,
29+ acceleration,
30+ accelerationIncludingGravity,
31+ rotationRate,
32+ interval
33+ } ;
34+ notif ( ) ;
35+ } ;
36+ if ( "DeviceMotionEvent" in window ) {
37+ listeners . add ( listener ) ;
38+ listeners . size === 1 && addEventListener ( "devicemotion" , handler ) ;
39+ }
40+ return ( ) => {
41+ if ( "DeviceMotionEvent" in window ) {
42+ listeners . delete ( listener ) ;
43+ listeners . size === 0 && window . removeEventListener ( "devicemotion" , handler )
44+ }
45+ }
46+ } , [ ] ) ,
47+ useCallback ( ( ) => {
48+ if (
49+ curr . current &&
50+ (
51+ prev . current . isSupported !== curr . current . isSupported ||
52+ prev . current . acceleration ?. x !== curr . current . acceleration ?. x ||
53+ prev . current . acceleration ?. y !== curr . current . acceleration ?. y ||
54+ prev . current . acceleration ?. z !== curr . current . acceleration ?. z ||
55+ prev . current . accelerationIncludingGravity ?. x !== curr . current . accelerationIncludingGravity ?. x ||
56+ prev . current . accelerationIncludingGravity ?. y !== curr . current . accelerationIncludingGravity ?. y ||
57+ prev . current . accelerationIncludingGravity ?. z !== curr . current . accelerationIncludingGravity ?. z ||
58+ prev . current . rotationRate ?. alpha !== curr . current . rotationRate ?. alpha ||
59+ prev . current . rotationRate ?. beta !== curr . current . rotationRate ?. beta ||
60+ prev . current . rotationRate ?. gamma !== curr . current . rotationRate ?. gamma ||
61+ prev . current . interval !== curr . current . interval
62+ )
63+ ) {
64+ prev . current = curr . current ;
65+ }
66+ return prev . current ;
67+ } , [ ] )
68+ ) ;
69+ }
0 commit comments