import React, { useEffect, useRef, memo } from "react"; import { View, StyleSheet, Animated } from "react-native"; import { useTheme } from "../utils/theme"; // 性能优化:颜色由顶层 useTheme 一次拿到,所有 block 走 inline style,避免 40+ store 订阅。 // 布局:与详情页 ListHeaderComponent 结构同步 —— // 标题块 → Meta 行 → 动作按钮行 → 创作者行 → 推荐视频标题 → 推荐卡片 interface BlockProps { width: number | `${number}%`; height: number; radius?: number; bg: string; style?: any; } const SkeletonBlock = memo(function SkeletonBlock({ width, height, radius = 4, bg, style }: BlockProps) { return ( ); }); const RelatedCardSkeleton = memo(function RelatedCardSkeleton({ bg, border }: { bg: string; border: string }) { return ( ); }); // 一个动作按钮占位(pill 形状,匹配 VideoActionRow 实际按钮形态) const ActionPillSkeleton = memo(function ActionPillSkeleton({ bg, width }: { bg: string; width: number }) { return ; }); const CARD_COUNT = 4; export function VideoDetailSkeleton() { const theme = useTheme(); const opacity = useRef(new Animated.Value(0.6)).current; useEffect(() => { const loop = Animated.loop( Animated.sequence([ Animated.timing(opacity, { toValue: 1, duration: 800, useNativeDriver: true }), Animated.timing(opacity, { toValue: 0.6, duration: 800, useNativeDriver: true }), ]), ); loop.start(); return () => loop.stop(); }, [opacity]); const bg = theme.placeholder; const border = theme.border; return ( {/* 标题块(两行) + Meta 行 */} {/* 动作按钮行 */} {/* 创作者行 + 关注按钮 */} {/* 推荐视频标题 */} {/* 推荐卡片占位(4 张足够撑满首屏,少绘制开销) */} {Array.from({ length: CARD_COUNT }).map((_, i) => ( ))} ); } const styles = StyleSheet.create({ container: { flex: 1 }, titleBlock: { paddingHorizontal: 14, paddingTop: 12, paddingBottom: 12 }, actionRow: { flexDirection: "row", alignItems: "center", paddingHorizontal: 12, paddingVertical: 10, gap: 8, borderTopWidth: StyleSheet.hairlineWidth, }, creatorRow: { flexDirection: "row", alignItems: "center", paddingHorizontal: 14, paddingVertical: 12, borderTopWidth: StyleSheet.hairlineWidth, borderBottomWidth: StyleSheet.hairlineWidth, }, creatorInfo: { flex: 1, marginLeft: 10 }, relatedHeader: { paddingLeft: 13, paddingTop: 12, paddingBottom: 8, }, card: { flexDirection: "row", paddingHorizontal: 12, paddingVertical: 8, borderBottomWidth: StyleSheet.hairlineWidth, gap: 10, }, cardInfo: { flex: 1, justifyContent: "space-between", paddingVertical: 2 }, cardMeta: { flexDirection: "row", justifyContent: "space-between", alignItems: "center" }, });