import React, { Ref, useContext, useEffect, useRef } from 'react'; import LinearGradient from 'react-native-linear-gradient'; import { ApplicationContext, MiniAppContext } from '../../Context'; import { Animated, Dimensions, Platform, StyleSheet, View } from 'react-native'; import { HeaderType } from '../../Layout/types'; import { InputRef, InputSearch } from '../../Input'; import Navigation from '../Navigation'; import { Colors, Radius, Spacing } from '../../Consts'; import { Image } from '../../Image'; import { SearchHeaderProps } from '../types'; import BackgroundImageView from './BackgroundImageView'; const SCREEN_PADDING = 12; const BACK_WIDTH = 28; const { width: screenWidth } = Dimensions.get('window'); const LinearGradientAnimated = Animated.createAnimatedComponent(LinearGradient); /** * Header extended with background image * @constructor */ const HeaderExtendHeader: React.FC<{ headerType?: HeaderType; animatedValue: Animated.Value; heightHeader: number; headerRightWidth: number; inputSearchProps?: SearchHeaderProps; inputSearchRef?: Ref; navigation?: Navigation; useShadowHeader?: boolean; gradientColor?: string; headerBackground?: string; }> = ({ headerType = 'default', animatedValue, heightHeader, headerRightWidth = 73, inputSearchProps, inputSearchRef, useShadowHeader = true, gradientColor: customGradientColor, headerBackground: customBackground, }) => { const { theme } = useContext(ApplicationContext); const context = useContext(MiniAppContext); const animated = useRef(new Animated.Value(0)); const gradientColor = customGradientColor ?? theme.colors.gradient; const headerBackground = customBackground ?? theme.assets?.headerBackground; const leftPosition = inputSearchProps?.leftPosition || BACK_WIDTH + 20; const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false; const opacityBackground = animatedValue?.interpolate({ inputRange: [0, 52], outputRange: [0, 1], extrapolate: 'clamp', }); const opacityGradient = animatedValue?.interpolate({ inputRange: [0, 52], outputRange: [1, 0], extrapolate: 'clamp', }); useEffect(() => { const listener = animatedValue.addListener(({ value }) => { animated.current.setValue(value); }); return () => { animatedValue?.removeListener(listener); }; }, [animatedValue]); const height = animated.current.interpolate({ inputRange: [0, 100], outputRange: [heightHeader + 52, heightHeader], extrapolate: 'clamp', }); const translateX = animated.current.interpolate({ inputRange: [0, 100], outputRange: [SCREEN_PADDING, leftPosition], extrapolate: 'clamp', }); const backgroundColor = animated.current.interpolate({ inputRange: [0, 100], outputRange: [ theme.colors.background.surface, theme.colors.background.default, ], extrapolate: 'clamp', }); if (inputSearchProps && Platform.OS === 'android') { useShadowHeader = false; } if (inputSearchProps) { return ( {!!gradientColor && ( {!!theme.assets?.headerBackground && ( )} )} ); } if (headerType === 'extended') { return ( {!!gradientColor && ( {!!headerBackground && ( )} )} ); } return ; }; const styles = StyleSheet.create({ headerBackground: { width: '100%', height: undefined, position: 'absolute', aspectRatio: 375 / 154, }, extendedHeader: { aspectRatio: 375 / 154, position: 'absolute', width: '100%', }, headerBox: { width: '100%', position: 'absolute', overflow: 'hidden', }, verifiedDot: { width: 4, height: 4, borderRadius: 2, backgroundColor: Colors.green_03, position: 'absolute', alignSelf: 'center', }, debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 }, }); export { HeaderExtendHeader };