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,
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: { width: 0, height: -4 },
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 10,
},
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, // Set a fixed height for the navbar
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 32,
backgroundColor: 'transparent', // Make sure it's transparent
},
centerButton: {
position: 'absolute',
left: width / 2,
top: -42.5, // Adjust this value to move the button up or down
marginLeft: -42.5, // Half of the button width (85/2)
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: 15,
right: 15,
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);