diff --git a/src/app/tv/live/play/page.tsx b/src/app/tv/live/play/page.tsx
index 7754f7e..2f2fb15 100644
--- a/src/app/tv/live/play/page.tsx
+++ b/src/app/tv/live/play/page.tsx
@@ -22,9 +22,10 @@ const REMOTE_KEY_DEDUPE_MS = 350;
function loadTVVolumeState() {
if (typeof window === 'undefined') return { volume: 1, muted: false };
- const savedVolume = Number(localStorage.getItem(TV_VOLUME_KEY));
- const volume = Number.isFinite(savedVolume)
- ? Math.max(0, Math.min(1, savedVolume))
+ const savedVolume = localStorage.getItem(TV_VOLUME_KEY);
+ const parsedVolume = savedVolume === null ? NaN : Number(savedVolume);
+ const volume = Number.isFinite(parsedVolume)
+ ? Math.max(0, Math.min(1, parsedVolume))
: 1;
const savedMuted = localStorage.getItem(TV_MUTED_KEY);
@@ -586,9 +587,9 @@ function TVLivePlayClient() {
)}
- {digitBuffer &&
频道 {digitBuffer}
}
+ {digitBuffer && 频道 {digitBuffer}
}
{channelHint && (
-
+
#{channelHint.number}
{channelHint.name}
diff --git a/src/app/tv/play/page.tsx b/src/app/tv/play/page.tsx
index 416e6a1..3906d8d 100644
--- a/src/app/tv/play/page.tsx
+++ b/src/app/tv/play/page.tsx
@@ -69,6 +69,7 @@ const TV_DANMAKU_MAX_ITEMS = 3000;
const TV_DANMAKU_SETTINGS_KEY = 'tv_danmaku_settings';
const TV_VOLUME_KEY = 'tv_player_volume';
const TV_MUTED_KEY = 'tv_player_muted';
+const REMOTE_KEY_DEDUPE_MS = 350;
type TVDanmakuSettings = {
fontSize: number;
@@ -85,9 +86,10 @@ const DEFAULT_TV_DANMAKU_SETTINGS: TVDanmakuSettings = {
function loadTVVolumeState() {
if (typeof window === 'undefined') return { volume: 1, muted: false };
- const savedVolume = Number(localStorage.getItem(TV_VOLUME_KEY));
- const volume = Number.isFinite(savedVolume)
- ? Math.max(0, Math.min(1, savedVolume))
+ const savedVolume = localStorage.getItem(TV_VOLUME_KEY);
+ const parsedVolume = savedVolume === null ? NaN : Number(savedVolume);
+ const volume = Number.isFinite(parsedVolume)
+ ? Math.max(0, Math.min(1, parsedVolume))
: 1;
const savedMuted = localStorage.getItem(TV_MUTED_KEY);
@@ -292,6 +294,7 @@ function TVPlayClient() {
const idleTimerRef = useRef
(null);
const volumeHintTimerRef = useRef(null);
const seekHintTimerRef = useRef(null);
+ const menuKeyTimeRef = useRef(0);
const spawnedDanmakuRef = useRef>(new Set());
const lastDanmakuTimeRef = useRef(0);
const skippedIntroRef = useRef('');
@@ -846,9 +849,19 @@ function TVPlayClient() {
const isMenuKey =
event.key === 'ContextMenu' ||
event.key === 'Menu' ||
- event.keyCode === 93;
+ event.key === 'BrowserContextMenu' ||
+ event.code === 'ContextMenu' ||
+ event.code === 'Menu' ||
+ event.keyCode === 93 ||
+ event.keyCode === 82 ||
+ event.which === 93 ||
+ event.which === 82;
if (isMenuKey) {
event.preventDefault();
+ event.stopImmediatePropagation();
+ const now = Date.now();
+ if (now - menuKeyTimeRef.current < REMOTE_KEY_DEDUPE_MS) return;
+ menuKeyTimeRef.current = now;
if (showPanel || showEpisodes || showDanmakuSettings) {
setShowPanel(false);
setShowEpisodes(false);
@@ -1026,6 +1039,21 @@ function TVPlayClient() {
? 'true'
: 'false'
}
+ onContextMenu={(event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ const now = Date.now();
+ if (now - menuKeyTimeRef.current < REMOTE_KEY_DEDUPE_MS) return;
+ menuKeyTimeRef.current = now;
+ if (showPanel || showEpisodes || showDanmakuSettings) {
+ setShowPanel(false);
+ setShowEpisodes(false);
+ setShowDanmakuSettings(false);
+ blurTVPlayerControl();
+ } else {
+ revealPanel();
+ }
+ }}
className='fixed inset-0 overflow-hidden bg-black text-white'
>
{videoUrl ? (