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" },
});