diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx index aa3a6ba..a78eb11 100644 --- a/src/app/play/page.tsx +++ b/src/app/play/page.tsx @@ -129,6 +129,21 @@ function PlayPageClient() { null ); + // 优选和测速开关 + const [optimizationEnabled] = useState(() => { + if (typeof window !== 'undefined') { + const saved = localStorage.getItem('enableOptimization'); + if (saved !== null) { + try { + return JSON.parse(saved); + } catch { + /* ignore */ + } + } + } + return true; + }); + // 保存优选时的测速结果,避免EpisodeSelector重复测速 const [precomputedVideoInfo, setPrecomputedVideoInfo] = useState< Map @@ -524,35 +539,25 @@ function PlayPageClient() { return; } - let needLoadSource = currentSource; - let needLoadId = currentId; - if ((!currentSource && !currentId) || needPreferRef.current) { + let detailData: SearchResult = sourcesInfo[0]; + if ( + ((!currentSource && !currentId) || needPreferRef.current) && + optimizationEnabled + ) { setLoadingStage('preferring'); setLoadingMessage('⚡ 正在优选最佳播放源...'); - const preferredSource = await preferBestSource(sourcesInfo); - setNeedPrefer(false); - setCurrentSource(preferredSource.source); - setCurrentId(preferredSource.id); - setVideoYear(preferredSource.year); - needLoadSource = preferredSource.source; - needLoadId = preferredSource.id; + detailData = await preferBestSource(sourcesInfo); } console.log(sourcesInfo); - console.log(needLoadSource, needLoadId); - const detailData = sourcesInfo.find( - (source) => - source.source === needLoadSource && - source.id.toString() === needLoadId.toString() - ); - if (!detailData) { - setError('未找到匹配结果'); - setLoading(false); - return; - } - setVideoTitle(detailData.title || videoTitleRef.current); + console.log(detailData.source, detailData.id); + + setNeedPrefer(false); + setCurrentSource(detailData.source); + setCurrentId(detailData.id); setVideoYear(detailData.year); + setVideoTitle(detailData.title || videoTitleRef.current); setVideoCover(detailData.poster); setDetail(detailData); if (currentEpisodeIndex >= detailData.episodes.length) { @@ -561,8 +566,8 @@ function PlayPageClient() { // 规范URL参数 const newUrl = new URL(window.location.href); - newUrl.searchParams.set('source', needLoadSource); - newUrl.searchParams.set('id', needLoadId); + newUrl.searchParams.set('source', detailData.source); + newUrl.searchParams.set('id', detailData.id); newUrl.searchParams.set('year', detailData.year); newUrl.searchParams.set('title', detailData.title); newUrl.searchParams.delete('prefer'); diff --git a/src/components/EpisodeSelector.tsx b/src/components/EpisodeSelector.tsx index 3ca96b6..c10a371 100644 --- a/src/components/EpisodeSelector.tsx +++ b/src/components/EpisodeSelector.tsx @@ -162,10 +162,30 @@ const EpisodeSelector: React.FC = ({ } }, [precomputedVideoInfo]); + // 读取本地“优选和测速”开关,默认开启 + const [optimizationEnabled] = useState(() => { + if (typeof window !== 'undefined') { + const saved = localStorage.getItem('enableOptimization'); + if (saved !== null) { + try { + return JSON.parse(saved); + } catch { + /* ignore */ + } + } + } + return true; + }); + // 当切换到换源tab并且有源数据时,异步获取视频信息 - 移除 attemptedSources 依赖避免循环触发 useEffect(() => { const fetchVideoInfosInBatches = async () => { - if (activeTab !== 'sources' || availableSources.length === 0) return; + if ( + !optimizationEnabled || // 若关闭测速则直接退出 + activeTab !== 'sources' || + availableSources.length === 0 + ) + return; // 筛选出尚未测速的播放源 const pendingSources = availableSources.filter((source) => { @@ -185,7 +205,7 @@ const EpisodeSelector: React.FC = ({ fetchVideoInfosInBatches(); // 依赖项保持与之前一致 - }, [activeTab, availableSources, getVideoInfo]); + }, [activeTab, availableSources, getVideoInfo, optimizationEnabled]); // 升序分页标签 const categoriesAsc = useMemo(() => { @@ -511,11 +531,11 @@ const EpisodeSelector: React.FC = ({ } // 始终显示占位符,确保布局一致且分辨率信息始终可见 - return ( + return optimizationEnabled ? (
检测中
- ); + ) : null; })()} diff --git a/src/components/SettingsButton.tsx b/src/components/SettingsButton.tsx index 04ce95e..0b83877 100644 --- a/src/components/SettingsButton.tsx +++ b/src/components/SettingsButton.tsx @@ -9,6 +9,7 @@ export const SettingsButton: React.FC = () => { const [defaultAggregateSearch, setDefaultAggregateSearch] = useState(true); const [doubanProxyUrl, setDoubanProxyUrl] = useState(''); const [imageProxyUrl, setImageProxyUrl] = useState(''); + const [enableOptimization, setEnableOptimization] = useState(true); const [mounted, setMounted] = useState(false); // 确保组件已挂载 @@ -35,6 +36,12 @@ export const SettingsButton: React.FC = () => { if (savedImageProxyUrl !== null) { setImageProxyUrl(savedImageProxyUrl); } + + const savedEnableOptimization = + localStorage.getItem('enableOptimization'); + if (savedEnableOptimization !== null) { + setEnableOptimization(JSON.parse(savedEnableOptimization)); + } } }, []); @@ -60,6 +67,13 @@ export const SettingsButton: React.FC = () => { } }; + const handleOptimizationToggle = (value: boolean) => { + setEnableOptimization(value); + if (typeof window !== 'undefined') { + localStorage.setItem('enableOptimization', JSON.stringify(value)); + } + }; + const handleSettingsClick = () => { setIsOpen(!isOpen); }; @@ -119,6 +133,30 @@ export const SettingsButton: React.FC = () => { + {/* 优选和测速 */} +
+
+

+ 启用优选和测速 +

+

+ 如出现播放器劫持问题可关闭 +

+
+ +
+ {/* 豆瓣代理设置 */}