tv页面音量持久化
This commit is contained in:
@@ -15,8 +15,25 @@ type EpgProgram = { start: string; end: string; title: string };
|
||||
type TVPlayerSourceType = 'm3u8' | 'flv' | 'native';
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
if (!logo) return '';
|
||||
const sourceParam = source ? `&source=${encodeURIComponent(source)}` : '';
|
||||
@@ -94,8 +111,9 @@ function TVLivePlayClient() {
|
||||
const [favorited, setFavorited] = useState(false);
|
||||
const [epgPrograms, setEpgPrograms] = useState<EpgProgram[]>([]);
|
||||
const [epgLoading, setEpgLoading] = useState(false);
|
||||
const [muted, setMuted] = useState(false);
|
||||
const [volume, setVolume] = useState(1);
|
||||
const [initialVolumeState] = useState(loadTVVolumeState);
|
||||
const [muted, setMuted] = useState(initialVolumeState.muted);
|
||||
const [volume, setVolume] = useState(initialVolumeState.volume);
|
||||
const [showVolumeHint, setShowVolumeHint] = useState(false);
|
||||
const [channelHint, setChannelHint] = useState<{ number: number; name: string } | null>(null);
|
||||
const channelButtonRefs = useRef<Record<string, HTMLButtonElement | null>>({});
|
||||
@@ -223,6 +241,12 @@ function TVLivePlayClient() {
|
||||
}
|
||||
}, [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(() => {
|
||||
if (!playbackError || !channel || retryCount >= 3) return;
|
||||
const timer = window.setTimeout(() => {
|
||||
|
||||
@@ -67,6 +67,8 @@ const TV_DANMAKU_SPAWN_GRACE = 0.6;
|
||||
const TV_DANMAKU_SEEK_WINDOW = 8;
|
||||
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';
|
||||
|
||||
type TVDanmakuSettings = {
|
||||
fontSize: number;
|
||||
@@ -80,6 +82,21 @@ const DEFAULT_TV_DANMAKU_SETTINGS: TVDanmakuSettings = {
|
||||
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 {
|
||||
if (typeof window === 'undefined') return DEFAULT_TV_DANMAKU_SETTINGS;
|
||||
|
||||
@@ -218,8 +235,9 @@ function TVPlayClient() {
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const [isBuffering, setIsBuffering] = useState(false);
|
||||
const [favorited, setFavorited] = useState(false);
|
||||
const [muted, setMuted] = useState(false);
|
||||
const [volume, setVolume] = useState(1);
|
||||
const [initialVolumeState] = useState(loadTVVolumeState);
|
||||
const [muted, setMuted] = useState(initialVolumeState.muted);
|
||||
const [volume, setVolume] = useState(initialVolumeState.volume);
|
||||
const [showVolumeHint, setShowVolumeHint] = useState(false);
|
||||
const [seekHint, setSeekHint] = useState<{
|
||||
current: number;
|
||||
@@ -403,6 +421,12 @@ function TVPlayClient() {
|
||||
localStorage.setItem('tv_playback_rate', String(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(() => {
|
||||
let alive = true;
|
||||
async function loadDanmaku() {
|
||||
|
||||
Reference in New Issue
Block a user