mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-21 19:53:43 +08:00
feat: implement IPTV channel search debouncing and pagination, add video source auto-fallback, and improve type normalization.
This commit is contained in:
@@ -17,12 +17,17 @@ import type { TypeBadge } from '@/lib/types';
|
||||
|
||||
// Normalize type names to merge near-duplicates
|
||||
function normalizeTypeName(type: string): string {
|
||||
let t = type.trim();
|
||||
// Remove trailing 片/剧 suffix for grouping (e.g., "动作片" → "动作", "喜剧片" → "喜剧")
|
||||
// Collapse whitespace and trim
|
||||
let t = type.replace(/\s+/g, '').trim();
|
||||
// Apply NFC unicode normalization
|
||||
t = t.normalize('NFC');
|
||||
// Remove trailing 片/剧/类 suffix for grouping (e.g., "动作片" → "动作", "喜剧片" → "喜剧")
|
||||
// But keep standalone names like "电影", "电视剧" etc.
|
||||
if (t.length > 2 && t.endsWith('片')) {
|
||||
if (t.length > 2 && (t.endsWith('片') || t.endsWith('剧') || t.endsWith('类'))) {
|
||||
t = t.slice(0, -1);
|
||||
}
|
||||
// Lowercase for English name normalization (e.g., "Action" vs "action")
|
||||
t = t.toLowerCase();
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -40,6 +45,10 @@ export function useTypeBadges<T extends { type_name?: string }>(videos: T[]) {
|
||||
const existing = typeMap.get(normalized);
|
||||
if (existing) {
|
||||
existing.count++;
|
||||
// Prefer shorter display name (e.g., "动作" over "动作片")
|
||||
if (raw.length < existing.display.length) {
|
||||
existing.display = raw;
|
||||
}
|
||||
} else {
|
||||
typeMap.set(normalized, { display: raw, count: 1 });
|
||||
}
|
||||
|
||||
@@ -32,7 +32,8 @@ export function useVideoPlayer(
|
||||
videoId: string | null,
|
||||
source: string | null,
|
||||
episodeParam: string | null,
|
||||
isReversed: boolean = false
|
||||
isReversed: boolean = false,
|
||||
onSourceUnavailable?: () => void
|
||||
): UseVideoPlayerReturn {
|
||||
const [videoData, setVideoData] = useState<VideoData | null>(null);
|
||||
// Initialize loading to true if we have the necessary params to start fetching
|
||||
@@ -45,6 +46,7 @@ export function useVideoPlayer(
|
||||
// This solves the stale closure problem while keeping fetchVideoDetails stable for the player
|
||||
const episodeParamRef = useRef(episodeParam);
|
||||
const isReversedRef = useRef(isReversed);
|
||||
const onSourceUnavailableRef = useRef(onSourceUnavailable);
|
||||
|
||||
useEffect(() => {
|
||||
episodeParamRef.current = episodeParam;
|
||||
@@ -54,6 +56,10 @@ export function useVideoPlayer(
|
||||
isReversedRef.current = isReversed;
|
||||
}, [isReversed]);
|
||||
|
||||
useEffect(() => {
|
||||
onSourceUnavailableRef.current = onSourceUnavailable;
|
||||
}, [onSourceUnavailable]);
|
||||
|
||||
|
||||
|
||||
const fetchVideoDetails = useCallback(async () => {
|
||||
@@ -93,6 +99,7 @@ export function useVideoPlayer(
|
||||
if (response.status === 404) {
|
||||
setVideoError(data.error || '该视频源不可用。请返回并尝试其他来源。');
|
||||
setLoading(false);
|
||||
onSourceUnavailableRef.current?.();
|
||||
return;
|
||||
}
|
||||
throw new Error(data.error || `HTTP ${response.status}: ${response.statusText}`);
|
||||
|
||||
Reference in New Issue
Block a user