Refactor dimension handling

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-07-13 19:03:53 +03:00
parent 703155232d
commit 4128b0df20
17 changed files with 406 additions and 250 deletions

View File

@@ -0,0 +1,90 @@
import React, {
ReactNode,
createContext,
useContext,
useEffect,
useState,
} from 'react';
import { Dimensions, ScaledSize } from 'react-native';
const guidelineBaseWidth = 350;
const guidelineBaseHeight = 680;
interface ScaleFunctions {
horizontalScale: (size: number) => number;
verticalScale: (size: number) => number;
moderateScale: (size: number, factor?: number) => number;
}
interface DimensionsContext {
orientation: 'portrait' | 'landscape';
responsive: ScaleFunctions;
static: ScaleFunctions;
}
const createScaleFunctions = (dimensionsIn: ScaledSize) => {
const horizontalScale = (size: number) =>
(dimensionsIn.width / guidelineBaseWidth) * size;
const verticalScale = (size: number) =>
(dimensionsIn.height / guidelineBaseHeight) * size;
const moderateScale = (size: number, factor = 0.5) =>
size + (horizontalScale(size) - size) * factor;
return { horizontalScale, verticalScale, moderateScale };
};
const DimensionsContext = createContext<DimensionsContext | undefined>(
undefined,
);
const DimensionsProvider = ({ children }: { children: ReactNode }) => {
const [dimensions, setDimensions] = useState(Dimensions.get('window'));
const orientation =
dimensions.width > dimensions.height ? 'landscape' : 'portrait';
const [initialDimensions, setInitialDimensions] = useState(dimensions);
const [initialOrientation] = useState(orientation);
if (initialOrientation === 'landscape') {
setInitialDimensions({
width: initialDimensions.height,
height: initialDimensions.width,
} as ScaledSize);
}
const responsiveScale = createScaleFunctions(dimensions);
const staticScale = createScaleFunctions(initialDimensions);
useEffect(() => {
const onChange = ({ window }: { window: ScaledSize }) => {
setDimensions(window);
};
const subscription = Dimensions.addEventListener('change', onChange);
return () => {
subscription.remove();
};
}, []);
return (
<DimensionsContext.Provider
value={{
orientation,
responsive: responsiveScale,
static: staticScale,
}}>
{children}
</DimensionsContext.Provider>
);
};
const useDimensions = (): DimensionsContext => {
const context = useContext(DimensionsContext);
if (!context) {
throw new Error('useDimensions must be used within a DimensionsProvider');
}
return context;
};
export { DimensionsProvider, useDimensions };