mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-22 02:24:44 +08:00
feat: dynamic skip buttons
This commit is contained in:
@@ -75,6 +75,56 @@ function PlayPageClient() {
|
||||
const [reverseEpisodeOrder, setReverseEpisodeOrder] = useState(false);
|
||||
const shortcutHintTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
// NEW STATE: 控制快进/快退按钮是否显示
|
||||
const [showSkipButtons, setShowSkipButtons] = useState(true);
|
||||
|
||||
// 使用 ResizeObserver 根据 MediaPlayer 元素尺寸动态决定按钮显隐
|
||||
useEffect(() => {
|
||||
if (
|
||||
typeof window === 'undefined' ||
|
||||
typeof ResizeObserver === 'undefined'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateShowSkipButtons = () => {
|
||||
const el: HTMLElement | undefined = (playerRef.current as any)?.el;
|
||||
if (!el) return;
|
||||
const rect = el.getBoundingClientRect();
|
||||
// width < 576 或 height < 380 时隐藏
|
||||
setShowSkipButtons(!(rect.width < 576 || rect.height < 380));
|
||||
};
|
||||
|
||||
// 尝试立即更新一次
|
||||
updateShowSkipButtons();
|
||||
|
||||
const observer = new ResizeObserver(updateShowSkipButtons);
|
||||
// 有可能此时 el 还未就绪,使用轮询确保绑定
|
||||
let retryTimer: NodeJS.Timeout | null = null;
|
||||
const attachObserver = () => {
|
||||
const el: HTMLElement | undefined = (playerRef.current as any)?.el;
|
||||
if (el) {
|
||||
observer.observe(el);
|
||||
if (retryTimer) clearInterval(retryTimer);
|
||||
}
|
||||
};
|
||||
|
||||
attachObserver();
|
||||
if (!(playerRef.current as any)?.el) {
|
||||
// 如果首次未获取到 el,继续重试直至获取
|
||||
retryTimer = setInterval(attachObserver, 200);
|
||||
}
|
||||
|
||||
// orientationchange 也可能影响高/宽
|
||||
window.addEventListener('orientationchange', updateShowSkipButtons);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
if (retryTimer) clearInterval(retryTimer);
|
||||
window.removeEventListener('orientationchange', updateShowSkipButtons);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 换源相关状态
|
||||
const [searchResults, setSearchResults] = useState<SearchResult[]>([]);
|
||||
const [searchLoading, setSearchLoading] = useState(false);
|
||||
@@ -1339,31 +1389,33 @@ function PlayPageClient() {
|
||||
airPlayButton: null, // 隐藏默认 AirPlay 按钮
|
||||
beforeCurrentTime: (
|
||||
<>
|
||||
{/* 快进 10 秒按钮 - 移动端隐藏 */}
|
||||
<button
|
||||
className='vds-button hidden md:inline-flex mr-2'
|
||||
onClick={() => {
|
||||
if (playerRef.current) {
|
||||
const p = playerRef.current;
|
||||
const newTime = Math.min(
|
||||
(p.currentTime || 0) + 10,
|
||||
p.duration || 0
|
||||
);
|
||||
p.currentTime = newTime;
|
||||
}
|
||||
}}
|
||||
aria-label='Fast Forward 10 Seconds'
|
||||
>
|
||||
<svg
|
||||
className='vds-icon'
|
||||
viewBox='0 0 32 32'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
{/* 快进 10 秒按钮 - 根据播放器尺寸决定显隐 */}
|
||||
{showSkipButtons && (
|
||||
<button
|
||||
className='vds-button mr-2'
|
||||
onClick={() => {
|
||||
if (playerRef.current) {
|
||||
const p = playerRef.current;
|
||||
const newTime = Math.min(
|
||||
(p.currentTime || 0) + 10,
|
||||
p.duration || 0
|
||||
);
|
||||
p.currentTime = newTime;
|
||||
}
|
||||
}}
|
||||
aria-label='Fast Forward 10 Seconds'
|
||||
>
|
||||
{/* 双三角快进图标 */}
|
||||
<path d='M6 24l10-8L6 8v16z' fill='currentColor' />
|
||||
<path d='M18 24l10-8-10-8v16z' fill='currentColor' />
|
||||
</svg>
|
||||
</button>
|
||||
<svg
|
||||
className='vds-icon'
|
||||
viewBox='0 0 32 32'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
{/* 双三角快进图标 */}
|
||||
<path d='M6 24l10-8L6 8v16z' fill='currentColor' />
|
||||
<path d='M18 24l10-8-10-8v16z' fill='currentColor' />
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{totalEpisodes > 1 && (
|
||||
// 下一集按钮放在时间显示前
|
||||
@@ -1411,29 +1463,33 @@ function PlayPageClient() {
|
||||
</AirPlayButton>
|
||||
</>
|
||||
),
|
||||
// 快退 10 秒按钮(移动端隐藏)
|
||||
// 快退 10 秒按钮(根据播放器尺寸决定显隐)
|
||||
beforePlayButton: (
|
||||
<button
|
||||
className='vds-button hidden md:inline-flex mr-2'
|
||||
onClick={() => {
|
||||
if (playerRef.current) {
|
||||
const p = playerRef.current;
|
||||
const newTime = Math.max(0, (p.currentTime || 0) - 10);
|
||||
p.currentTime = newTime;
|
||||
}
|
||||
}}
|
||||
aria-label='Rewind 10 Seconds'
|
||||
>
|
||||
<svg
|
||||
className='vds-icon'
|
||||
viewBox='0 0 32 32'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
{/* 双三角快退图标 */}
|
||||
<path d='M26 24l-10-8 10-8v16z' fill='currentColor' />
|
||||
<path d='M14 24l-10-8 10-8v16z' fill='currentColor' />
|
||||
</svg>
|
||||
</button>
|
||||
<>
|
||||
{showSkipButtons && (
|
||||
<button
|
||||
className='vds-button mr-2'
|
||||
onClick={() => {
|
||||
if (playerRef.current) {
|
||||
const p = playerRef.current;
|
||||
const newTime = Math.max(0, (p.currentTime || 0) - 10);
|
||||
p.currentTime = newTime;
|
||||
}
|
||||
}}
|
||||
aria-label='Rewind 10 Seconds'
|
||||
>
|
||||
<svg
|
||||
className='vds-icon'
|
||||
viewBox='0 0 32 32'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
{/* 双三角快退图标 */}
|
||||
<path d='M26 24l-10-8 10-8v16z' fill='currentColor' />
|
||||
<path d='M14 24l-10-8 10-8v16z' fill='currentColor' />
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user