feat(ui): add clear cache and optimize media session
- Add button in side drawer settings to clear local cache data - Refactor Media Session position updates to trigger on specific events (seek, play/pause, load) instead of every time update - Add finite number validation for seek operations
This commit is contained in:
67
index.html
67
index.html
@@ -319,7 +319,7 @@
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const SideDrawer = ({ isOpen, onClose, view, setView, quality, setQuality }) => {
|
const SideDrawer = ({ isOpen, onClose, view, setView, quality, setQuality, onClearCache }) => {
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -355,8 +355,8 @@
|
|||||||
<div className="mt-8 px-4 mb-2 text-xs font-bold text-gray-500 uppercase tracking-wider">设置</div>
|
<div className="mt-8 px-4 mb-2 text-xs font-bold text-gray-500 uppercase tracking-wider">设置</div>
|
||||||
<div className="px-4 py-2">
|
<div className="px-4 py-2">
|
||||||
<label className="block text-sm text-gray-300 mb-2">默认播放音质</label>
|
<label className="block text-sm text-gray-300 mb-2">默认播放音质</label>
|
||||||
<select
|
<select
|
||||||
value={quality}
|
value={quality}
|
||||||
onChange={(e) => setQuality(e.target.value)}
|
onChange={(e) => setQuality(e.target.value)}
|
||||||
className="drawer-select"
|
className="drawer-select"
|
||||||
>
|
>
|
||||||
@@ -365,6 +365,21 @@
|
|||||||
<option value="flac">无损 (FLAC)</option>
|
<option value="flac">无损 (FLAC)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="px-4 py-2 mt-2">
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
if(confirm('确定要清除所有缓存数据吗?这将重置播放列表和收藏。')) {
|
||||||
|
onClearCache();
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="w-full py-2 px-4 rounded-lg border border-red-500/50 text-red-500 hover:bg-red-500/10 transition-colors text-sm flex items-center justify-center gap-2"
|
||||||
|
>
|
||||||
|
<Icon name="trash-can" />
|
||||||
|
清理缓存数据
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 border-t border-white/10 text-xs text-gray-500 text-center">
|
<div className="p-4 border-t border-white/10 text-xs text-gray-500 text-center">
|
||||||
@@ -719,17 +734,6 @@
|
|||||||
audio.volume = volume;
|
audio.volume = volume;
|
||||||
const updateTime = () => {
|
const updateTime = () => {
|
||||||
setCurrentTime(audio.currentTime);
|
setCurrentTime(audio.currentTime);
|
||||||
if ('mediaSession' in navigator && !isNaN(audio.duration)) {
|
|
||||||
try {
|
|
||||||
navigator.mediaSession.setPositionState({
|
|
||||||
duration: audio.duration,
|
|
||||||
playbackRate: audio.playbackRate,
|
|
||||||
position: audio.currentTime
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// Ignore errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const updateDuration = () => setDuration(audio.duration);
|
const updateDuration = () => setDuration(audio.duration);
|
||||||
const onEnded = () => playNext(true);
|
const onEnded = () => playNext(true);
|
||||||
@@ -878,8 +882,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSeek = (time) => {
|
const handleSeek = (time) => {
|
||||||
audioRef.current.currentTime = time;
|
if (Number.isFinite(time)) {
|
||||||
setCurrentTime(time);
|
audioRef.current.currentTime = time;
|
||||||
|
setCurrentTime(time);
|
||||||
|
updateMediaSessionPosition();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteFromPlaylist = (index) => {
|
const deleteFromPlaylist = (index) => {
|
||||||
@@ -915,6 +922,18 @@
|
|||||||
|
|
||||||
// --- Media Session Integration ---
|
// --- Media Session Integration ---
|
||||||
|
|
||||||
|
const updateMediaSessionPosition = () => {
|
||||||
|
if ('mediaSession' in navigator && audioRef.current && !isNaN(audioRef.current.duration)) {
|
||||||
|
try {
|
||||||
|
navigator.mediaSession.setPositionState({
|
||||||
|
duration: audioRef.current.duration,
|
||||||
|
playbackRate: audioRef.current.playbackRate,
|
||||||
|
position: audioRef.current.currentTime
|
||||||
|
});
|
||||||
|
} catch (e) { console.error("MediaSession Position Error:", e); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Update refs for Media Session actions
|
// Update refs for Media Session actions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
playNextRef.current = playNext;
|
playNextRef.current = playNext;
|
||||||
@@ -958,24 +977,34 @@
|
|||||||
}
|
}
|
||||||
}, [currentSong]);
|
}, [currentSong]);
|
||||||
|
|
||||||
// Media Session Playback State
|
// Media Session Playback State & Position
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if ('mediaSession' in navigator) {
|
if ('mediaSession' in navigator) {
|
||||||
navigator.mediaSession.playbackState = isPlaying ? 'playing' : 'paused';
|
navigator.mediaSession.playbackState = isPlaying ? 'playing' : 'paused';
|
||||||
|
updateMediaSessionPosition();
|
||||||
}
|
}
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
|
|
||||||
|
// Update position when song loads
|
||||||
|
useEffect(() => {
|
||||||
|
const audio = audioRef.current;
|
||||||
|
const onLoadedMetadata = () => updateMediaSessionPosition();
|
||||||
|
audio.addEventListener('loadedmetadata', onLoadedMetadata);
|
||||||
|
return () => audio.removeEventListener('loadedmetadata', onLoadedMetadata);
|
||||||
|
}, []);
|
||||||
|
|
||||||
// --- Render ---
|
// --- Render ---
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col h-full bg-darker font-sans">
|
<div className="flex flex-col h-full bg-darker font-sans">
|
||||||
<SideDrawer
|
<SideDrawer
|
||||||
isOpen={showSideDrawer}
|
isOpen={showSideDrawer}
|
||||||
onClose={() => setShowSideDrawer(false)}
|
onClose={() => setShowSideDrawer(false)}
|
||||||
view={view}
|
view={view}
|
||||||
setView={setView}
|
setView={setView}
|
||||||
quality={quality}
|
quality={quality}
|
||||||
setQuality={setQuality}
|
setQuality={setQuality}
|
||||||
|
onClearCache={handleClearCache}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Top Navigation / Search Bar */}
|
{/* Top Navigation / Search Bar */}
|
||||||
|
|||||||
Reference in New Issue
Block a user