Refactor dimension handling
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
90
src/contexts/dimensions.tsx
Normal file
90
src/contexts/dimensions.tsx
Normal 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 };
|
Reference in New Issue
Block a user