fix: address code review issues in danmaku components

This commit is contained in:
Developer
2026-03-11 10:01:50 +08:00
parent a9b5b364a2
commit 72a8fdfdc0
3 changed files with 15 additions and 5 deletions

View File

@@ -47,7 +47,7 @@ export default function DanmakuList({ danmakus, currentTime, visible, onToggle }
<FlatList <FlatList
ref={flatListRef} ref={flatListRef}
data={visibleItems} data={visibleItems}
keyExtractor={(_, i) => String(i)} keyExtractor={(item, i) => `${item.time}_${item.text}_${i}`}
style={styles.list} style={styles.list}
renderItem={({ item }) => ( renderItem={({ item }) => (
<Text <Text

View File

@@ -28,6 +28,10 @@ export default function DanmakuOverlay({ danmakus, currentTime, screenWidth, scr
const activated = useRef<Set<string>>(new Set()); const activated = useRef<Set<string>>(new Set());
const prevTimeRef = useRef<number>(currentTime); const prevTimeRef = useRef<number>(currentTime);
const idCounter = useRef(0); const idCounter = useRef(0);
const mountedRef = useRef(true);
useEffect(() => {
return () => { mountedRef.current = false; };
}, []);
const pickLane = useCallback((): number | null => { const pickLane = useCallback((): number | null => {
const now = Date.now(); const now = Date.now();
@@ -37,6 +41,12 @@ export default function DanmakuOverlay({ danmakus, currentTime, screenWidth, scr
return null; return null;
}, []); }, []);
useEffect(() => {
activated.current.clear();
laneAvailAt.current.fill(0);
setActiveDanmakus([]);
}, [danmakus]);
useEffect(() => { useEffect(() => {
if (!visible) return; if (!visible) return;
@@ -63,9 +73,9 @@ export default function DanmakuOverlay({ danmakus, currentTime, screenWidth, scr
const newItems: ActiveDanmaku[] = []; const newItems: ActiveDanmaku[] = [];
if (activated.current.size > 200) activated.current.clear(); // prevent memory leak
for (const item of candidates) { for (const item of candidates) {
const key = `${item.time}_${item.text}`; const key = `${item.time}_${item.text}`;
if (activated.current.size > 200) activated.current.clear(); // prevent memory leak
activated.current.add(key); activated.current.add(key);
if (item.mode === 1) { if (item.mode === 1) {
@@ -94,7 +104,7 @@ export default function DanmakuOverlay({ danmakus, currentTime, screenWidth, scr
duration, duration,
useNativeDriver: true, useNativeDriver: true,
}).start(() => { }).start(() => {
setActiveDanmakus(prev => prev.filter(d => d.id !== id)); if (mountedRef.current) setActiveDanmakus(prev => prev.filter(d => d.id !== id));
}); });
} else { } else {
// Fixed danmaku (mode 4 = bottom, mode 5 = top) // Fixed danmaku (mode 4 = bottom, mode 5 = top)
@@ -106,7 +116,7 @@ export default function DanmakuOverlay({ danmakus, currentTime, screenWidth, scr
Animated.delay(2000), Animated.delay(2000),
Animated.timing(opacity, { toValue: 0, duration: 500, useNativeDriver: true }), Animated.timing(opacity, { toValue: 0, duration: 500, useNativeDriver: true }),
]).start(() => { ]).start(() => {
setActiveDanmakus(prev => prev.filter(d => d.id !== id)); if (mountedRef.current) setActiveDanmakus(prev => prev.filter(d => d.id !== id));
}); });
} }
} }

View File

@@ -9,7 +9,7 @@ import { Ionicons } from '@expo/vector-icons';
import type { PlayUrlResponse, VideoShotData, DanmakuItem } from '../services/types'; import type { PlayUrlResponse, VideoShotData, DanmakuItem } from '../services/types';
import { buildDashMpdUri } from '../utils/dash'; import { buildDashMpdUri } from '../utils/dash';
import { getHeatmap, getVideoShot } from '../services/bilibili'; import { getHeatmap, getVideoShot } from '../services/bilibili';
import { DanmakuOverlay } from './DanmakuOverlay'; import DanmakuOverlay from './DanmakuOverlay';
const BAR_H = 3; const BAR_H = 3;
const BALL = 12; const BALL = 12;