diff --git a/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsEvent.java b/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsEvent.java index b69d346..3cede34 100644 --- a/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsEvent.java +++ b/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsEvent.java @@ -10,6 +10,7 @@ import com.facebook.react.modules.core.DeviceEventManagerModule; public class UtilsEvent { final String SCREEN_STATE = "screen-state"; + final String SCREEN_SIZE_CHANGED = "screen-size-changed"; private final ReactApplicationContext reactContext; UtilsEvent(ReactApplicationContext reactContext) { this.reactContext = reactContext; } diff --git a/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsModule.java b/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsModule.java index fdb4f48..7a953ff 100644 --- a/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsModule.java +++ b/android/app/src/main/java/cn/toside/music/mobile/utils/UtilsModule.java @@ -14,6 +14,8 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.util.Log; import android.view.View; +import android.view.ViewTreeObserver; +import android.view.Window; import android.view.WindowManager; import androidx.core.app.LocaleManagerCompat; @@ -346,5 +348,25 @@ public class UtilsModule extends ReactContextBaseJavaModule { // }); // } + @ReactMethod + public void getWindowSize(Promise promise) { + WritableMap params = Arguments.createMap(); + + Activity currentActivity = reactContext.getCurrentActivity(); + if (currentActivity == null) { + params.putInt("width", 0); + params.putInt("height", 0); + promise.resolve(params); + return; + } + // 获取当前应用可用区域大小 + Window window = currentActivity.getWindow(); + View decorView = window.getDecorView(); + int width = decorView.getMeasuredWidth(); + int height = decorView.getMeasuredHeight(); + params.putInt("width", width); + params.putInt("height", height); + promise.resolve(params); + } } diff --git a/publish/changeLog.md b/publish/changeLog.md index 0f70809..7641e3a 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -2,6 +2,7 @@ - 通过歌曲菜单添加不喜欢歌曲时需要二次确认防止手抖 - 减慢歌词详情页歌词滚动速度 +- 更改应用窗口大小获取方式,尝试解决在某些设备上的背景、弹出菜单显示问题 ### 修复 diff --git a/src/app.ts b/src/app.ts index 9ba31da..72b4a0d 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,82 +2,82 @@ import '@/utils/errorHandle' import { init as initLog } from '@/utils/log' import { bootLog, getBootLog } from '@/utils/bootLog' import '@/config/globalData' -import { init as initNavigation, navigations } from '@/navigation' import { getFontSize } from '@/utils/data' import { Alert } from 'react-native' import { exitApp } from './utils/nativeModules/utils' +import { windowSizeTools } from './utils/windowSizeTools' +import { listenLaunchEvent } from './navigation/regLaunchedEvent' console.log('starting app...') -let isInited = false -let handlePushedHomeScreen: () => void | Promise +listenLaunchEvent() -const tryGetBootLog = () => { - try { - return getBootLog() - } catch (err) { - return 'Get boot log failed.' - } -} - -const handleInit = async() => { - if (isInited) return - void initLog() - global.lx.fontSize = await getFontSize() +void Promise.all([getFontSize(), windowSizeTools.init()]).then(async([fontSize]) => { + global.lx.fontSize = fontSize bootLog('Font size setting loaded.') - const { default: init } = await import('@/core/init') - try { - handlePushedHomeScreen = await init() - } catch (err: any) { - Alert.alert('初始化失败 (Init Failed)', `Boot Log:\n${tryGetBootLog()}\n\n${(err.stack ?? err.message) as string}`, [ - { - text: 'Exit', - onPress() { - exitApp() - }, - }, - ], { - cancelable: false, - }) - return + + let isInited = false + let handlePushedHomeScreen: () => void | Promise + + const tryGetBootLog = () => { + try { + return getBootLog() + } catch (err) { + return 'Get boot log failed.' + } } - isInited ||= true -} -initNavigation(async() => { - await handleInit() - if (!isInited) return - // import('@/utils/nativeModules/cryptoTest') - - await navigations.pushHomeScreen().then(() => { - void handlePushedHomeScreen() - }).catch((err: any) => { - Alert.alert('Error', err.message, [ - { - text: 'Exit', - onPress() { - exitApp() + const handleInit = async() => { + if (isInited) return + void initLog() + const { default: init } = await import('@/core/init') + try { + handlePushedHomeScreen = await init() + } catch (err: any) { + Alert.alert('初始化失败 (Init Failed)', `Boot Log:\n${tryGetBootLog()}\n\n${(err.stack ?? err.message) as string}`, [ + { + text: 'Exit', + onPress() { + exitApp() + }, }, - }, - ], { - cancelable: false, + ], { + cancelable: false, + }) + return + } + isInited ||= true + } + const { init: initNavigation, navigations } = await import('@/navigation') + + initNavigation(async() => { + await handleInit() + if (!isInited) return + // import('@/utils/nativeModules/cryptoTest') + + await navigations.pushHomeScreen().then(() => { + void handlePushedHomeScreen() + }).catch((err: any) => { + Alert.alert('Error', err.message, [ + { + text: 'Exit', + onPress() { + exitApp() + }, + }, + ], { + cancelable: false, + }) }) }) +}).catch((err) => { + Alert.alert('初始化失败 (Init Failed)', `Boot Log:\n\n${(err.stack ?? err.message) as string}`, [ + { + text: 'Exit', + onPress() { + exitApp() + }, + }, + ], { + cancelable: false, + }) }) - -// const createProxy = () => { -// return new Proxy(function() {}, { -// get: (_target, prop, receiver) => { -// let propName = prop.toString() -// console.log('proxy get', propName) -// return createProxy() -// }, -// // eslint-disable-next-line @typescript-eslint/promise-function-async -// apply: (target, thisArg, argumentsList) => { -// console.log('proxy apply') -// return '56' -// }, - -// }) -// } -// const proxy = createProxy() -// console.log(proxy.aaa()) diff --git a/src/components/MusicAddModal/List.tsx b/src/components/MusicAddModal/List.tsx index 1389e78..8825d85 100644 --- a/src/components/MusicAddModal/List.tsx +++ b/src/components/MusicAddModal/List.tsx @@ -5,7 +5,7 @@ import Text from '@/components/common/Text' import { useMyList } from '@/store/list/hook' import ListItem, { styles as listStyles } from './ListItem' import CreateUserList from './CreateUserList' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import { useTheme } from '@/store/theme/hook' import { useI18n } from '@/lang' import { createStyle } from '@/utils/tools' @@ -54,14 +54,14 @@ export default ({ musicInfo, onPress }: { musicInfo: LX.Music.MusicInfo onPress: (listInfo: LX.List.MyListInfo) => void }) => { - const { window } = useDimensions() + const windowSize = useWindowSize() const allList = useMyList() const itemWidth = useMemo(() => { - let w = Math.floor(window.width * 0.9 - PADDING) + let w = Math.floor(windowSize.width * 0.9 - PADDING) let n = Math.floor(w / MIN_WIDTH) if (n > 10) n = 10 return Math.floor((w - 1) / n) - }, [window]) + }, [windowSize]) return ( diff --git a/src/components/MusicMultiAddModal/List.tsx b/src/components/MusicMultiAddModal/List.tsx index 63b5954..f422add 100644 --- a/src/components/MusicMultiAddModal/List.tsx +++ b/src/components/MusicMultiAddModal/List.tsx @@ -5,7 +5,7 @@ import Text from '@/components/common/Text' import { useMyList } from '@/store/list/hook' import ListItem, { styles as listStyles } from './ListItem' import CreateUserList from '../MusicAddModal/CreateUserList' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import { useTheme } from '@/store/theme/hook' import { useI18n } from '@/lang' import { createStyle } from '@/utils/tools' @@ -52,14 +52,14 @@ export default ({ listId, onPress }: { listId: string onPress: (listInfo: LX.List.MyListInfo) => void }) => { - const { window } = useDimensions() + const windowSize = useWindowSize() const allList = useMyList().filter(l => l.id != listId) const itemWidth = useMemo(() => { - let w = Math.floor(window.width * 0.9 - PADDING) + let w = Math.floor(windowSize.width * 0.9 - PADDING) let n = Math.floor(w / MIN_WIDTH) if (n > 10) n = 10 return Math.floor((w - 1) / n) - }, [window]) + }, [windowSize]) return ( diff --git a/src/components/PageContent.tsx b/src/components/PageContent.tsx index 3566858..54a3ee0 100644 --- a/src/components/PageContent.tsx +++ b/src/components/PageContent.tsx @@ -1,8 +1,8 @@ -import { useEffect, useState } from 'react' -import { Dimensions, View, type LayoutChangeEvent } from 'react-native' +// import { useEffect, useState } from 'react' +import { View } from 'react-native' import { useTheme } from '@/store/theme/hook' import ImageBackground from '@/components/common/ImageBackground' -// import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' interface Props { children: React.ReactNode @@ -11,31 +11,31 @@ interface Props { export default ({ children }: Props) => { const theme = useTheme() - // const { window } = useDimensions() - const [wh, setWH] = useState<{ width: number | string, height: number | string }>({ width: '100%', height: Dimensions.get('screen').height }) + const windowSize = useWindowSize() + // const [wh, setWH] = useState<{ width: number | string, height: number | string }>({ width: '100%', height: Dimensions.get('screen').height }) // 固定宽高度 防止弹窗键盘时大小改变导致背景被缩放 - useEffect(() => { - const onChange = () => { - setWH({ width: '100%', height: '100%' }) - } + // useEffect(() => { + // const onChange = () => { + // setWH({ width: '100%', height: '100%' }) + // } - const changeEvent = Dimensions.addEventListener('change', onChange) - return () => { - changeEvent.remove() - } - }, []) - const handleLayout = (e: LayoutChangeEvent) => { - // console.log('handleLayout', e.nativeEvent) - // console.log(Dimensions.get('screen')) - setWH({ width: e.nativeEvent.layout.width, height: Dimensions.get('screen').height }) - } + // const changeEvent = Dimensions.addEventListener('change', onChange) + // return () => { + // changeEvent.remove() + // } + // }, []) + // const handleLayout = (e: LayoutChangeEvent) => { + // // console.log('handleLayout', e.nativeEvent) + // // console.log(Dimensions.get('screen')) + // setWH({ width: e.nativeEvent.layout.width, height: Dimensions.get('screen').height }) + // } // console.log('render page content') return ( - + diff --git a/src/components/common/DorpDownPanel/Panel.tsx b/src/components/common/DorpDownPanel/Panel.tsx index ef999e1..445231e 100644 --- a/src/components/common/DorpDownPanel/Panel.tsx +++ b/src/components/common/DorpDownPanel/Panel.tsx @@ -1,6 +1,6 @@ import { useMemo, useRef, useImperativeHandle, forwardRef, useState } from 'react' import { View, TouchableWithoutFeedback } from 'react-native' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Modal, { type ModalType } from '@/components/common/Modal' import { createStyle } from '@/utils/tools' @@ -42,8 +42,8 @@ const Panel = ({ onHide: () => void children: React.ReactNode | React.ReactNode[] }) => { - // const dimensions = useDimensions() - const { window: windowSize } = useDimensions() + // const dimensions = useWindowSize() + const windowSize = useWindowSize() // const theme = useGetter('common', 'theme') // const fadeAnim = useRef(new Animated.Value(0)).current // console.log(buttonPosition) diff --git a/src/components/common/Menu.tsx b/src/components/common/Menu.tsx index 97378e9..16d72ff 100644 --- a/src/components/common/Menu.tsx +++ b/src/components/common/Menu.tsx @@ -1,6 +1,6 @@ import { useImperativeHandle, forwardRef, useMemo, useRef, useState, type Ref } from 'react' import { View, Animated, TouchableHighlight } from 'react-native' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Modal, { type ModalType } from './Modal' @@ -73,7 +73,7 @@ const Menu = ({ center = false, }: Props) => { const theme = useTheme() - const { window: windowSize } = useDimensions() + const windowSize = useWindowSize() // const fadeAnim = useRef(new Animated.Value(0)).current // console.log(buttonPosition) diff --git a/src/components/common/Modal.tsx b/src/components/common/Modal.tsx index b98807d..b972e64 100644 --- a/src/components/common/Modal.tsx +++ b/src/components/common/Modal.tsx @@ -2,7 +2,7 @@ import { useImperativeHandle, forwardRef, useState, useMemo } from 'react' import { Modal, TouchableWithoutFeedback, View, type ModalProps as _ModalProps } from 'react-native' import StatusBar from './StatusBar' -// import { useDimensions } from '@/utils/hooks' +// import { useWindowSize } from '@/utils/hooks' // const styles = createStyle({ // container: { @@ -54,7 +54,7 @@ export default forwardRef(({ ...props }: ModalProps, ref) => { const [visible, setVisible] = useState(false) - // const { window: windowSize } = useDimensions() + // const { window: windowSize } = useWindowSize() const handleRequestClose = () => { if (keyHide) { setVisible(false) diff --git a/src/lang/i18n.ts b/src/lang/i18n.ts index 9050d7f..17c4218 100644 --- a/src/lang/i18n.ts +++ b/src/lang/i18n.ts @@ -51,7 +51,7 @@ const useI18n = () => { }, []) return useCallback((key: keyof Message, val?: TranslateValues): string => { - return i18n.getMessage(key, val) + return i18n?.getMessage(key, val) ?? '' // eslint-disable-next-line react-hooks/exhaustive-deps }, [locale]) } diff --git a/src/navigation/components/ModalContent.tsx b/src/navigation/components/ModalContent.tsx index 3851778..4300a43 100644 --- a/src/navigation/components/ModalContent.tsx +++ b/src/navigation/components/ModalContent.tsx @@ -1,7 +1,7 @@ import { View } from 'react-native' import { useTheme } from '@/store/theme/hook' import { createStyle } from '@/utils/tools' -// import { useDimensions } from '@/utils/hooks' +// import { useWindowSize } from '@/utils/hooks' const HEADER_HEIGHT = 20 interface Props { diff --git a/src/navigation/index.ts b/src/navigation/index.ts index 22b5c59..ff94f92 100644 --- a/src/navigation/index.ts +++ b/src/navigation/index.ts @@ -4,6 +4,7 @@ import * as navigations from './navigation' import registerScreens from './registerScreens' import { removeComponentId } from '@/core/common' +import { onAppLaunched } from './regLaunchedEvent' let unRegisterEvent: ReturnType['registerScreenPoppedListener']> @@ -23,7 +24,7 @@ const init = (callback: () => void | Promise) => { unRegisterEvent = Navigation.events().registerScreenPoppedListener(({ componentId }) => { removeComponentId(componentId) }) - Navigation.events().registerAppLaunchedListener(() => { + onAppLaunched(() => { console.log('Register app launched listener') void callback() }) diff --git a/src/navigation/navigation.ts b/src/navigation/navigation.ts index af8685d..592bfe3 100644 --- a/src/navigation/navigation.ts +++ b/src/navigation/navigation.ts @@ -1,5 +1,5 @@ import { Navigation } from 'react-native-navigation' -import { Dimensions, InteractionManager } from 'react-native' +import { InteractionManager } from 'react-native' import { HOME_SCREEN, @@ -12,6 +12,7 @@ import { import themeState from '@/store/theme/state' import { NAV_SHEAR_NATIVE_IDS } from '@/config/constant' import { getStatusBarStyle } from './utils' +import { windowSizeTools } from '@/utils/windowSizeTools' // const store = getStore() // const getTheme = () => getter('common', 'theme')(store.getState()) @@ -187,7 +188,7 @@ export function pushPlayDetailScreen(componentId: string) { ], // content: { // translationX: { - // from: Dimensions.get('window').width, + // from: windowSizeTools.getSize().width, // to: 0, // duration: 300, // }, @@ -197,7 +198,7 @@ export function pushPlayDetailScreen(componentId: string) { content: { translationX: { from: 0, - to: Dimensions.get('window').width, + to: windowSizeTools.getSize().width, duration: 300, }, }, @@ -371,7 +372,7 @@ export function pushCommentScreen(componentId: string) { push: { content: { translationX: { - from: Dimensions.get('window').width, + from: windowSizeTools.getSize().width, to: 0, duration: 300, }, @@ -381,7 +382,7 @@ export function pushCommentScreen(componentId: string) { content: { translationX: { from: 0, - to: Dimensions.get('window').width, + to: windowSizeTools.getSize().width, duration: 300, }, }, @@ -455,7 +456,7 @@ export function pushCommentScreen(componentId: string) { // push: { // content: { // translationX: { -// from: Dimensions.get('window').width, +// from: windowSizeTools.getSize().width, // to: 0, // duration: 300, // }, @@ -465,7 +466,7 @@ export function pushCommentScreen(componentId: string) { // content: { // translationX: { // from: 0, -// to: Dimensions.get('window').width, +// to: windowSizeTools.getSize().width, // duration: 300, // }, // }, diff --git a/src/navigation/regLaunchedEvent.ts b/src/navigation/regLaunchedEvent.ts new file mode 100644 index 0000000..373f319 --- /dev/null +++ b/src/navigation/regLaunchedEvent.ts @@ -0,0 +1,24 @@ +import { Navigation } from 'react-native-navigation' + +let launched = false +const handlers: Array<() => void> = [] + + +export const listenLaunchEvent = () => { + Navigation.events().registerAppLaunchedListener(() => { + // console.log('Register app launched listener', launched) + launched = true + setImmediate(() => { + for (const handler of handlers) handler() + }) + }) +} + +export const onAppLaunched = (handler: () => void) => { + handlers.push(handler) + if (launched) { + setImmediate(() => { + handler() + }) + } +} diff --git a/src/screens/Home/Views/Leaderboard/index.tsx b/src/screens/Home/Views/Leaderboard/index.tsx index d9c7116..50e307a 100644 --- a/src/screens/Home/Views/Leaderboard/index.tsx +++ b/src/screens/Home/Views/Leaderboard/index.tsx @@ -1,12 +1,12 @@ -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Vertical from './Vertical' import Horizontal from './Horizontal' // import { AppColors } from '@/theme' export default () => { - const { window } = useDimensions() + const windowSize = useWindowSize() - return window.height > window.width + return windowSize.height > windowSize.width ? : } diff --git a/src/screens/Home/Views/Setting/index.tsx b/src/screens/Home/Views/Setting/index.tsx index 94175a1..b61cee8 100644 --- a/src/screens/Home/Views/Setting/index.tsx +++ b/src/screens/Home/Views/Setting/index.tsx @@ -1,4 +1,4 @@ -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Vertical from './Vertical' import Horizontal from './Horizontal' // import { AppColors } from '@/theme' @@ -6,9 +6,9 @@ import Horizontal from './Horizontal' export type { SettingScreenIds } from './Main' export default () => { - const { window } = useDimensions() + const windowSize = useWindowSize() - return window.height > window.width + return windowSize.height > windowSize.width ? : } diff --git a/src/screens/Home/index.tsx b/src/screens/Home/index.tsx index dc43dd3..efa3ec4 100644 --- a/src/screens/Home/index.tsx +++ b/src/screens/Home/index.tsx @@ -1,5 +1,5 @@ import { useEffect } from 'react' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import PageContent from '@/components/PageContent' import { setComponentId } from '@/core/common' import { COMPONENT_IDS } from '@/config/constant' @@ -12,7 +12,7 @@ interface Props { export default ({ componentId }: Props) => { - const { window } = useDimensions() + const windowSize = useWindowSize() useEffect(() => { setComponentId(COMPONENT_IDS.home, componentId) // eslint-disable-next-line react-hooks/exhaustive-deps @@ -21,7 +21,7 @@ export default ({ componentId }: Props) => { return ( { - window.height > window.width + windowSize.height > windowSize.width ? : } diff --git a/src/screens/PlayDetail/Horizontal/Pic.tsx b/src/screens/PlayDetail/Horizontal/Pic.tsx index 7dfb8cf..aa5a43f 100644 --- a/src/screens/PlayDetail/Horizontal/Pic.tsx +++ b/src/screens/PlayDetail/Horizontal/Pic.tsx @@ -5,7 +5,7 @@ import { useTheme } from '@/store/theme/hook' import { BorderRadius } from '@/theme' import Text from '@/components/common/Text' import { usePlayerMusicInfo } from '@/store/player/hook' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import { useNavigationComponentDidAppear } from '@/navigation' import { NAV_SHEAR_NATIVE_IDS } from '@/config/constant' @@ -22,7 +22,7 @@ const EmptyPic = memo(({ width }: { width: number }) => { export default memo(({ componentId }: { componentId: string }) => { const musicInfo = usePlayerMusicInfo() - const { window: { width: winWidth, height: winHeight } } = useDimensions() + const { width: winWidth, height: winHeight } = useWindowSize() const [animated, setAnimated] = useState(false) diff --git a/src/screens/PlayDetail/Vertical/Pic.tsx b/src/screens/PlayDetail/Vertical/Pic.tsx index dfcd7a2..ad9398e 100644 --- a/src/screens/PlayDetail/Vertical/Pic.tsx +++ b/src/screens/PlayDetail/Vertical/Pic.tsx @@ -5,7 +5,7 @@ import { createStyle } from '@/utils/tools' import { usePlayerMusicInfo } from '@/store/player/hook' import { useTheme } from '@/store/theme/hook' import { BorderRadius } from '@/theme' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Text from '@/components/common/Text' import { NAV_SHEAR_NATIVE_IDS } from '@/config/constant' import { useNavigationComponentDidAppear } from '@/navigation' @@ -23,7 +23,7 @@ const EmptyPic = memo(({ width }: { width: number }) => { export default ({ componentId }: { componentId: string }) => { const musicInfo = usePlayerMusicInfo() - const { window } = useDimensions() + const windowSize = useWindowSize() const [animated, setAnimated] = useState(false) @@ -32,7 +32,7 @@ export default ({ componentId }: { componentId: string }) => { }) // console.log('render pic') - const imgWidth = window.width * 0.8 + const imgWidth = windowSize.width * 0.8 return ( diff --git a/src/screens/PlayDetail/index.tsx b/src/screens/PlayDetail/index.tsx index 80804c3..8154ae8 100644 --- a/src/screens/PlayDetail/index.tsx +++ b/src/screens/PlayDetail/index.tsx @@ -1,6 +1,6 @@ import { useEffect } from 'react' // import { View, StyleSheet } from 'react-native' -import { useDimensions } from '@/utils/hooks' +import { useWindowSize } from '@/utils/hooks' import Vertical from './Vertical' import Horizontal from './Horizontal' @@ -10,7 +10,7 @@ import { setComponentId } from '@/core/common' import { COMPONENT_IDS } from '@/config/constant' export default ({ componentId }: { componentId: string }) => { - const { window } = useDimensions() + const windowSize = useWindowSize() useEffect(() => { setComponentId(COMPONENT_IDS.playDetail, componentId) @@ -21,7 +21,7 @@ export default ({ componentId }: { componentId: string }) => { { - window.height > window.width + windowSize.height > windowSize.width ? : } diff --git a/src/utils/hooks/index.js b/src/utils/hooks/index.js index 2719b5f..91469a0 100644 --- a/src/utils/hooks/index.js +++ b/src/utils/hooks/index.js @@ -1,6 +1,6 @@ export { default as useLayout } from './useLayout' export { default as useKeyboard } from './useKeyboard' -export { default as useDimensions } from './useDimensions' +export { default as useWindowSize } from './useWindowSize' export { default as useDeviceOrientation } from './useDeviceOrientation' export { default as usePlayTime } from './usePlayTime' diff --git a/src/utils/hooks/useDeviceOrientation.js b/src/utils/hooks/useDeviceOrientation.js index 71b75d5..9d72d2c 100644 --- a/src/utils/hooks/useDeviceOrientation.js +++ b/src/utils/hooks/useDeviceOrientation.js @@ -1,7 +1,6 @@ import { useEffect, useState, useCallback } from 'react' -import { Dimensions } from 'react-native' +import { windowSizeTools } from '../windowSizeTools' -const screen = Dimensions.get('screen') export default () => { const isOrientationPortrait = ({ @@ -13,20 +12,21 @@ export default () => { height, }) => width >= height + const size = windowSizeTools.getSize() const [orientation, setOrientation] = useState({ - portrait: isOrientationPortrait(screen), - landscape: isOrientationLandscape(screen), + portrait: isOrientationPortrait(size), + landscape: isOrientationLandscape(size), }) - const onChange = useCallback(({ screen: scr }) => { + const onChange = useCallback((size) => { setOrientation({ - portrait: isOrientationPortrait(scr), - landscape: isOrientationLandscape(scr), + portrait: isOrientationPortrait(size), + landscape: isOrientationLandscape(size), }) }, []) useEffect(() => { - const changeEvent = Dimensions.addEventListener('change', onChange) + const changeEvent = windowSizeTools.onSizeChanged(onChange) return () => { changeEvent.remove() diff --git a/src/utils/hooks/useDimensions.js b/src/utils/hooks/useDimensions.js deleted file mode 100644 index 8992ef3..0000000 --- a/src/utils/hooks/useDimensions.js +++ /dev/null @@ -1,21 +0,0 @@ -import { useEffect, useState } from 'react' -import { Dimensions } from 'react-native' -import { getWindowSise } from '@/utils/tools' - -export default () => { - const [dimensions, setDimensions] = useState({ - window: getWindowSise(), - screen: Dimensions.get('screen'), - }) - - useEffect(() => { - const onChange = ({ window, screen }) => { - setDimensions({ window: getWindowSise(window), screen }) - } - - const changeEvent = Dimensions.addEventListener('change', onChange) - return () => changeEvent.remove() - }, []) - - return dimensions -} diff --git a/src/utils/hooks/useWindowSize.ts b/src/utils/hooks/useWindowSize.ts new file mode 100644 index 0000000..2ac16ec --- /dev/null +++ b/src/utils/hooks/useWindowSize.ts @@ -0,0 +1,19 @@ +import { useEffect, useState } from 'react' +import { type SizeHandler, windowSizeTools } from '@/utils/windowSizeTools' + +export default () => { + const [size, setSize] = useState(windowSizeTools.getSize()) + + useEffect(() => { + const onChange: SizeHandler = (size) => { + setSize(size) + } + + const remove = windowSizeTools.onSizeChanged(onChange) + return () => { + remove() + } + }, []) + + return size +} diff --git a/src/utils/nativeModules/utils.ts b/src/utils/nativeModules/utils.ts index 0bf30fa..cd58606 100644 --- a/src/utils/nativeModules/utils.ts +++ b/src/utils/nativeModules/utils.ts @@ -55,3 +55,19 @@ export const onScreenStateChange = (callback: (state: 'ON' | 'OFF') => void): () eventListener.remove() } } + +export const getWindowSize = async(): Promise<{ width: number, height: number }> => { + return UtilsModule.getWindowSize() +} + +export const onWindowSizeChange = (callback: (size: { width: number, height: number }) => void): () => void => { + UtilsModule.listenWindowSizeChanged() + const eventEmitter = new NativeEventEmitter(UtilsModule) + const eventListener = eventEmitter.addListener('screen-size-changed', event => { + callback(event) + }) + + return () => { + eventListener.remove() + } +} diff --git a/src/utils/pixelRatio.ts b/src/utils/pixelRatio.ts index 1c630f6..314f52d 100644 --- a/src/utils/pixelRatio.ts +++ b/src/utils/pixelRatio.ts @@ -5,15 +5,18 @@ * width:375 * height:667 */ -import { Dimensions, PixelRatio } from 'react-native' +import { PixelRatio } from 'react-native' +import { windowSizeTools } from './windowSizeTools' // 高保真的宽度和高度 const designWidth = 375.0 const designHeight = 667.0 // 获取屏幕的dp -let screenW = Dimensions.get('window').width -let screenH = Dimensions.get('window').height +const size = windowSizeTools.getSize() +// console.log('size', size) +let screenW = size.width +let screenH = size.height if (screenW > screenH) { const temp = screenW screenW = screenH diff --git a/src/utils/tools.ts b/src/utils/tools.ts index b4265a1..7980351 100644 --- a/src/utils/tools.ts +++ b/src/utils/tools.ts @@ -29,29 +29,29 @@ export const osVer = Platform.constants.Release as string export const isActive = () => AppState.currentState == 'active' - // fix https://github.com/facebook/react-native/issues/4934 -export const getWindowSise = (windowDimensions?: ReturnType<(typeof Dimensions)['get']>) => { - windowDimensions ??= Dimensions.get('window') - // if (Platform.OS === 'ios') return windowDimensions - return windowDimensions - // const windowSize = { - // width: ExtraDimensions.getRealWindowWidth(), - // height: ExtraDimensions.getRealWindowHeight(), - // } - // if ( - // (windowDimensions.height > windowDimensions.width && windowSize.height < windowSize.width) || - // (windowDimensions.width > windowDimensions.height && windowSize.width < windowSize.height) - // ) { - // windowSize.height = windowSize.width - // } - // windowSize.width = windowDimensions.width +// export const getWindowSise = (windowDimensions?: ReturnType<(typeof Dimensions)['get']>) => { +// return windowSizeTools.getSize() +// // windowDimensions ??= Dimensions.get('window') +// // if (Platform.OS === 'ios') return windowDimensions +// // return windowDimensions +// // const windowSize = { +// // width: ExtraDimensions.getRealWindowWidth(), +// // height: ExtraDimensions.getRealWindowHeight(), +// // } +// // if ( +// // (windowDimensions.height > windowDimensions.width && windowSize.height < windowSize.width) || +// // (windowDimensions.width > windowDimensions.height && windowSize.width < windowSize.height) +// // ) { +// // windowSize.height = windowSize.width +// // } +// // windowSize.width = windowDimensions.width - // if (ExtraDimensions.isSoftMenuBarEnabled()) { - // windowSize.height -= ExtraDimensions.getSoftMenuBarHeight() - // } - // return windowSize -} +// // if (ExtraDimensions.isSoftMenuBarEnabled()) { +// // windowSize.height -= ExtraDimensions.getSoftMenuBarHeight() +// // } +// // return windowSize +// } export const checkStoragePermissions = async() => PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE) diff --git a/src/utils/windowSizeTools.ts b/src/utils/windowSizeTools.ts new file mode 100644 index 0000000..b18e8fa --- /dev/null +++ b/src/utils/windowSizeTools.ts @@ -0,0 +1,48 @@ +import { Dimensions } from 'react-native' +import { getWindowSize } from './nativeModules/utils' + +export type SizeHandler = (size: { width: number, height: number }) => void +export const windowSizeTools = { + size: { + width: 0, + height: 0, + }, + listeners: [] as SizeHandler[], + getSize() { + return this.size + }, + onSizeChanged(handler: SizeHandler) { + this.listeners.push(handler) + + return () => { + this.listeners.splice(this.listeners.indexOf(handler), 1) + } + }, + async init() { + Dimensions.addEventListener('change', () => { + void getWindowSize().then((size) => { + if (!size.width) return + const scale = Dimensions.get('screen').scale + size.width = Math.trunc(size.width / scale) + size.height = Math.trunc(size.height / scale) + this.size = size + for (const handler of this.listeners) handler(size) + }) + }) + const size = await getWindowSize() + if (size.width) { + const scale = Dimensions.get('screen').scale + size.width = Math.trunc(size.width / scale) + size.height = Math.trunc(size.height / scale) + this.size = size + } else { + const window = Dimensions.get('window') + this.size = { + width: window.width, + height: window.height, + } + } + console.log('init windowSizeTools') + return size + }, +}