import ChatInSvg from "@/assets/icons/svg/chatIn.svg"; import ChatNotInSvg from "@/assets/icons/svg/chatNotIn.svg"; import PersonInSvg from "@/assets/icons/svg/personIn.svg"; import PersonNotInSvg from "@/assets/icons/svg/personNotIn.svg"; import { WebSocketStatus } from "@/lib/websocket-util"; import { router, usePathname } from "expo-router"; import React, { useCallback, useEffect, useMemo } from 'react'; import { Dimensions, Image, StyleSheet, TouchableOpacity, View } from 'react-native'; import Svg, { Circle, Ellipse, G, Mask, Path, Rect } from "react-native-svg"; // 使用 React.memo 包装 SVG 组件,避免不必要的重渲染 const TabIcon = React.memo(({ isActive, ActiveIcon, InactiveIcon }: { isActive: boolean; ActiveIcon: React.FC<{ width: number; height: number }>; InactiveIcon: React.FC<{ width: number; height: number }>; }) => { const Icon = isActive ? ActiveIcon : InactiveIcon; return ; }); // 提取 SVG 组件,避免重复渲染 const CenterButtonSvg = React.memo(() => ( )); interface AskNavbarProps { wsStatus: WebSocketStatus; } const AskNavbar = ({ wsStatus }: AskNavbarProps) => { // 获取设备尺寸 const { width } = useMemo(() => Dimensions.get('window'), []); const pathname = usePathname(); const statusColor = useMemo(() => { switch (wsStatus) { case 'connected': return '#4CAF50'; // Green case 'connecting': case 'reconnecting': return '#FFC107'; // Amber case 'disconnected': default: return '#F44336'; // Red } }, [wsStatus]); // 预加载目标页面 useEffect(() => { const preloadPages = async () => { try { await Promise.all([ router.prefetch('/memo-list'), router.prefetch('/ask'), router.prefetch('/owner') ]); } catch (error) { console.warn('预加载页面失败:', error); } }; preloadPages(); }, []); // 使用 useCallback 缓存导航函数 const navigateTo = useCallback((route: string) => { if (route === '/ask') { router.push({ pathname: '/ask', params: { newSession: "true" } }); } else { router.push(route as any); } }, []); // 使用 useMemo 缓存样式对象 const styles = useMemo(() => StyleSheet.create({ container: { position: 'absolute', bottom: 0, left: 0, right: 0 }, backgroundImage: { width, height: 80, resizeMode: 'cover' }, navButton: { width: width / 2, // 半屏宽度 height: 80, // 与 navbar 高度相同 justifyContent: 'center', alignItems: 'center' }, navContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 80, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 32, backgroundColor: 'transparent', }, centerButton: { position: 'absolute', left: '50%', top: -30, transform: [{ translateX: -17 }], width: 85, height: 85, justifyContent: 'center', alignItems: 'center', shadowColor: '#FFB645', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 8, borderRadius: 50, backgroundColor: 'transparent', zIndex: 10, }, statusIndicator: { position: 'absolute', top: 3, right: 20, width: 10, height: 10, borderRadius: 5, borderWidth: 1, borderColor: '#FFF', backgroundColor: statusColor, zIndex: 11, } }), [width, statusColor]); // 如果当前路径是ask页面,则不渲染导航栏 if (pathname != '/memo-list' && pathname != '/owner') { return null; } return ( navigateTo('/memo-list')} style={[styles.navButton, { alignItems: "flex-start", paddingLeft: 16 }]} > navigateTo('/ask')} style={styles.centerButton} > navigateTo('/owner')} style={styles.navButton} > ); }; export default React.memo(AskNavbar);