@applicaster/zapp-react-native-ui-components
Version:
Applicaster Zapp React Native ui components for the Quick Brick App
138 lines (108 loc) • 3.93 kB
text/typescript
import React, { useLayoutEffect } from "react";
import {
allowedOrientationsForScreen,
ORIENTATIONS,
getOrientation,
useGetScreenOrientation,
} from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper";
import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils";
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
import { findPluginByType } from "@applicaster/zapp-react-native-utils/pluginUtils";
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
import { ZappHookModalContext } from "../../Contexts";
import { HookModalContextT } from "../../Contexts/ZappHookModalContext";
/**
* This function calls the native module needed to set orientation
* @param {ORIENTATIONS} orientation desired orientation
*/
function setOrientation(orientation: ORIENTATIONS) {
allowedOrientationsForScreen(orientation);
}
type OrientationHookArgs = {
screenData: {};
};
// Current device orienatation state, can not be inside ref,
// because ref lifetime connected to components (i.e. we lose state)
let current = null;
// Override function we use until player screen will start to provide orientation
// in a generic way as other screens
const getPlayerOrientation = ({ screenData, plugins, screenOrientation }) => {
if (!screenData) {
return null;
}
const isPlayer =
screenData.plugin_type === "player" || screenData.screenType === "playable";
if (!isPlayer) {
return null;
}
if (screenOrientation) {
// Prefer layout screen orientation
return screenOrientation;
}
const player = findPluginByType("player", plugins, {
returnFullObject: true,
});
const playerPluginOrientation = getOrientation(
player?.configuration?.screen_orientation
);
return playerPluginOrientation || ORIENTATIONS.landscapeSensor;
};
export function useNewOrientationForScreenData({
screenData,
}: OrientationHookArgs) {
const isTablet = useIsTablet();
const { appData, plugins } = usePickFromState(["appData", "plugins"]);
const isTabletPortrait = appData?.isTabletPortrait;
const isLandscapeTablet = isTablet && !isTabletPortrait;
const screenOrientation = useGetScreenOrientation(screenData);
current =
current ||
(isLandscapeTablet ? ORIENTATIONS.landscapeSensor : ORIENTATIONS.portrait);
return isLandscapeTablet
? ORIENTATIONS.landscapeSensor
: getPlayerOrientation({ screenData, plugins, screenOrientation }) ||
screenOrientation;
}
type Props = {
screenData: {
screen: {};
};
isActive: boolean;
};
export function useScreenOrientationHandler({ screenData, isActive }: Props) {
const { isHooksExecutionInProgress } = React.useContext<HookModalContextT>(
ZappHookModalContext.ReactContext
);
const prevIsActive = usePrevious(isActive);
const newOrientation = useNewOrientationForScreenData({
screenData: screenData.screen,
});
useLayoutEffect(() => {
// Null means screen does not have orientation preference, so we can skip rotate
if (!newOrientation) {
return;
}
// If modal hook presented we need to skip
// Change orientation for presenter screen
if (isHooksExecutionInProgress) {
return;
}
if (!prevIsActive && isActive && newOrientation !== current) {
current = newOrientation;
setOrientation(newOrientation);
}
}, [newOrientation, isHooksExecutionInProgress, prevIsActive, isActive]);
}
export function useOrientationHandler({ screenData }: OrientationHookArgs) {
const newOrientation = useNewOrientationForScreenData({ screenData });
useLayoutEffect(() => {
// Null means screen does not have orientation preference, so we can skip rotate
if (!newOrientation) {
return;
}
if (newOrientation !== current) {
current = newOrientation;
setOrientation(newOrientation);
}
}, [newOrientation]);
}