tv页面音量持久化
This commit is contained in:
@@ -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(() => {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
Reference in New Issue
Block a user