import React, {ReactNode, useEffect, useState} from 'react'; import { LayoutRectangle, StatusBar as OriginalStatusBar, StyleProp, StyleSheet, TouchableWithoutFeedback, View, 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'; import {IIconName} from '@/components/base/icon.tsx'; interface IAppBarProps { titleTextOpacity?: number; withStatusBar?: boolean; color?: string; actions?: Array<{ icon: IIconName; onPress?: () => void; }>; menu?: Array<{ icon: IIconName; title: string; show?: boolean; onPress?: () => void; }>; menuWithStatusBar?: boolean; children?: string | ReactNode; containerStyle?: StyleProp; contentStyle?: StyleProp; actionComponent?: ReactNode; onBackPress?: () => void; } 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 { titleTextOpacity = 1, withStatusBar, color: _color, actions = [], menu = [], menuWithStatusBar = true, containerStyle, contentStyle, children, actionComponent, onBackPress, } = props; const colors = useColors(); const navigation = useNavigation(); const bgColor = color(colors.appBar ?? colors.primary).toString(); const contentColor = _color ?? colors.appBarText; const [showMenu, setShowMenu] = useState(false); const [menuIconLayout, setMenuIconLayout] = useState(null); 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 ? ( { setMenuIconLayout(evt.nativeEvent.layout); }} color={contentColor} style={[globalStyle.notShrink, styles.rightButton]} onPress={() => { setShowMenu(true); }} /> ) : null} {showMenu ? ( { setShowMenu(false); }}> ) : null} <> {menu.map(it => it.show !== false ? ( { setShowMenu(false); // async setTimeout(() => { it.onPress?.(); }, 20); }}> ) : null, )} ); } const styles = StyleSheet.create({ container: { width: '100%', zIndex: 10000, height: rpx(88), flexDirection: 'row', alignItems: 'center', 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, }, });