From 8733af871b2a694e92d676c127664d7c3ce34b94 Mon Sep 17 00:00:00 2001 From: Botzy Date: Tue, 25 Feb 2025 13:57:50 +0200 Subject: [PATCH] fix(BottomSheet): close BottomSheet on orientation change --- src/common/index.js | 4 +- src/common/useOrientation.ts | 63 ++++++++++++++++++++++ src/common/useWindowSize.js | 18 ------- src/components/BottomSheet/BottomSheet.tsx | 6 +-- 4 files changed, 68 insertions(+), 23 deletions(-) create mode 100644 src/common/useOrientation.ts delete mode 100644 src/common/useWindowSize.js diff --git a/src/common/index.js b/src/common/index.js index ab3723cd0..82f7a6a0c 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -24,7 +24,7 @@ const { default: useShell } = require('./useShell'); const useStreamingServer = require('./useStreamingServer'); const useTorrent = require('./useTorrent'); const useTranslate = require('./useTranslate'); -const useWindowSize = require('./useWindowSize'); +const { default: useOrientation } = require('./useOrientation'); module.exports = { FileDropProvider, @@ -56,5 +56,5 @@ module.exports = { useStreamingServer, useTorrent, useTranslate, - useWindowSize, + useOrientation, }; diff --git a/src/common/useOrientation.ts b/src/common/useOrientation.ts new file mode 100644 index 000000000..b92c7b394 --- /dev/null +++ b/src/common/useOrientation.ts @@ -0,0 +1,63 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import { useState, useEffect } from 'react'; + +type DeviceOrientationData = { + alpha: number | null; + beta: number | null; + gamma: number | null; + absolute: boolean | null; + permissionGranted: boolean; +}; + +const useOrientation = () => { + const [orientation, setOrientation] = useState({ + alpha: null, + beta: null, + gamma: null, + absolute: null, + permissionGranted: false, + }); + + const requestPermission = async () => { + if ( + typeof DeviceOrientationEvent !== 'undefined' && + (DeviceOrientationEvent as any).requestPermission + ) { + try { + const permissionState = await (DeviceOrientationEvent as any).requestPermission(); + if (permissionState === 'granted') { + setOrientation((prev) => ({ ...prev, permissionGranted: true })); + } + } catch (error) { + console.error('Error requesting DeviceOrientation permission:', error); + } + } else { + setOrientation((prev) => ({ ...prev, permissionGranted: true })); + } + }; + + useEffect(() => { + const handleOrientationChange = (event: DeviceOrientationEvent) => { + setOrientation((prev) => ({ + ...prev, + alpha: event.alpha ?? null, + beta: event.beta ?? null, + gamma: event.gamma ?? null, + absolute: event.absolute ?? null, + })); + }; + + if (orientation.permissionGranted && window.DeviceOrientationEvent) { + window.addEventListener('deviceorientation', handleOrientationChange); + } + + return () => { + window.removeEventListener('deviceorientation', handleOrientationChange); + }; + }, [orientation.permissionGranted]); + + return { ...orientation, requestPermission }; +}; + +export default useOrientation; diff --git a/src/common/useWindowSize.js b/src/common/useWindowSize.js deleted file mode 100644 index 9f7285261..000000000 --- a/src/common/useWindowSize.js +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (C) 2017-2025 Smart code 203358507 - -const { useState, useEffect } = require('react'); - -const useWindowSize = () => { - const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight }); - - useEffect(() => { - const handleResize = () => setSize({ width: window.innerWidth, height: window.innerHeight }); - - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); - }, []); - - return size; -}; - -module.exports = useWindowSize; diff --git a/src/components/BottomSheet/BottomSheet.tsx b/src/components/BottomSheet/BottomSheet.tsx index 28e2f631a..d7dfe7130 100644 --- a/src/components/BottomSheet/BottomSheet.tsx +++ b/src/components/BottomSheet/BottomSheet.tsx @@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { createPortal } from 'react-dom'; import classNames from 'classnames'; import useBinaryState from 'stremio/common/useBinaryState'; -import useWindowSize from 'stremio/common/useWindowSize'; +import useOrientation from 'stremio/common/useOrientation'; import styles from './BottomSheet.less'; const CLOSE_THRESHOLD = 100; @@ -18,7 +18,7 @@ type Props = { const BottomSheet = ({ children, title, show, onClose }: Props) => { const containerRef = useRef(null); - const { width: windowWidth, height: windowHeight } = useWindowSize(); + const orientation = useOrientation(); const [startOffset, setStartOffset] = useState(0); const [offset, setOffset] = useState(0); @@ -62,7 +62,7 @@ const BottomSheet = ({ children, title, show, onClose }: Props) => { useEffect(() => { opened && close(); - }, [windowWidth, windowHeight]); + }, [orientation]); return opened && createPortal((