feat: offline content
This commit is contained in:
@@ -18,6 +18,19 @@ import {
|
||||
syncLocalToRemote,
|
||||
type ProgressEntry,
|
||||
} from "@/lib/audio-progress";
|
||||
import {
|
||||
primeOfflineAudio,
|
||||
offlineAudioURL,
|
||||
releaseOfflineAudio,
|
||||
} from "@/lib/offline";
|
||||
|
||||
/**
|
||||
* Resolve the media source for a track: prefer a saved offline object URL
|
||||
* (works with no network + full seeking) and fall back to the remote URL.
|
||||
*/
|
||||
function resolveSrc(url: string): string {
|
||||
return offlineAudioURL(trackKey(url)) ?? url;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
@@ -242,6 +255,13 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
currentIndexRef.current = currentIndex;
|
||||
}, [currentIndex]);
|
||||
|
||||
// Build object URLs for any audio saved offline so `resolveSrc` can prefer
|
||||
// them synchronously at play time (offline playback + full seeking).
|
||||
useEffect(() => {
|
||||
void primeOfflineAudio();
|
||||
return () => releaseOfflineAudio();
|
||||
}, []);
|
||||
|
||||
// --- Sync volume/muted to the <audio> element ---
|
||||
useEffect(() => {
|
||||
const audio = audioRef.current;
|
||||
@@ -334,7 +354,7 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
setDuration(0);
|
||||
setIsLoading(true);
|
||||
if (audio) {
|
||||
audio.src = nextTrack.url;
|
||||
audio.src = resolveSrc(nextTrack.url);
|
||||
audio.load();
|
||||
audio.play().catch((err) => {
|
||||
console.error("[AudioPlayer] Auto-play next failed:", err);
|
||||
@@ -409,7 +429,7 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
setDuration(0);
|
||||
setIsLoading(true);
|
||||
|
||||
audio.src = track.url;
|
||||
audio.src = resolveSrc(track.url);
|
||||
audio.load();
|
||||
audio.play().catch((err) => {
|
||||
console.error("[AudioPlayer] Play failed:", err);
|
||||
@@ -438,7 +458,7 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
setDuration(0);
|
||||
setIsLoading(true);
|
||||
|
||||
audio.src = track.url;
|
||||
audio.src = resolveSrc(track.url);
|
||||
audio.load();
|
||||
audio.play().catch((err) => {
|
||||
console.error("[AudioPlayer] PlayPlaylist failed:", err);
|
||||
@@ -545,7 +565,7 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
setDuration(0);
|
||||
setIsLoading(true);
|
||||
|
||||
audio.src = nextTrack.url;
|
||||
audio.src = resolveSrc(nextTrack.url);
|
||||
audio.load();
|
||||
audio.play().catch((err) => {
|
||||
console.error("[AudioPlayer] Next failed:", err);
|
||||
@@ -587,7 +607,7 @@ export function AudioPlayerProvider({ children }: { children: ReactNode }) {
|
||||
setDuration(0);
|
||||
setIsLoading(true);
|
||||
|
||||
audio.src = prevTrack.url;
|
||||
audio.src = resolveSrc(prevTrack.url);
|
||||
audio.load();
|
||||
audio.play().catch((err) => {
|
||||
console.error("[AudioPlayer] Previous failed:", err);
|
||||
|
||||
Reference in New Issue
Block a user