Files
JKVideo/hooks/useLiveDetail.ts

62 lines
1.7 KiB
TypeScript
Raw Normal View History

2026-03-16 21:13:26 +08:00
import { useState, useEffect, useCallback } from 'react';
2026-03-16 16:20:59 +08:00
import { getLiveRoomDetail, getLiveAnchorInfo, getLiveStreamUrl } from '../services/bilibili';
import type { LiveRoomDetail, LiveAnchorInfo, LiveStreamInfo } from '../services/types';
interface LiveDetailState {
room: LiveRoomDetail | null;
anchor: LiveAnchorInfo | null;
stream: LiveStreamInfo | null;
loading: boolean;
error: string | null;
}
export function useLiveDetail(roomId: number) {
const [state, setState] = useState<LiveDetailState>({
room: null,
anchor: null,
stream: null,
loading: true,
error: null,
});
useEffect(() => {
if (!roomId) return;
let cancelled = false;
setState({ room: null, anchor: null, stream: null, loading: true, error: null });
async function fetch() {
try {
const [room, anchor] = await Promise.all([
getLiveRoomDetail(roomId),
getLiveAnchorInfo(roomId),
]);
if (cancelled) return;
2026-03-16 21:13:26 +08:00
let stream: LiveStreamInfo = { hlsUrl: '', flvUrl: '', qn: 0, qualities: [] };
2026-03-16 16:20:59 +08:00
if (room.live_status === 1) {
stream = await getLiveStreamUrl(roomId);
}
if (cancelled) return;
setState({ room, anchor, stream, loading: false, error: null });
} catch (e: any) {
if (cancelled) return;
setState(prev => ({ ...prev, loading: false, error: e?.message ?? '加载失败' }));
}
}
fetch();
return () => { cancelled = true; };
}, [roomId]);
2026-03-16 21:13:26 +08:00
const changeQuality = useCallback(async (qn: number) => {
try {
const stream = await getLiveStreamUrl(roomId, qn);
setState(prev => ({ ...prev, stream: { ...stream, qn } }));
2026-03-16 21:13:26 +08:00
} catch { /* ignore */ }
}, [roomId]);
return { ...state, changeQuality };
2026-03-16 16:20:59 +08:00
}