import React, {ReactNode, useEffect, useRef, useState} from 'react'; import { LayoutRectangle, StyleSheet, TouchableWithoutFeedback, View, StatusBar as OriginalStatusBar, StyleProp, ViewStyle, } from 'react-native'; import rpx from '@/utils/rpx'; import useColors from '@/hooks/useColors'; import StatusBar from './statusBar'; import color from 'color'; import IconButton from './iconButton'; import globalStyle from '@/constants/globalStyle'; import ThemeText from './themeText'; import {useNavigation} from '@react-navigation/native'; import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; import Portal from './portal'; import ListItem from './listItem'; interface IAppBarProps { backgroundOpacity?: number; titleTextOpacity?: number; withStatusBar?: boolean; color?: string; actions?: Array<{ icon: string; onPress?: () => void; }>; menu?: Array<{ icon: string; title: string; show?: boolean; onPress?: () => void; }>; menuWithStatusBar?: boolean; children?: string | ReactNode; containerStyle?: StyleProp; contentStyle?: StyleProp; actionComponent?: ReactNode; } const ANIMATION_EASING: Animated.EasingFunction = Easing.out(Easing.exp); const ANIMATION_DURATION = 500; const timingConfig = { duration: ANIMATION_DURATION, easing: ANIMATION_EASING, }; export default function AppBar(props: IAppBarProps) { const { backgroundOpacity = 1, titleTextOpacity = 1, withStatusBar, color: _color, actions = [], menu = [], menuWithStatusBar = true, containerStyle, contentStyle, children, actionComponent, } = props; const colors = useColors(); const navigation = useNavigation(); const bgColor = color(colors.appBar ?? colors.primary) .alpha(backgroundOpacity) .toString(); const contentColor = _color ?? colors.appBarText; const [showMenu, setShowMenu] = useState(false); const menuIconLayoutRef = useRef(); const scaleRate = useSharedValue(0); useEffect(() => { if (showMenu) { scaleRate.value = withTiming(1, timingConfig); } else { scaleRate.value = withTiming(0, timingConfig); } }, [showMenu]); const transformStyle = useAnimatedStyle(() => { return { opacity: scaleRate.value, }; }); return ( <> {withStatusBar ? : null} { navigation.goBack(); }} /> {typeof children === 'string' ? ( {children} ) : ( children )} {actions.map((action, index) => ( ))} {actionComponent ?? null} {menu?.length ? ( { menuIconLayoutRef.current = e.nativeEvent.layout; }} color={contentColor} style={[globalStyle.notShrink, styles.rightButton]} onPress={() => { setShowMenu(true); }} /> ) : null} {showMenu ? ( { setShowMenu(false); }}> ) : null} <> {menu.map(it => it.show !== false ? ( { it.onPress?.(); setShowMenu(false); }}> ) : null, )} ); } const styles = StyleSheet.create({ container: { width: '100%', zIndex: 10000, height: rpx(88), flexDirection: 'row', paddingHorizontal: rpx(24), }, content: { flexDirection: 'row', flexBasis: 0, alignItems: 'center', paddingHorizontal: rpx(24), }, rightButton: { marginLeft: rpx(28), }, blocker: { position: 'absolute', bottom: 0, left: 0, width: '100%', height: '100%', zIndex: 10010, }, bubbleCorner: { position: 'absolute', borderColor: 'transparent', borderWidth: rpx(10), zIndex: 10012, transformOrigin: 'right top', opacity: 0, }, menu: { width: rpx(340), maxHeight: rpx(600), borderRadius: rpx(8), zIndex: 10011, position: 'absolute', opacity: 0, shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.23, shadowRadius: 2.62, elevation: 4, }, });