fix(conversation): 优化对话列表滚动与播放队列并发

- 使用 InteractionManager.runAfterInteractions 包裹 scrollToEnd,避免滚动卡顿
- 提取 flattenedData 变量,减少重复计算
- 输入框增加 minHeight:22,空内容时保持一行高度
- use-player: 用 isPlayNextInProgressRef 防止 playNext 并发执行
- hooks: 格式化 useEffect 依赖数组
This commit is contained in:
Kevin
2026-03-19 10:24:48 +08:00
parent 15512834d2
commit bcee000735
3 changed files with 42 additions and 20 deletions

View File

@@ -28,6 +28,7 @@ export function usePlayer(): UsePlayerResult {
const [currentSource, setCurrentSource] = useState<string | null>(null);
const isPlayingRef = useRef(false);
const wasBlockedByRecorderRef = useRef(false);
const isPlayNextInProgressRef = useRef(false);
const player = useAudioPlayer(currentSource);
const playerStatus = useAudioPlayerStatus(player);
@@ -41,24 +42,32 @@ export function usePlayer(): UsePlayerResult {
}, [currentSource, player]);
const playNext = useCallback(async () => {
if (queueRef.current.length === 0) {
setCurrentSource(null);
setStatus('idle');
setQueueLength(0);
await audioFocus.release();
return;
}
if (isPlayNextInProgressRef.current) return;
isPlayNextInProgressRef.current = true;
try {
if (queueRef.current.length === 0) {
setCurrentSource(null);
setStatus('idle');
setQueueLength(0);
await audioFocus.release();
return;
}
const acquired = await audioFocus.acquireForPlayback();
if (!acquired) {
setStatus('idle');
return;
}
const acquired = await audioFocus.acquireForPlayback();
if (!acquired) {
setStatus('idle');
return;
}
const next = queueRef.current.shift()!;
setQueueLength(queueRef.current.length);
setStatus('playing');
setCurrentSource(next.uri);
if (queueRef.current.length === 0) return;
const next = queueRef.current.shift()!;
setQueueLength(queueRef.current.length);
setStatus('playing');
setCurrentSource(next.uri);
} finally {
isPlayNextInProgressRef.current = false;
}
}, []);
// Detect playback completion → advance queue