From d09c1d734655bd02b3f01e5cf8f841b73e83a1cd Mon Sep 17 00:00:00 2001 From: Developer Date: Wed, 11 Mar 2026 14:32:40 +0800 Subject: [PATCH] fix: BigVideoCard stale closure, visibility guard, mediaContainer positioning --- components/BigVideoCard.tsx | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/components/BigVideoCard.tsx b/components/BigVideoCard.tsx index d5a12c7..fb1e45e 100644 --- a/components/BigVideoCard.tsx +++ b/components/BigVideoCard.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { View, Text, Image, TouchableOpacity, StyleSheet, - Dimensions, Animated, + useWindowDimensions, Animated, } from 'react-native'; import Video from 'react-native-video'; import { Ionicons } from '@expo/vector-icons'; @@ -12,9 +12,6 @@ import { proxyImageUrl } from '../utils/imageUrl'; import { formatCount, formatDuration } from '../utils/format'; import type { VideoItem } from '../services/types'; -const { width: SCREEN_W } = Dimensions.get('window'); -const THUMB_H = SCREEN_W * 0.5625; // 16:9 - const HEADERS = { Referer: 'https://www.bilibili.com', 'User-Agent': @@ -28,11 +25,22 @@ interface Props { } export function BigVideoCard({ item, isVisible, onPress }: Props) { + const { width: SCREEN_W } = useWindowDimensions(); + const THUMB_H = SCREEN_W * 0.5625; + const [videoUrl, setVideoUrl] = useState(); const [isDash, setIsDash] = useState(false); const [paused, setPaused] = useState(true); const thumbOpacity = useRef(new Animated.Value(1)).current; + // Reset video state when the item changes + useEffect(() => { + setVideoUrl(undefined); + setIsDash(false); + setPaused(true); + thumbOpacity.setValue(1); + }, [item.bvid]); + // Fetch play URL when visible for the first time useEffect(() => { if (!isVisible || videoUrl) return; @@ -64,7 +72,7 @@ export function BigVideoCard({ item, isVisible, onPress }: Props) { console.warn('BigVideoCard: failed to load play URL', e); } })(); - }, [isVisible]); + }, [isVisible, item.bvid]); // Pause/resume when visibility changes useEffect(() => { @@ -77,6 +85,7 @@ export function BigVideoCard({ item, isVisible, onPress }: Props) { }, [isVisible, videoUrl]); const handleVideoReady = () => { + if (!isVisible) return; setPaused(false); Animated.timing(thumbOpacity, { toValue: 0, @@ -88,12 +97,12 @@ export function BigVideoCard({ item, isVisible, onPress }: Props) { return ( {/* Media area */} - + {/* Thumbnail */} @@ -143,14 +152,6 @@ const styles = StyleSheet.create({ borderRadius: 6, overflow: 'hidden', }, - mediaContainer: { - width: SCREEN_W - 8, - height: THUMB_H, - }, - thumb: { - width: SCREEN_W - 8, - height: THUMB_H, - }, durationBadge: { position: 'absolute', bottom: 4,