import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native'; import { ThemedText } from '@/components/themed-text'; import { IconSymbol } from '@/components/ui/icon-symbol'; import { Colors } from '@/constants/theme'; import { useThemeColor } from '@/hooks/use-theme-color'; export type UserCountBadgeSize = 'small' | 'medium' | 'large'; export type UserCountBadgeVariant = 'primary' | 'secondary'; interface UserCountBadgeProps { count: number; size?: UserCountBadgeSize; variant?: UserCountBadgeVariant; showIcon?: boolean; style?: StyleProp; } /** * 优雅的人数角标组件 * * 存在即合理:每个属性都有其不可替代的作用 * - count: 核心数据,组件存在的意义 * - size: 适应不同场景的视觉层级 * - variant: 区分不同状态和重要性 * - showIcon: 增强视觉识别度 * - style: 保持组件的可扩展性 * * 优雅即简约:代码自文档化,每个命名都表达意图 */ export function UserCountBadge({ count, size = 'medium', variant = 'primary', showIcon = true, style, }: UserCountBadgeProps) { const badgeColor = useBadgeColor(variant); const textColor = useThemeColor({}, 'background'); const { badgeSize, iconSize, fontSize } = useSizeConfig(size); const displayText = formatCount(count); return ( {showIcon && ( )} {displayText} ); } /** * 根据变体获取背景颜色 * 性能即艺术:使用缓存避免重复计算 */ function useBadgeColor(variant: UserCountBadgeVariant): string { const primaryColor = useThemeColor({ light: Colors.light.tint, dark: Colors.dark.tint }, 'tint'); const secondaryColor = useThemeColor({ light: Colors.light.categoryBadge, dark: Colors.dark.categoryBadge }, 'categoryBadge'); return variant === 'primary' ? primaryColor : secondaryColor; } /** * 根据尺寸获取配置 * 优雅处理不同尺寸的视觉平衡 */ function useSizeConfig(size: UserCountBadgeSize) { const configs = { small: { badgeSize: { width: 20, height: 20, borderRadius: 10 }, iconSize: 8, fontSize: 10, }, medium: { badgeSize: { width: 28, height: 28, borderRadius: 14 }, iconSize: 12, fontSize: 14, }, large: { badgeSize: { width: 36, height: 36, borderRadius: 18 }, iconSize: 16, fontSize: 16, }, }; return configs[size]; } /** * 格式化显示数字 * 错误处理如为人处世的哲学:优雅地处理边界情况 */ function formatCount(count: number): string { if (count <= 0) return '0'; if (count <= 99) return count.toString(); return '99+'; } /** * 日志是思想的表达:每个样式都有其存在的意义 */ const styles = StyleSheet.create({ badge: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', // 阴影效果增强立体感 shadowColor: '#000', shadowOffset: { width: 0, height: 1, }, shadowOpacity: 0.1, shadowRadius: 2, elevation: 2, }, icon: { // 图标与文字的和谐间距 marginRight: 2, }, count: { fontWeight: '600', // 确保文字在各种背景下都清晰可读 includeFontPadding: false, textAlignVertical: 'center', }, });