tv页面音量持久化

This commit is contained in:
mtvpls
2026-05-31 10:41:35 +08:00
parent 3fa206450a
commit 3ba4759d99
2 changed files with 52 additions and 4 deletions
+26 -2
View File
@@ -15,8 +15,25 @@ type EpgProgram = { start: string; end: string; title: string };
type TVPlayerSourceType = 'm3u8' | 'flv' | 'native'; type TVPlayerSourceType = 'm3u8' | 'flv' | 'native';
const TV_LIVE_LAST_CHANNEL_KEY = 'tv_live_last_channel'; const TV_LIVE_LAST_CHANNEL_KEY = 'tv_live_last_channel';
const TV_VOLUME_KEY = 'tv_player_volume';
const TV_MUTED_KEY = 'tv_player_muted';
const REMOTE_KEY_DEDUPE_MS = 350; 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))
: 1;
const savedMuted = localStorage.getItem(TV_MUTED_KEY);
return {
volume,
muted: savedMuted === null ? volume <= 0 : savedMuted === 'true',
};
}
function getLogoUrl(logo?: string, source?: string) { function getLogoUrl(logo?: string, source?: string) {
if (!logo) return ''; if (!logo) return '';
const sourceParam = source ? `&source=${encodeURIComponent(source)}` : ''; const sourceParam = source ? `&source=${encodeURIComponent(source)}` : '';
@@ -94,8 +111,9 @@ function TVLivePlayClient() {
const [favorited, setFavorited] = useState(false); const [favorited, setFavorited] = useState(false);
const [epgPrograms, setEpgPrograms] = useState<EpgProgram[]>([]); const [epgPrograms, setEpgPrograms] = useState<EpgProgram[]>([]);
const [epgLoading, setEpgLoading] = useState(false); const [epgLoading, setEpgLoading] = useState(false);
const [muted, setMuted] = useState(false); const [initialVolumeState] = useState(loadTVVolumeState);
const [volume, setVolume] = useState(1); const [muted, setMuted] = useState(initialVolumeState.muted);
const [volume, setVolume] = useState(initialVolumeState.volume);
const [showVolumeHint, setShowVolumeHint] = useState(false); const [showVolumeHint, setShowVolumeHint] = useState(false);
const [channelHint, setChannelHint] = useState<{ number: number; name: string } | null>(null); const [channelHint, setChannelHint] = useState<{ number: number; name: string } | null>(null);
const channelButtonRefs = useRef<Record<string, HTMLButtonElement | null>>({}); const channelButtonRefs = useRef<Record<string, HTMLButtonElement | null>>({});
@@ -223,6 +241,12 @@ function TVLivePlayClient() {
} }
}, [channel, source]); }, [channel, source]);
useEffect(() => {
if (typeof window === 'undefined') return;
localStorage.setItem(TV_VOLUME_KEY, String(volume));
localStorage.setItem(TV_MUTED_KEY, String(muted));
}, [muted, volume]);
useEffect(() => { useEffect(() => {
if (!playbackError || !channel || retryCount >= 3) return; if (!playbackError || !channel || retryCount >= 3) return;
const timer = window.setTimeout(() => { const timer = window.setTimeout(() => {
+26 -2
View File
@@ -67,6 +67,8 @@ const TV_DANMAKU_SPAWN_GRACE = 0.6;
const TV_DANMAKU_SEEK_WINDOW = 8; const TV_DANMAKU_SEEK_WINDOW = 8;
const TV_DANMAKU_MAX_ITEMS = 3000; const TV_DANMAKU_MAX_ITEMS = 3000;
const TV_DANMAKU_SETTINGS_KEY = 'tv_danmaku_settings'; const TV_DANMAKU_SETTINGS_KEY = 'tv_danmaku_settings';
const TV_VOLUME_KEY = 'tv_player_volume';
const TV_MUTED_KEY = 'tv_player_muted';
type TVDanmakuSettings = { type TVDanmakuSettings = {
fontSize: number; fontSize: number;
@@ -80,6 +82,21 @@ const DEFAULT_TV_DANMAKU_SETTINGS: TVDanmakuSettings = {
opacity: 0.75, opacity: 0.75,
}; };
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))
: 1;
const savedMuted = localStorage.getItem(TV_MUTED_KEY);
return {
volume,
muted: savedMuted === null ? volume <= 0 : savedMuted === 'true',
};
}
function loadTVDanmakuSettings(): TVDanmakuSettings { function loadTVDanmakuSettings(): TVDanmakuSettings {
if (typeof window === 'undefined') return DEFAULT_TV_DANMAKU_SETTINGS; if (typeof window === 'undefined') return DEFAULT_TV_DANMAKU_SETTINGS;
@@ -218,8 +235,9 @@ function TVPlayClient() {
const [isPlaying, setIsPlaying] = useState(false); const [isPlaying, setIsPlaying] = useState(false);
const [isBuffering, setIsBuffering] = useState(false); const [isBuffering, setIsBuffering] = useState(false);
const [favorited, setFavorited] = useState(false); const [favorited, setFavorited] = useState(false);
const [muted, setMuted] = useState(false); const [initialVolumeState] = useState(loadTVVolumeState);
const [volume, setVolume] = useState(1); const [muted, setMuted] = useState(initialVolumeState.muted);
const [volume, setVolume] = useState(initialVolumeState.volume);
const [showVolumeHint, setShowVolumeHint] = useState(false); const [showVolumeHint, setShowVolumeHint] = useState(false);
const [seekHint, setSeekHint] = useState<{ const [seekHint, setSeekHint] = useState<{
current: number; current: number;
@@ -403,6 +421,12 @@ function TVPlayClient() {
localStorage.setItem('tv_playback_rate', String(playbackRate)); localStorage.setItem('tv_playback_rate', String(playbackRate));
}, [playbackRate]); }, [playbackRate]);
useEffect(() => {
if (typeof window === 'undefined') return;
localStorage.setItem(TV_VOLUME_KEY, String(volume));
localStorage.setItem(TV_MUTED_KEY, String(muted));
}, [muted, volume]);
useEffect(() => { useEffect(() => {
let alive = true; let alive = true;
async function loadDanmaku() { async function loadDanmaku() {